Add function call expressions
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -22,9 +22,10 @@ impl Spanned for AssignStmt {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Base(BaseExpr),
|
|
||||||
Bin(Box<BinExpr>),
|
Bin(Box<BinExpr>),
|
||||||
Un(Box<UnExpr>),
|
Un(Box<UnExpr>),
|
||||||
|
FunCall(Box<FunCallExpr>),
|
||||||
|
Base(BaseExpr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for Expr {
|
impl Spanned for Expr {
|
||||||
@@ -33,6 +34,7 @@ impl Spanned for Expr {
|
|||||||
Expr::Base(b) => b.span(),
|
Expr::Base(b) => b.span(),
|
||||||
Expr::Bin(b) => b.span(),
|
Expr::Bin(b) => b.span(),
|
||||||
Expr::Un(u) => u.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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum BaseExprKind {
|
pub enum BaseExprKind {
|
||||||
Ident,
|
Ident,
|
||||||
|
|||||||
@@ -276,7 +276,32 @@ impl<'t> Parser<'t> {
|
|||||||
_ => unreachable!(),
|
_ => 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
|
/// 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]
|
#[test]
|
||||||
fn test_base_expr() {
|
fn test_base_expr() {
|
||||||
test_parser!(
|
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
|
// Stmt testing
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user