Implement if else
This commit is contained in:
parent
24f5aa30ea
commit
d035724d20
@ -18,9 +18,9 @@
|
||||
- [x] Declaration
|
||||
- [x] Assignment
|
||||
- [x] While loop `while X { ... }`
|
||||
- [ ] If else statement `if X { ... } else { ... }`
|
||||
- [ ] If Statement
|
||||
- [ ] Else statement
|
||||
- [x] If else statement `if X { ... } else { ... }`
|
||||
- [x] If Statement
|
||||
- [x] Else statement
|
||||
- [ ] Line comments `//`
|
||||
- [ ] Strings
|
||||
- [ ] IO Intrinsics
|
||||
|
||||
@ -28,7 +28,7 @@ impl Interpreter {
|
||||
Stmt::Let(name, rhs) => {
|
||||
let result = self.resolve_expr(rhs);
|
||||
self.vartable.insert(name, result);
|
||||
},
|
||||
}
|
||||
Stmt::While(condition, body) => {
|
||||
loop {
|
||||
// Check condition
|
||||
@ -41,6 +41,13 @@ impl Interpreter {
|
||||
self.run(body.clone());
|
||||
}
|
||||
}
|
||||
Stmt::If(condition, body_if, body_else) => {
|
||||
if matches!(self.resolve_expr(condition), Value::I64(0)) {
|
||||
self.run(body_else);
|
||||
} else {
|
||||
self.run(body_if);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,12 @@ pub enum Token {
|
||||
/// While (while)
|
||||
While,
|
||||
|
||||
/// If (if)
|
||||
If,
|
||||
|
||||
/// Else (else)
|
||||
Else,
|
||||
|
||||
/// Assignment (single equal) (=)
|
||||
Assign,
|
||||
|
||||
@ -184,6 +190,8 @@ impl<'a> Lexer<'a> {
|
||||
"false" => tokens.push(Token::I64(0)),
|
||||
"let" => tokens.push(Token::Let),
|
||||
"while" => tokens.push(Token::While),
|
||||
"if" => tokens.push(Token::If),
|
||||
"else" => tokens.push(Token::Else),
|
||||
_ => tokens.push(Token::Ident(ident)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ pub enum Stmt {
|
||||
Expr(Expr),
|
||||
Let(String, Expr),
|
||||
While(Expr, Ast),
|
||||
If(Expr, Ast, Ast),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
@ -106,7 +107,8 @@ expr = expr_bor
|
||||
stmt_expr = expr
|
||||
stmt_let = "let" IDENT "=" expr
|
||||
stmt_while = "while" expr "{" (stmt)* "}"
|
||||
stmt = stmt_expr | stmt_let | stmt_while
|
||||
stmt_if = "if" expr "{" (stmt)* "}" ( "else" "{" (stmt)* "}" )
|
||||
stmt = stmt_expr | stmt_let | stmt_while | stmt_if
|
||||
*/
|
||||
|
||||
struct Parser<T: Iterator<Item = Token>> {
|
||||
@ -133,6 +135,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Token::RBrace => break,
|
||||
Token::Let => self.parse_let_stmt(),
|
||||
Token::While => self.parse_while(),
|
||||
Token::If => self.parse_if(),
|
||||
// By default try to parse an expression
|
||||
_ => Stmt::Expr(self.parse_expr()),
|
||||
};
|
||||
@ -143,6 +146,42 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Ast { prog }
|
||||
}
|
||||
|
||||
fn parse_if(&mut self) -> Stmt {
|
||||
if !matches!(self.next(), Token::If) {
|
||||
panic!("Error parsing if: Expected if token");
|
||||
}
|
||||
|
||||
let condition = self.parse_expr();
|
||||
|
||||
if !matches!(self.next(), Token::LBrace) {
|
||||
panic!("Error parsing if: Expected '{{' token");
|
||||
}
|
||||
|
||||
let body_if = self.parse();
|
||||
|
||||
if !matches!(self.next(), Token::RBrace) {
|
||||
panic!("Error parsing if: Expected '}}' token");
|
||||
}
|
||||
|
||||
let mut body_else = Ast { prog: Vec::new() };
|
||||
|
||||
if matches!(self.peek(), Token::Else) {
|
||||
self.next();
|
||||
|
||||
if !matches!(self.next(), Token::LBrace) {
|
||||
panic!("Error parsing else: Expected '{{' token");
|
||||
}
|
||||
|
||||
body_else = self.parse();
|
||||
|
||||
if !matches!(self.next(), Token::RBrace) {
|
||||
panic!("Error parsing else: Expected '}}' token");
|
||||
}
|
||||
}
|
||||
|
||||
Stmt::If(condition, body_if, body_else)
|
||||
}
|
||||
|
||||
fn parse_while(&mut self) -> Stmt {
|
||||
if !matches!(self.next(), Token::While) {
|
||||
panic!("Error parsing while: Expected while token");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user