diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 55190b0..a9ca5ce 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -13,6 +13,7 @@ use winnow::combinator::peek; use winnow::combinator::preceded; use winnow::combinator::repeat; use winnow::combinator::repeat_till; +use winnow::combinator::separated; use winnow::combinator::trace; use winnow::error::AddContext; use winnow::error::FromRecoverableError; @@ -268,6 +269,10 @@ pub enum TemplateAstExpr<'input> { source: TemplateToken, value: NomoValue, }, + FunctionCall { + name: Box>, + args: Vec>, + }, } fn parse_asts<'input>(input: &mut Input<'input>) -> Result>, AstError> { @@ -559,6 +564,22 @@ fn parse_end<'input>(input: &mut Input<'input>) -> Result(input: &mut Input<'input>) -> Result, AstError> { + trace( + "variable_access", + ( + TokenKind::Ident + .map(TemplateAstExpr::VariableAccess) + .map(Box::new), + TokenKind::LeftArgList, + separated(0.., parse_expression, TokenKind::ArgSeperator), + TokenKind::RightArgList, + ) + .map(|(name, _left, args, _right)| TemplateAstExpr::FunctionCall { name, args }), + ) + .parse_next(input) +} + fn parse_variable_access<'input>( input: &mut Input<'input>, ) -> Result, AstError> { @@ -620,7 +641,11 @@ where } fn parse_operand<'input>(input: &mut Input<'input>) -> Result, AstError> { - trace("operand", alt((parse_variable_access, parse_literal))).parse_next(input) + trace( + "operand", + alt((parse_function, parse_variable_access, parse_literal)), + ) + .parse_next(input) } fn parse_literal<'input>(input: &mut Input<'input>) -> Result, AstError> { @@ -658,7 +683,11 @@ fn parse_expression<'input>( ($parser:expr => [ $($side:tt $val:tt => $prec:expr),* $(,)? ]) => { dispatch! { surrounded(ws, parse_operator); $( - TokenOperator::$val => $side($prec, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::$val, lhs: Box::new(lhs), rhs: Box::new(rhs) })) + TokenOperator::$val => $side($prec, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { + op: TokenOperator::$val, + lhs: Box::new(lhs), + rhs: Box::new(rhs) + })) ),* } }; @@ -1008,4 +1037,15 @@ mod tests { insta::assert_debug_snapshot!(ast); } + + #[test] + fn check_function_call() { + let input = "{{= foo(2 * 3, bar(2 + baz)) }}"; + + let parsed = crate::parser::parse(input.into()).unwrap(); + + let ast = panic_pretty(input, parse(parsed.tokens())); + + insta::assert_debug_snapshot!(ast); + } } diff --git a/src/ast/snapshots/nomo__ast__tests__check_function_call.snap b/src/ast/snapshots/nomo__ast__tests__check_function_call.snap new file mode 100644 index 0000000..44eaec1 --- /dev/null +++ b/src/ast/snapshots/nomo__ast__tests__check_function_call.snap @@ -0,0 +1,53 @@ +--- +source: src/ast/mod.rs +expression: ast +--- +TemplateAst { + root: [ + Interpolation { + prev_whitespace_content: None, + expression: FunctionCall { + name: VariableAccess( + [Ident]"foo" (4..7), + ), + args: [ + Operation { + op: Times, + lhs: Literal { + source: [Literal(Integer(2))]"2" (8..9), + value: Integer { + value: 2, + }, + }, + rhs: Literal { + source: [Literal(Integer(3))]"3" (12..13), + value: Integer { + value: 3, + }, + }, + }, + FunctionCall { + name: VariableAccess( + [Ident]"bar" (15..18), + ), + args: [ + Operation { + op: Plus, + lhs: Literal { + source: [Literal(Integer(2))]"2" (19..20), + value: Integer { + value: 2, + }, + }, + rhs: VariableAccess( + [Ident]"baz" (23..26), + ), + }, + ], + }, + ], + }, + post_whitespace_content: None, + }, + ], +} diff --git a/src/emit/mod.rs b/src/emit/mod.rs index aa3e6c0..1a8603a 100644 --- a/src/emit/mod.rs +++ b/src/emit/mod.rs @@ -417,6 +417,7 @@ fn emit_ast_expr( | TemplateAstExpr::ForElse | TemplateAstExpr::Invalid { .. } | TemplateAstExpr::Literal { .. } + | TemplateAstExpr::FunctionCall { .. } | TemplateAstExpr::Operation { .. } | TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort), } @@ -459,6 +460,7 @@ fn emit_expr_load( TemplateAstExpr::StaticContent { .. } | TemplateAstExpr::Interpolation { .. } => { unreachable!("Invalid AST here") } + TemplateAstExpr::FunctionCall { .. } => todo!(), TemplateAstExpr::ConditionalChain { .. } => todo!(), TemplateAstExpr::ElseConditional { .. } => todo!(), TemplateAstExpr::EndBlock => todo!(), diff --git a/src/value.rs b/src/value.rs index 965cb2b..dd57a03 100644 --- a/src/value.rs +++ b/src/value.rs @@ -5,8 +5,6 @@ use std::collections::BTreeMap; use displaydoc::Display; use thiserror::Error; -use crate::Nomo; - #[derive(Clone)] pub enum NomoValue { String {