feat(tazjin/rlox): Parse variable assignment & access
Change-Id: I9894d76716d739e85a4757d9e658f884228e7f52 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2290 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									5010b79718
								
							
						
					
					
						commit
						0f9a7b3f86
					
				
					 3 changed files with 46 additions and 3 deletions
				
			
		| 
						 | 
					@ -5,6 +5,7 @@ pub enum ErrorKind {
 | 
				
			||||||
    UnmatchedParens,
 | 
					    UnmatchedParens,
 | 
				
			||||||
    ExpectedExpression(String),
 | 
					    ExpectedExpression(String),
 | 
				
			||||||
    ExpectedSemicolon,
 | 
					    ExpectedSemicolon,
 | 
				
			||||||
 | 
					    ExpectedVariableName,
 | 
				
			||||||
    TypeError(String),
 | 
					    TypeError(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,7 @@ fn eval<'a>(expr: &Expr<'a>) -> Result<Literal, Error> {
 | 
				
			||||||
        Expr::Grouping(grouping) => eval(&*grouping.0),
 | 
					        Expr::Grouping(grouping) => eval(&*grouping.0),
 | 
				
			||||||
        Expr::Unary(unary) => eval_unary(unary),
 | 
					        Expr::Unary(unary) => eval_unary(unary),
 | 
				
			||||||
        Expr::Binary(binary) => eval_binary(binary),
 | 
					        Expr::Binary(binary) => eval_binary(binary),
 | 
				
			||||||
 | 
					        Expr::Variable(_) => unimplemented!(),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,6 +123,7 @@ fn run_program<'a>(program: &Program<'a>) -> Result<(), Error> {
 | 
				
			||||||
    for decl in program {
 | 
					    for decl in program {
 | 
				
			||||||
        match decl {
 | 
					        match decl {
 | 
				
			||||||
            Declaration::Stmt(stmt) => run_stmt(stmt)?,
 | 
					            Declaration::Stmt(stmt) => run_stmt(stmt)?,
 | 
				
			||||||
 | 
					            Declaration::Var(_var) => unimplemented!(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,12 +34,16 @@ pub struct Unary<'a> {
 | 
				
			||||||
    pub right: Box<Expr<'a>>,
 | 
					    pub right: Box<Expr<'a>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct Variable<'a>(pub Token<'a>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum Expr<'a> {
 | 
					pub enum Expr<'a> {
 | 
				
			||||||
    Binary(Binary<'a>),
 | 
					    Binary(Binary<'a>),
 | 
				
			||||||
    Grouping(Grouping<'a>),
 | 
					    Grouping(Grouping<'a>),
 | 
				
			||||||
    Literal(Literal),
 | 
					    Literal(Literal),
 | 
				
			||||||
    Unary(Unary<'a>),
 | 
					    Unary(Unary<'a>),
 | 
				
			||||||
 | 
					    Variable(Variable<'a>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
| 
						 | 
					@ -48,9 +52,17 @@ pub enum Statement<'a> {
 | 
				
			||||||
    Print(Expr<'a>),
 | 
					    Print(Expr<'a>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Not to be confused with `Variable`, which is for access.
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct Var<'a> {
 | 
				
			||||||
 | 
					    pub name: Token<'a>,
 | 
				
			||||||
 | 
					    pub initialiser: Option<Expr<'a>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum Declaration<'a> {
 | 
					pub enum Declaration<'a> {
 | 
				
			||||||
    Stmt(Statement<'a>),
 | 
					    Stmt(Statement<'a>),
 | 
				
			||||||
 | 
					    Var(Var<'a>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Program<'a> = Vec<Declaration<'a>>;
 | 
					pub type Program<'a> = Vec<Declaration<'a>>;
 | 
				
			||||||
| 
						 | 
					@ -93,9 +105,36 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
    // recursive-descent parser functions
 | 
					    // recursive-descent parser functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn declaration(&mut self) -> DeclResult<'a> {
 | 
					    fn declaration(&mut self) -> DeclResult<'a> {
 | 
				
			||||||
 | 
					        if self.match_token(&[TokenKind::Var]) {
 | 
				
			||||||
 | 
					            return self.var_declaration();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Declaration::Stmt(self.statement()?))
 | 
					        Ok(Declaration::Stmt(self.statement()?))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn var_declaration(&mut self) -> DeclResult<'a> {
 | 
				
			||||||
 | 
					        // Since `TokenKind::Identifier` carries data, we can't use
 | 
				
			||||||
 | 
					        // `consume`.
 | 
				
			||||||
 | 
					        if let TokenKind::Identifier(_) = self.peek().kind {
 | 
				
			||||||
 | 
					            let mut var = Var {
 | 
				
			||||||
 | 
					                name: self.advance(),
 | 
				
			||||||
 | 
					                initialiser: None,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.match_token(&[TokenKind::Equal]) {
 | 
				
			||||||
 | 
					                var.initialiser = Some(self.expression()?);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.consume(&TokenKind::Semicolon, ErrorKind::ExpectedSemicolon)?;
 | 
				
			||||||
 | 
					            return Ok(Declaration::Var(var));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Err(Error {
 | 
				
			||||||
 | 
					            line: self.peek().line,
 | 
				
			||||||
 | 
					            kind: ErrorKind::ExpectedVariableName,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn statement(&mut self) -> StmtResult<'a> {
 | 
					    fn statement(&mut self) -> StmtResult<'a> {
 | 
				
			||||||
        if self.match_token(&[TokenKind::Print]) {
 | 
					        if self.match_token(&[TokenKind::Print]) {
 | 
				
			||||||
            self.print_statement()
 | 
					            self.print_statement()
 | 
				
			||||||
| 
						 | 
					@ -173,6 +212,8 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
                return Ok(Expr::Grouping(Grouping(Box::new(expr))));
 | 
					                return Ok(Expr::Grouping(Grouping(Box::new(expr))));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            TokenKind::Identifier(_) => return Ok(Expr::Variable(Variable(next))),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            unexpected => {
 | 
					            unexpected => {
 | 
				
			||||||
                eprintln!("encountered {:?}", unexpected);
 | 
					                eprintln!("encountered {:?}", unexpected);
 | 
				
			||||||
                return Err(Error {
 | 
					                return Err(Error {
 | 
				
			||||||
| 
						 | 
					@ -225,10 +266,9 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
        &self.tokens[self.current - 1]
 | 
					        &self.tokens[self.current - 1]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn consume(&mut self, kind: &TokenKind, err: ErrorKind) -> Result<(), Error> {
 | 
					    fn consume(&mut self, kind: &TokenKind, err: ErrorKind) -> Result<Token, Error> {
 | 
				
			||||||
        if self.check_token(kind) {
 | 
					        if self.check_token(kind) {
 | 
				
			||||||
            self.advance();
 | 
					            return Ok(self.advance());
 | 
				
			||||||
            return Ok(());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Err(Error {
 | 
					        Err(Error {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue