This commit is contained in:
parent
29b8d9644f
commit
21616e2723
|
@ -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),
|
||||
|
|
|
@ -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 })
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue