Implement if else

This commit is contained in:
Daniel M 2022-01-28 19:47:07 +01:00
parent 24f5aa30ea
commit d035724d20
4 changed files with 59 additions and 5 deletions

View File

@ -18,9 +18,9 @@
- [x] Declaration - [x] Declaration
- [x] Assignment - [x] Assignment
- [x] While loop `while X { ... }` - [x] While loop `while X { ... }`
- [ ] If else statement `if X { ... } else { ... }` - [x] If else statement `if X { ... } else { ... }`
- [ ] If Statement - [x] If Statement
- [ ] Else statement - [x] Else statement
- [ ] Line comments `//` - [ ] Line comments `//`
- [ ] Strings - [ ] Strings
- [ ] IO Intrinsics - [ ] IO Intrinsics

View File

@ -28,7 +28,7 @@ impl Interpreter {
Stmt::Let(name, rhs) => { Stmt::Let(name, rhs) => {
let result = self.resolve_expr(rhs); let result = self.resolve_expr(rhs);
self.vartable.insert(name, result); self.vartable.insert(name, result);
}, }
Stmt::While(condition, body) => { Stmt::While(condition, body) => {
loop { loop {
// Check condition // Check condition
@ -41,6 +41,13 @@ impl Interpreter {
self.run(body.clone()); 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);
}
}
} }
} }
} }

View File

@ -28,6 +28,12 @@ pub enum Token {
/// While (while) /// While (while)
While, While,
/// If (if)
If,
/// Else (else)
Else,
/// Assignment (single equal) (=) /// Assignment (single equal) (=)
Assign, Assign,
@ -184,6 +190,8 @@ impl<'a> Lexer<'a> {
"false" => tokens.push(Token::I64(0)), "false" => tokens.push(Token::I64(0)),
"let" => tokens.push(Token::Let), "let" => tokens.push(Token::Let),
"while" => tokens.push(Token::While), "while" => tokens.push(Token::While),
"if" => tokens.push(Token::If),
"else" => tokens.push(Token::Else),
_ => tokens.push(Token::Ident(ident)), _ => tokens.push(Token::Ident(ident)),
} }
} }

View File

@ -74,6 +74,7 @@ pub enum Stmt {
Expr(Expr), Expr(Expr),
Let(String, Expr), Let(String, Expr),
While(Expr, Ast), While(Expr, Ast),
If(Expr, Ast, Ast),
} }
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
@ -106,7 +107,8 @@ expr = expr_bor
stmt_expr = expr stmt_expr = expr
stmt_let = "let" IDENT "=" expr stmt_let = "let" IDENT "=" expr
stmt_while = "while" expr "{" (stmt)* "}" 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>> { struct Parser<T: Iterator<Item = Token>> {
@ -133,6 +135,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
Token::RBrace => break, Token::RBrace => break,
Token::Let => self.parse_let_stmt(), Token::Let => self.parse_let_stmt(),
Token::While => self.parse_while(), Token::While => self.parse_while(),
Token::If => self.parse_if(),
// By default try to parse an expression // By default try to parse an expression
_ => Stmt::Expr(self.parse_expr()), _ => Stmt::Expr(self.parse_expr()),
}; };
@ -143,6 +146,42 @@ impl<T: Iterator<Item = Token>> Parser<T> {
Ast { prog } 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 { fn parse_while(&mut self) -> Stmt {
if !matches!(self.next(), Token::While) { if !matches!(self.next(), Token::While) {
panic!("Error parsing while: Expected while token"); panic!("Error parsing while: Expected while token");