Merge remote-tracking branch 'refs/remotes/origin/compiler' into compiler

This commit is contained in:
2025-11-14 23:37:57 +00:00
+203 -43
View File
@@ -1,4 +1,4 @@
use crate::expect_type; use crate::expect_tt;
use crate::lexer::Token; use crate::lexer::Token;
pub struct Parser { pub struct Parser {
@@ -10,7 +10,7 @@ pub struct Parser {
impl Parser { impl Parser {
pub fn new(tokens: Vec<Token>) -> Self { pub fn new(tokens: Vec<Token>) -> Self {
Self { Self {
ast: Node::Scope { ast: Node::Block {
children: Vec::new(), children: Vec::new(),
}, },
idx: 0, idx: 0,
@@ -19,13 +19,17 @@ impl Parser {
} }
pub fn parse(&mut self) -> Result<Node, CompileError> { pub fn parse(&mut self) -> Result<Node, CompileError> {
self.parse_block()
}
fn parse_block(&mut self) -> Result<Node, CompileError> {
let mut statements = Vec::new(); let mut statements = Vec::new();
while let Some(_) = self.peek_next() { while self.peek_next().is_ok() {
statements.push(self.parse_statement()?); statements.push(self.parse_statement()?);
} }
Ok(Node::Scope { Ok(Node::Block {
children: statements, children: statements,
}) })
} }
@@ -35,11 +39,11 @@ impl Parser {
let left = if let Ok(typed_var) = self.parse_typed_var() { let left = if let Ok(typed_var) = self.parse_typed_var() {
Box::new(typed_var) Box::new(typed_var)
} else { } else {
let tok = expect_type!(self.next()?, Identifier)?; let tok = expect_tt!(self.next()?, Identifier)?;
Box::new(Node::Terminal { value: tok }) Box::new(Node::Terminal { value: tok })
}; };
let _ = expect_type!(self.next()?, Assign)?; let _ = expect_tt!(self.next()?, Assign)?;
let right = Box::new(self.parse_expression()?); let right = Box::new(self.parse_expression()?);
@@ -47,17 +51,144 @@ impl Parser {
} }
fn parse_typed_var(&mut self) -> Result<Node, CompileError> { fn parse_typed_var(&mut self) -> Result<Node, CompileError> {
let name = expect_type!(self.next()?, Identifier)?; let name = expect_tt!(self.next()?, Identifier)?;
let _ = expect_type!(self.next()?, Colon)?; let _ = expect_tt!(self.next()?, Colon)?;
let type_ = expect_type!(self.next()?, Identifier)?; let type_ = expect_tt!(self.next()?, Identifier)?;
Ok(Node::TypedVar { name, type_ }) Ok(Node::TypedVar { name, type_ })
} }
fn parse_expression(&mut self) -> Result<Node, CompileError> { fn parse_expression(&mut self) -> Result<Node, CompileError> {
if expect_tt!(self.peek_next()?, Pipe).is_ok() {
return self.parse_func();
}
if expect_tt!(self.peek_next()?, If).is_ok() {
return self.parse_if();
}
if expect_tt!(self.peek_next()?, Loop).is_ok() {
return self.parse_loop();
}
if expect_tt!(self.peek_next()?, Identifier, String, Number).is_ok() {
let left = Node::Terminal {
value: self.next()?,
};
if expect_tt!(
self.next()?,
Plus,
Minus,
Star,
Slash,
EqualEqual,
BangEqual,
Less,
LessEqual,
Greater,
GreaterEqual
)
.is_err()
{
return Ok(left);
}
let operator = self.next()?;
let right = Box::new(self.parse_expression()?);
return Ok(Node::BinaryOp {
left: Box::new(left),
op: operator,
right,
});
}
Err(CompileError::Generic) Err(CompileError::Generic)
} }
fn parse_func(&mut self) -> Result<Node, CompileError> {
// left arg delimiter
let _ = expect_tt!(self.next()?, Pipe)?;
// parse args
let mut args = Vec::new();
while expect_tt!(self.peek_next()?, Identifier).is_ok() {
// add a typed var
let arg = self.parse_typed_var()?;
args.push(arg);
}
// right arg delimiter
let _ = expect_tt!(self.next()?, Pipe)?;
// ensure we have an open brace
let _ = expect_tt!(self.next()?, LeftBrace)?;
// parse the body
let body = Box::new(self.parse_block()?);
// ensure we have a close brace
let _ = expect_tt!(self.next()?, RightBrace)?;
Ok(Node::FunctionDef { params: args, body })
}
fn parse_loop(&mut self) -> Result<Node, CompileError> {
let _ = expect_tt!(self.next()?, Loop)?;
// ensure we have an open brace
let _ = expect_tt!(self.next()?, LeftBrace)?;
// parse the body
let body = Box::new(self.parse_block()?);
// ensure we have a close brace
let _ = expect_tt!(self.next()?, RightBrace)?;
Ok(Node::Loop { body })
}
fn parse_if(&mut self) -> Result<Node, CompileError> {
let _ = expect_tt!(self.next()?, If)?;
// parse condition (expr)
let condition = Box::new(self.parse_expression()?);
// ensure we have an open brace
let _ = expect_tt!(self.next()?, LeftBrace)?;
// parse the "then" branch (expr/statement)
let then_branch = Box::new(self.parse_expression()?);
// ensure we have a close brace
let _ = expect_tt!(self.next()?, RightBrace)?;
// if there is an else branch, we include it in the statement
let else_branch = self.parse_else()?.map(Box::new);
Ok(Node::If {
condition,
then_branch,
else_branch,
})
}
fn parse_else(&mut self) -> Result<Option<Node>, CompileError> {
// if there is no else branch, return None.
if expect_tt!(self.peek_next()?, Else).is_err() {
return Ok(None);
}
let _ = self.next()?;
if expect_tt!(self.peek_next()?, If).is_ok() {
Ok(Some(self.parse_if()?))
} else {
Ok(Some(self.parse_expression()?))
}
}
fn next(&mut self) -> Result<Token, CompileError> { fn next(&mut self) -> Result<Token, CompileError> {
if self.idx >= self.tokens.len() { if self.idx >= self.tokens.len() {
return Err(CompileError::UnexpectedEOF); return Err(CompileError::UnexpectedEOF);
@@ -69,53 +200,54 @@ impl Parser {
Ok(token) Ok(token)
} }
fn peek_next(&mut self) -> Option<Token> { fn peek_next(&mut self) -> Result<Token, CompileError> {
if self.idx >= self.tokens.len() { if self.idx >= self.tokens.len() {
return None; return Err(CompileError::UnexpectedEOF);
} }
Some(self.tokens[self.idx].clone()) Ok(self.tokens[self.idx].clone())
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Node { pub enum Node {
Scope { /// A scope, which is a list of child nodes that are evaluated in order.
children: Vec<Node>, Block { children: Vec<Node> },
},
Terminal { /// A leaf node with a value.
value: Token, Terminal { value: Token },
},
UnaryOp { /// A unary operator with a right operand.
op: Token, UnaryOp { op: Token, right: Box<Node> },
right: Box<Node>,
}, /// A binary operator with a left and right operand.
BinaryOp { BinaryOp {
left: Box<Node>, left: Box<Node>,
op: Token, op: Token,
right: Box<Node>, right: Box<Node>,
}, },
Statement {
left: Box<Node>, /// A statement, consisting of a value to assign to, and an expression.
right: Box<Node>, Statement { left: Box<Node>, right: Box<Node> },
},
/// An if expression, which evaluates to either the then branch or the else branch.
If { If {
condition: Box<Node>, condition: Box<Node>,
then_branch: Box<Node>, then_branch: Box<Node>,
else_branch: Option<Box<Node>>, else_branch: Option<Box<Node>>,
}, },
FunctionDef {
params: Vec<Node>, /// A loop expression, which evaluates to the last value of the loop.
body: Box<Node>, /// a loop can be exited with the break keyword.
}, Loop { body: Box<Node> },
TypedVar {
name: Token, /// A function definition. ``` | param: type .. | -> ret_type { body }```
type_: Token, FunctionDef { params: Vec<Node>, body: Box<Node> },
},
TypeDef { /// A typed variable definition: ```val: Type```
name: Token, TypedVar { name: Token, type_: Token },
fields: Vec<Node>,
}, /// A type definition, which is a list of fields. ```type MyType { field: Type }```
TypeDef { name: Token, fields: Vec<Node> },
} }
#[derive(Debug)] #[derive(Debug)]
@@ -126,16 +258,44 @@ pub enum CompileError {
} }
#[macro_export] #[macro_export]
macro_rules! expect_type { macro_rules! expect_tt {
($token:expr, $($variant:ident),+) => {{ ($token:expr, $($variant:ident),+) => {{
match $token.tt() { let tt = $token.tt().to_string();
println!("CASE");
println!("TOK {:?}", $token);
println!("TT {}", tt);
let mut vs = String::new();
$(
let s = stringify!($variant);
vs.push_str(s);
vs.push_str("|");
)+
match tt.as_str() {
$( $(
stringify!($variant) => Ok($token.clone()), stringify!($variant) => Ok($token.clone()),
)+ )+
_ => { _ => {
// return an expected token error println!("EXPECTED!! {} [{}]", tt, vs);
let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | ")); let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | "));
Err(CompileError::ExpectedToken {
expected,
found: $token.clone(),
})
}
}
}};
}
#[macro_export]
macro_rules! expect_value {
($token:expr, $variant:expr) => {{
match $token {
$variant(x) => Ok(x),
_ => {
let expected = format!("[{}]")
Err(CompileError::ExpectedToken { Err(CompileError::ExpectedToken {
expected, expected,
found: $token.clone(), found: $token.clone(),