Add function call expressions

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-06 17:39:31 -04:00
parent bd87e9dd30
commit 5c505e5ae5
2 changed files with 105 additions and 2 deletions

View File

@@ -22,9 +22,10 @@ impl Spanned for AssignStmt {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expr {
Base(BaseExpr),
Bin(Box<BinExpr>),
Un(Box<UnExpr>),
FunCall(Box<FunCallExpr>),
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<Expr>,
#[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,

View File

@@ -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<Expr> {
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 {
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
////////////////////////////////////////////////////////////////////////////////