From 5c505e5ae52f82be63dce6c2c1c26cfbd47356e5 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Wed, 6 May 2020 17:39:31 -0400 Subject: [PATCH] Add function call expressions Signed-off-by: Alek Ratzloff --- src/syn/ast.rs | 19 +++++++++- src/syn/parser.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/syn/ast.rs b/src/syn/ast.rs index 23ddcb3..cf1d6e9 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -22,9 +22,10 @@ impl Spanned for AssignStmt { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Expr { - Base(BaseExpr), Bin(Box), Un(Box), + FunCall(Box), + Base(BaseExpr), } impl Spanned for Expr { @@ -33,6 +34,7 @@ impl Spanned for Expr { Expr::Base(b) => b.span(), Expr::Bin(b) => b.span(), Expr::Un(u) => u.span(), + Expr::FunCall(f) => f.span(), } } } @@ -86,6 +88,21 @@ impl Spanned for UnExpr { } } +#[derive(Derivative, Clone, PartialEq, Eq)] +#[derivative(Debug)] +pub struct FunCallExpr { + pub expr: Expr, + pub args: Vec, + #[derivative(Debug = "ignore")] + pub span: Span, +} + +impl Spanned for FunCallExpr { + fn span(&self) -> Span { + self.span + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum BaseExprKind { Ident, diff --git a/src/syn/parser.rs b/src/syn/parser.rs index b4c53a8..26d50fe 100644 --- a/src/syn/parser.rs +++ b/src/syn/parser.rs @@ -276,7 +276,32 @@ impl<'t> Parser<'t> { _ => unreachable!(), }; - Ok(expr) + self.next_suffix_expr(expr) + } + + /// Takes an expression and attempts to match a suffix for it - either a function call or + /// index access. + fn next_suffix_expr(&mut self, expr: Expr) -> Result { + if self.match_token_kind(TokenKind::LParen)?.is_some() { + let prev_skip = self.set_skip_newlines(true)?; + let args = self.next_expr_list(TokenKind::RParen)?; + self.set_skip_newlines(prev_skip)?; + let end_token = + self.expect_token_kind(TokenKind::RParen, "end of function call (left paren)")?; + let span = expr.span().union(end_token.span()); + let fun_call = Expr::FunCall( + FunCallExpr { + expr, + args, + span, + }.into() + ); + self.next_suffix_expr(fun_call) + } else if self.match_token_kind(TokenKind::LBracket)?.is_some() { + todo!() + } else { + Ok(expr) + } } /// Gets a list of expressions separated by commas, stopping when EOF or specified end token is @@ -570,6 +595,14 @@ mod test { }) } + fn fun_call_expr(expr: Expr, args: Vec) -> Expr { + Expr::FunCall(FunCallExpr { + expr, + args, + span: Default::default(), + }.into()) + } + #[test] fn test_base_expr() { test_parser!( @@ -894,6 +927,59 @@ mod test { ); } + #[test] + fn test_fun_call_expr() { + test_parser!( + Parser::try_from(r"foo()").unwrap(), + next_expr, + fun_call_expr( + base_expr(BaseExprKind::Ident), + vec![] + ) + ); + + test_parser!( + Parser::try_from(r"foo(bar)").unwrap(), + next_expr, + fun_call_expr( + base_expr(BaseExprKind::Ident), + vec![ + base_expr(BaseExprKind::Ident) + ] + ) + ); + + test_parser!( + Parser::try_from(r"foo(bar, 1, :sym)").unwrap(), + next_expr, + fun_call_expr( + base_expr(BaseExprKind::Ident), + vec![ + base_expr(BaseExprKind::Ident), + base_expr(BaseExprKind::Num), + base_expr(BaseExprKind::Sym) + ] + ) + ); + + test_parser!( + Parser::try_from(r"foo( + bar, + 1, + :sym + )").unwrap(), + next_expr, + fun_call_expr( + base_expr(BaseExprKind::Ident), + vec![ + base_expr(BaseExprKind::Ident), + base_expr(BaseExprKind::Num), + base_expr(BaseExprKind::Sym) + ] + ) + ); + } + //////////////////////////////////////////////////////////////////////////////// // Stmt testing ////////////////////////////////////////////////////////////////////////////////