This commit is contained in:
parent
29b8d9644f
commit
21616e2723
|
@ -47,6 +47,8 @@ pub enum Token {
|
||||||
Comma,
|
Comma,
|
||||||
Eol,
|
Eol,
|
||||||
|
|
||||||
|
If,
|
||||||
|
Else,
|
||||||
Return,
|
Return,
|
||||||
|
|
||||||
Not,
|
Not,
|
||||||
|
@ -68,6 +70,7 @@ pub enum Token {
|
||||||
pub enum Precedence {
|
pub enum Precedence {
|
||||||
Min,
|
Min,
|
||||||
Return,
|
Return,
|
||||||
|
If,
|
||||||
Assign,
|
Assign,
|
||||||
Logical,
|
Logical,
|
||||||
Equality,
|
Equality,
|
||||||
|
@ -86,6 +89,7 @@ impl Token {
|
||||||
pub fn prefix_precedence(&self) -> Option<Precedence> {
|
pub fn prefix_precedence(&self) -> Option<Precedence> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Token::Return => Precedence::Return,
|
Token::Return => Precedence::Return,
|
||||||
|
Token::If => Precedence::If,
|
||||||
Token::Minus | Token::Not => Precedence::NegateNot,
|
Token::Minus | Token::Not => Precedence::NegateNot,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
|
@ -192,6 +196,8 @@ where
|
||||||
|
|
||||||
match word.as_str() {
|
match word.as_str() {
|
||||||
"return" => Token::Return,
|
"return" => Token::Return,
|
||||||
|
"if" => Token::If,
|
||||||
|
"else" => Token::Else,
|
||||||
"true" => Token::Literal(Literal::Boolean(true)),
|
"true" => Token::Literal(Literal::Boolean(true)),
|
||||||
"false" => Token::Literal(Literal::Boolean(false)),
|
"false" => Token::Literal(Literal::Boolean(false)),
|
||||||
"nil" => Token::Literal(Literal::Nil),
|
"nil" => Token::Literal(Literal::Nil),
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub enum Expr {
|
||||||
// Runtime datatypes
|
// Runtime datatypes
|
||||||
Block(Block),
|
Block(Block),
|
||||||
// Control flow
|
// Control flow
|
||||||
|
If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
|
||||||
Return(Box<Expr>),
|
Return(Box<Expr>),
|
||||||
Call(Box<Expr>, Vec<Expr>),
|
Call(Box<Expr>, Vec<Expr>),
|
||||||
// Unary operations
|
// Unary operations
|
||||||
|
@ -137,6 +138,19 @@ where
|
||||||
Token::Minus => Expr::Negate(rhs),
|
Token::Minus => Expr::Negate(rhs),
|
||||||
Token::Not => Expr::Not(rhs),
|
Token::Not => Expr::Not(rhs),
|
||||||
Token::Return => Expr::Return(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!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -238,15 +252,14 @@ where
|
||||||
match self.try_peek() {
|
match self.try_peek() {
|
||||||
// end (block)
|
// end (block)
|
||||||
Ok(Token::CurlyClose) if in_block => break,
|
Ok(Token::CurlyClose) if in_block => break,
|
||||||
// end (stream) lpwkey idk if this is a good way to check for error
|
// end (stream)
|
||||||
// need to add error nodes anyway so whatever
|
|
||||||
Err(ParseError::UnexpectedEnd) if !in_block => break,
|
Err(ParseError::UnexpectedEnd) if !in_block => break,
|
||||||
|
|
||||||
// try to parse expr
|
// try to parse expr
|
||||||
Ok(_) => exprs.push(*self.parse_expr(Precedence::Min, false)?),
|
Ok(_) => exprs.push(*self.parse_expr(Precedence::Min, false)?),
|
||||||
|
|
||||||
// invalid
|
// invalid
|
||||||
Err(err) => return Err(err),
|
Err(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Block { exprs })
|
Ok(Block { exprs })
|
||||||
|
|
|
@ -31,6 +31,13 @@ fn fmt_expr(e: Expr, depth: usize) -> String {
|
||||||
result.push(')');
|
result.push(')');
|
||||||
result
|
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::Return(l) => format!("return {}", fmt_expr(*l, depth)),
|
||||||
Expr::Block(b) => {
|
Expr::Block(b) => {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
|
Loading…
Reference in New Issue