diff --git a/src/syn/ast.rs b/src/syn/ast.rs index cf1d6e9..6a7eddc 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -25,6 +25,7 @@ pub enum Expr { Bin(Box), Un(Box), FunCall(Box), + Index(Box), Base(BaseExpr), } @@ -35,6 +36,7 @@ impl Spanned for Expr { Expr::Bin(b) => b.span(), Expr::Un(u) => u.span(), Expr::FunCall(f) => f.span(), + Expr::Index(i) => i.span(), } } } @@ -103,6 +105,21 @@ impl Spanned for FunCallExpr { } } +#[derive(Derivative, Clone, PartialEq, Eq)] +#[derivative(Debug)] +pub struct IndexExpr { + pub expr: Expr, + pub index: Expr, + #[derivative(Debug = "ignore")] + pub span: Span, +} + +impl Spanned for IndexExpr { + 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 26d50fe..82d25ec 100644 --- a/src/syn/parser.rs +++ b/src/syn/parser.rs @@ -283,11 +283,12 @@ impl<'t> Parser<'t> { /// index access. fn next_suffix_expr(&mut self, expr: Expr) -> Result { if self.match_token_kind(TokenKind::LParen)?.is_some() { + // function call 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)")?; + self.expect_token_kind(TokenKind::RParen, "end of function call (right paren)")?; let span = expr.span().union(end_token.span()); let fun_call = Expr::FunCall( FunCallExpr { @@ -298,7 +299,21 @@ impl<'t> Parser<'t> { ); self.next_suffix_expr(fun_call) } else if self.match_token_kind(TokenKind::LBracket)?.is_some() { - todo!() + // indexing + let prev_skip = self.set_skip_newlines(true)?; + let index = self.next_expr()?; + self.set_skip_newlines(prev_skip)?; + let end_token = + self.expect_token_kind(TokenKind::RBracket, "end of index expression (right square bracket)")?; + let span = expr.span().union(end_token.span()); + let index_expr = Expr::Index( + IndexExpr { + expr, + index, + span, + }.into() + ); + self.next_suffix_expr(index_expr) } else { Ok(expr) } @@ -603,6 +618,14 @@ mod test { }.into()) } + fn index_expr(expr: Expr, index: Expr) -> Expr { + Expr::Index(IndexExpr { + expr, + index, + span: Default::default(), + }.into()) + } + #[test] fn test_base_expr() { test_parser!( @@ -928,7 +951,7 @@ mod test { } #[test] - fn test_fun_call_expr() { + fn test_suffix_expr() { test_parser!( Parser::try_from(r"foo()").unwrap(), next_expr, @@ -978,6 +1001,32 @@ mod test { ] ) ); + + test_parser!( + Parser::try_from(r"foo()[0]").unwrap(), + next_expr, + index_expr( + fun_call_expr( + base_expr(BaseExprKind::Ident), + vec![] + ), + base_expr(BaseExprKind::Num), + ) + ); + + test_parser!( + Parser::try_from(r"foo[0](bar)").unwrap(), + next_expr, + fun_call_expr( + index_expr( + base_expr(BaseExprKind::Ident), + base_expr(BaseExprKind::Num), + ), + vec![ + base_expr(BaseExprKind::Ident) + ] + ) + ); } ////////////////////////////////////////////////////////////////////////////////