From f3c60865a3bf8c90afa58df477779bad72e6945d Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 11 Jan 2021 20:29:20 +0300 Subject: feat(tazjin/rlox): Parse function calls Change-Id: I1836c73dbfd5fc4ca30c2d22bbffee2fb222d566 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2366 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/interpreter.rs | 1 + users/tazjin/rlox/src/parser.rs | 56 +++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/users/tazjin/rlox/src/interpreter.rs b/users/tazjin/rlox/src/interpreter.rs index 28eb23f9948c..b3fc3d1900a8 100644 --- a/users/tazjin/rlox/src/interpreter.rs +++ b/users/tazjin/rlox/src/interpreter.rs @@ -190,6 +190,7 @@ impl Interpreter { Expr::Binary(binary) => self.eval_binary(binary), Expr::Variable(var) => self.get_var(var), Expr::Logical(log) => self.eval_logical(log), + Expr::Call(_) => unimplemented!(), } } diff --git a/users/tazjin/rlox/src/parser.rs b/users/tazjin/rlox/src/parser.rs index fd1f7c9ea825..4d72eed539bd 100644 --- a/users/tazjin/rlox/src/parser.rs +++ b/users/tazjin/rlox/src/parser.rs @@ -47,6 +47,13 @@ pub struct Unary<'a> { pub right: Box>, } +#[derive(Debug)] +pub struct Call<'a> { + pub callee: Box>, + pub paren: Token<'a>, + pub args: Vec>, +} + // Not to be confused with `Var`, which is for assignment. #[derive(Debug)] pub struct Variable<'a>(pub Token<'a>); @@ -58,6 +65,7 @@ pub enum Expr<'a> { Grouping(Grouping<'a>), Literal(Literal), Unary(Unary<'a>), + Call(Call<'a>), Variable(Variable<'a>), Logical(Logical<'a>), } @@ -132,8 +140,9 @@ equality → comparison ( ( "!=" | "==" ) comparison )* ; comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ; term → factor ( ( "-" | "+" ) factor )* ; factor → unary ( ( "/" | "*" ) unary )* ; -unary → ( "!" | "-" ) unary - | primary ; +unary → ( "!" | "-" ) unary | call ; +call → primary ( "(" arguments? ")" )* ; +arguments → expression ( "," expression )* ; primary → NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ; */ @@ -410,7 +419,46 @@ impl<'a> Parser<'a> { })); } - return self.primary(); + return self.call(); + } + + fn call(&mut self) -> ExprResult<'a> { + let mut expr = self.primary()?; + + loop { + if self.match_token(&[TokenKind::LeftParen]) { + expr = self.finish_call(expr)?; + } else { + break; + } + } + + Ok(expr) + } + + fn finish_call(&mut self, callee: Expr<'a>) -> ExprResult<'a> { + let mut args = vec![]; + + if !self.check_token(&TokenKind::RightParen) { + loop { + // TODO(tazjin): Check for max args count + args.push(self.expression()?); + if !self.match_token(&[TokenKind::Comma]) { + break; + } + } + } + + let paren = self.consume( + &TokenKind::RightParen, + ErrorKind::ExpectedToken("Expect ')' after arguments."), + )?; + + Ok(Expr::Call(Call { + args, + callee: Box::new(callee), + paren, + })) } fn primary(&mut self) -> ExprResult<'a> { @@ -482,7 +530,7 @@ impl<'a> Parser<'a> { &self.tokens[self.current - 1] } - fn consume(&mut self, kind: &TokenKind, err: ErrorKind) -> Result { + fn consume(&mut self, kind: &TokenKind, err: ErrorKind) -> Result, Error> { if self.check_token(kind) { return Ok(self.advance()); } -- cgit 1.4.1