diff options
author | Vincent Ambo <mail@tazj.in> | 2020-12-31T13·31+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2020-12-31T14·32+0000 |
commit | cc958e67309593b24634816c0c29d90eda84b3ed (patch) | |
tree | b909bd04999db8c5a708f64adf71c8c504fb2511 /users/tazjin/rlox/src/parser.rs | |
parent | 8ab66f1689dade7c346d5a3b51b87194716e03a7 (diff) |
feat(tazjin/rlox): Implement mutable variable assignment r/2033
Change-Id: I56db10a5ac26958ae27a8d4c8fa7b8f8285bc7e1 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2299 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src/parser.rs')
-rw-r--r-- | users/tazjin/rlox/src/parser.rs | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs index 3f1dda6e39cf..b46e570994c4 100644 --- a/users/tazjin/rlox/src/parser.rs +++ b/users/tazjin/rlox/src/parser.rs @@ -11,6 +11,12 @@ use crate::scanner::{Token, TokenKind}; // AST #[derive(Debug)] +pub struct Assign<'a> { + pub name: Token<'a>, + pub value: Box<Expr<'a>>, +} + +#[derive(Debug)] pub struct Binary<'a> { pub left: Box<Expr<'a>>, pub operator: Token<'a>, @@ -34,11 +40,13 @@ pub struct Unary<'a> { pub right: Box<Expr<'a>>, } +// Not to be confused with `Var`, which is for assignment. #[derive(Debug)] pub struct Variable<'a>(pub Token<'a>); #[derive(Debug)] pub enum Expr<'a> { + Assign(Assign<'a>), Binary(Binary<'a>), Grouping(Grouping<'a>), Literal(Literal), @@ -81,7 +89,9 @@ statement → exprStmt exprStmt → expression ";" ; printStmt → "print" expression ";" ; -expression → equality ; +expression → assignment ; +assignment → IDENTIFIER "=" assignment + | equality ; equality → comparison ( ( "!=" | "==" ) comparison )* ; comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ; term → factor ( ( "-" | "+" ) factor )* ; @@ -156,7 +166,30 @@ impl<'a> Parser<'a> { } fn expression(&mut self) -> ExprResult<'a> { - self.equality() + self.assignment() + } + + fn assignment(&mut self) -> ExprResult<'a> { + let expr = self.equality()?; + + if self.match_token(&[TokenKind::Equal]) { + let equals = self.previous().clone(); + let value = self.assignment()?; + + if let Expr::Variable(Variable(name)) = expr { + return Ok(Expr::Assign(Assign { + name, + value: Box::new(value), + })); + } + + return Err(Error { + line: equals.line, + kind: ErrorKind::InvalidAssignmentTarget(format!("{:?}", equals)), + }); + } + + Ok(expr) } fn equality(&mut self) -> ExprResult<'a> { |