rust macros make me want to unalive.

This commit is contained in:
2025-07-01 01:08:37 +01:00
parent 2582ad10fa
commit b33fdbfeec
+203 -43
View File
@@ -1,4 +1,4 @@
use crate::expect_type;
use crate::expect_tt;
use crate::lexer::Token;
pub struct Parser {
@@ -10,7 +10,7 @@ pub struct Parser {
impl Parser {
pub fn new(tokens: Vec<Token>) -> Self {
Self {
ast: Node::Scope {
ast: Node::Block {
children: Vec::new(),
},
idx: 0,
@@ -19,13 +19,17 @@ impl Parser {
}
pub fn parse(&mut self) -> Result<Node, CompileError> {
self.parse_block()
}
fn parse_block(&mut self) -> Result<Node, CompileError> {
let mut statements = Vec::new();
while let Some(_) = self.peek_next() {
while self.peek_next().is_ok() {
statements.push(self.parse_statement()?);
}
Ok(Node::Scope {
Ok(Node::Block {
children: statements,
})
}
@@ -35,11 +39,11 @@ impl Parser {
let left = if let Ok(typed_var) = self.parse_typed_var() {
Box::new(typed_var)
} else {
let tok = expect_type!(self.next()?, Identifier)?;
let tok = expect_tt!(self.next()?, Identifier)?;
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()?);
@@ -47,17 +51,144 @@ impl Parser {
}
fn parse_typed_var(&mut self) -> Result<Node, CompileError> {
let name = expect_type!(self.next()?, Identifier)?;
let _ = expect_type!(self.next()?, Colon)?;
let type_ = expect_type!(self.next()?, Identifier)?;
let name = expect_tt!(self.next()?, Identifier)?;
let _ = expect_tt!(self.next()?, Colon)?;
let type_ = expect_tt!(self.next()?, Identifier)?;
Ok(Node::TypedVar { name, type_ })
}
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)
}
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> {
if self.idx >= self.tokens.len() {
return Err(CompileError::UnexpectedEOF);
@@ -69,53 +200,54 @@ impl Parser {
Ok(token)
}
fn peek_next(&mut self) -> Option<Token> {
fn peek_next(&mut self) -> Result<Token, CompileError> {
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)]
pub enum Node {
Scope {
children: Vec<Node>,
},
Terminal {
value: Token,
},
UnaryOp {
op: Token,
right: Box<Node>,
},
/// A scope, which is a list of child nodes that are evaluated in order.
Block { children: Vec<Node> },
/// A leaf node with a value.
Terminal { value: Token },
/// A unary operator with a right operand.
UnaryOp { op: Token, right: Box<Node> },
/// A binary operator with a left and right operand.
BinaryOp {
left: Box<Node>,
op: Token,
right: Box<Node>,
},
Statement {
left: Box<Node>,
right: Box<Node>,
},
/// A statement, consisting of a value to assign to, and an expression.
Statement { left: Box<Node>, right: Box<Node> },
/// An if expression, which evaluates to either the then branch or the else branch.
If {
condition: Box<Node>,
then_branch: Box<Node>,
else_branch: Option<Box<Node>>,
},
FunctionDef {
params: Vec<Node>,
body: Box<Node>,
},
TypedVar {
name: Token,
type_: Token,
},
TypeDef {
name: Token,
fields: Vec<Node>,
},
/// A loop expression, which evaluates to the last value of the loop.
/// a loop can be exited with the break keyword.
Loop { body: Box<Node> },
/// A function definition. ``` | param: type .. | -> ret_type { body }```
FunctionDef { params: Vec<Node>, body: Box<Node> },
/// A typed variable definition: ```val: Type```
TypedVar { name: Token, type_: Token },
/// A type definition, which is a list of fields. ```type MyType { field: Type }```
TypeDef { name: Token, fields: Vec<Node> },
}
#[derive(Debug)]
@@ -126,16 +258,44 @@ pub enum CompileError {
}
#[macro_export]
macro_rules! expect_type {
macro_rules! expect_tt {
($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()),
)+
_ => {
// return an expected token error
println!("EXPECTED!! {} [{}]", tt, vs);
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 {
expected,
found: $token.clone(),