feat(tazjin/rlox): Parse & interpret while statements
Change-Id: Iee772274de95dfd6a6d4af973402859aeda17b1d Reviewed-on: https://cl.tvl.fyi/c/depot/+/2325 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
parent
0a0335ae6c
commit
d47e55ba4d
2 changed files with 40 additions and 0 deletions
|
@ -128,6 +128,7 @@ impl Interpreter {
|
||||||
Statement::Var(var) => return self.interpret_var(var),
|
Statement::Var(var) => return self.interpret_var(var),
|
||||||
Statement::Block(block) => return self.interpret_block(block),
|
Statement::Block(block) => return self.interpret_block(block),
|
||||||
Statement::If(if_stmt) => return self.interpret_if(if_stmt),
|
Statement::If(if_stmt) => return self.interpret_if(if_stmt),
|
||||||
|
Statement::While(while_stmt) => return self.interpret_while(while_stmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -172,6 +173,14 @@ impl Interpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn interpret_while<'a>(&mut self, stmt: &parser::While<'a>) -> Result<(), Error> {
|
||||||
|
while eval_truthy(&self.eval(&stmt.condition)?) {
|
||||||
|
self.interpret_stmt(&stmt.body)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn eval<'a>(&mut self, expr: &Expr<'a>) -> Result<Literal, Error> {
|
fn eval<'a>(&mut self, expr: &Expr<'a>) -> Result<Literal, Error> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Assign(assign) => self.eval_assign(assign),
|
Expr::Assign(assign) => self.eval_assign(assign),
|
||||||
|
|
|
@ -77,6 +77,12 @@ pub struct If<'a> {
|
||||||
pub else_branch: Option<Box<Statement<'a>>>,
|
pub else_branch: Option<Box<Statement<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct While<'a> {
|
||||||
|
pub condition: Expr<'a>,
|
||||||
|
pub body: Box<Statement<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
pub type Block<'a> = Vec<Statement<'a>>;
|
pub type Block<'a> = Vec<Statement<'a>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -86,6 +92,7 @@ pub enum Statement<'a> {
|
||||||
Var(Var<'a>),
|
Var(Var<'a>),
|
||||||
Block(Block<'a>),
|
Block(Block<'a>),
|
||||||
If(If<'a>),
|
If(If<'a>),
|
||||||
|
While(While<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parser
|
// Parser
|
||||||
|
@ -99,8 +106,11 @@ declaration → varDecl
|
||||||
statement → exprStmt
|
statement → exprStmt
|
||||||
| ifStmt
|
| ifStmt
|
||||||
| printStmt
|
| printStmt
|
||||||
|
| whileStmt
|
||||||
| block ;
|
| block ;
|
||||||
|
|
||||||
|
whileStmt → "while" "(" expression ")" statement ;
|
||||||
|
|
||||||
exprStmt → expression ";" ;
|
exprStmt → expression ";" ;
|
||||||
|
|
||||||
ifStmt → "if" "(" expression ")" statement
|
ifStmt → "if" "(" expression ")" statement
|
||||||
|
@ -172,6 +182,8 @@ impl<'a> Parser<'a> {
|
||||||
self.block_statement()
|
self.block_statement()
|
||||||
} else if self.match_token(&[TokenKind::If]) {
|
} else if self.match_token(&[TokenKind::If]) {
|
||||||
self.if_statement()
|
self.if_statement()
|
||||||
|
} else if self.match_token(&[TokenKind::While]) {
|
||||||
|
self.while_statement()
|
||||||
} else {
|
} else {
|
||||||
self.expr_statement()
|
self.expr_statement()
|
||||||
}
|
}
|
||||||
|
@ -221,6 +233,25 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Statement::If(stmt))
|
Ok(Statement::If(stmt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn while_statement(&mut self) -> StmtResult<'a> {
|
||||||
|
self.consume(
|
||||||
|
&TokenKind::LeftParen,
|
||||||
|
ErrorKind::ExpectedToken("Expected '(' after 'while'"),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let condition = self.expression()?;
|
||||||
|
|
||||||
|
self.consume(
|
||||||
|
&TokenKind::RightParen,
|
||||||
|
ErrorKind::ExpectedToken("Expected ')' after 'while'"),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Statement::While(While {
|
||||||
|
condition,
|
||||||
|
body: Box::new(self.statement()?),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn expr_statement(&mut self) -> StmtResult<'a> {
|
fn expr_statement(&mut self) -> StmtResult<'a> {
|
||||||
let expr = self.expression()?;
|
let expr = self.expression()?;
|
||||||
self.consume(&TokenKind::Semicolon, ErrorKind::ExpectedSemicolon)?;
|
self.consume(&TokenKind::Semicolon, ErrorKind::ExpectedSemicolon)?;
|
||||||
|
|
Loading…
Reference in a new issue