This commit is contained in:
minish 2025-07-11 03:02:03 -04:00
parent 29b8d9644f
commit 21616e2723
Signed by: min
SSH Key Fingerprint: SHA256:h4k7JNrfe1dzv1WE3oGVeAY9DPSZXIu3/j89+6DtHWE
3 changed files with 29 additions and 3 deletions

View File

@ -47,6 +47,8 @@ pub enum Token {
Comma,
Eol,
If,
Else,
Return,
Not,
@ -68,6 +70,7 @@ pub enum Token {
pub enum Precedence {
Min,
Return,
If,
Assign,
Logical,
Equality,
@ -86,6 +89,7 @@ impl Token {
pub fn prefix_precedence(&self) -> Option<Precedence> {
Some(match self {
Token::Return => Precedence::Return,
Token::If => Precedence::If,
Token::Minus | Token::Not => Precedence::NegateNot,
_ => return None,
})
@ -192,6 +196,8 @@ where
match word.as_str() {
"return" => Token::Return,
"if" => Token::If,
"else" => Token::Else,
"true" => Token::Literal(Literal::Boolean(true)),
"false" => Token::Literal(Literal::Boolean(false)),
"nil" => Token::Literal(Literal::Nil),

View File

@ -12,6 +12,7 @@ pub enum Expr {
// Runtime datatypes
Block(Block),
// Control flow
If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
Return(Box<Expr>),
Call(Box<Expr>, Vec<Expr>),
// Unary operations
@ -137,6 +138,19 @@ where
Token::Minus => Expr::Negate(rhs),
Token::Not => Expr::Not(rhs),
Token::Return => Expr::Return(rhs),
Token::If => {
// parse the true case
let true_case = self.parse_expr(Precedence::Min, false)?;
// and maybe a false case
let false_case = matches!(self.try_peek(), Ok(Token::Else))
.then(|| {
self.eat();
self.parse_expr(Precedence::Min, false)
})
.transpose()?;
// pack
Expr::If(rhs, true_case, false_case)
}
_ => unreachable!(),
})
}
@ -238,15 +252,14 @@ where
match self.try_peek() {
// end (block)
Ok(Token::CurlyClose) if in_block => break,
// end (stream) lpwkey idk if this is a good way to check for error
// need to add error nodes anyway so whatever
// end (stream)
Err(ParseError::UnexpectedEnd) if !in_block => break,
// try to parse expr
Ok(_) => exprs.push(*self.parse_expr(Precedence::Min, false)?),
// invalid
Err(err) => return Err(err),
Err(_) => unreachable!(),
}
}
Ok(Block { exprs })

View File

@ -31,6 +31,13 @@ fn fmt_expr(e: Expr, depth: usize) -> String {
result.push(')');
result
}
Expr::If(c, t, f) => {
let mut result = format!("if ({}) ({})", fmt_expr(*c, depth), fmt_expr(*t, depth));
if let Some(f) = f {
result.push_str(&format!(" else ({})", fmt_expr(*f, depth)));
}
result
}
Expr::Return(l) => format!("return {}", fmt_expr(*l, depth)),
Expr::Block(b) => {
let mut result = String::new();