diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index c402914033..746821aac4 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -441,6 +441,40 @@ fn infix_op( par.error(span, "floats not supported"); return Err(ParseFailed); } + Expr::Call { + func, + generic_args, + args, + } => { + let func_span = left.span + func.span; + let func = Box::new(Node::new( + Expr::Attribute { + value: Box::new(left), + attr: { + if let Expr::Name(name) = func.kind { + Node::new(name, func.span) + } else { + par.fancy_error( + "failed to parse attribute expression", + vec![Label::primary(func.span, "expected a name")], + vec![], + ); + return Err(ParseFailed); + } + }, + }, + func_span, + )); + + Node::new( + Expr::Call { + func, + generic_args, + args, + }, + span, + ) + } _ => { par.fancy_error( "failed to parse attribute expression", diff --git a/crates/parser/tests/cases/parse_ast.rs b/crates/parser/tests/cases/parse_ast.rs index 11ac286f99..be8c1f1fb4 100644 --- a/crates/parser/tests/cases/parse_ast.rs +++ b/crates/parser/tests/cases/parse_ast.rs @@ -68,6 +68,8 @@ macro_rules! test_parse { test_parse! { expr_call1, expressions::parse_expr, "foo()" } test_parse! { expr_call2, expressions::parse_expr, "foo(1,2,x:3)" } +test_parse! { expr_call3, expressions::parse_expr, "bing.foo(x:3)" } +test_parse! { expr_call4, expressions::parse_expr, "bang.bing.foo(26, 42)" } test_parse! { expr_attr1, expressions::parse_expr, "foo.bar[0][y]" } test_parse! { expr_attr2, expressions::parse_expr, "a[x].b[y](1)" } test_parse! { expr_num1, expressions::parse_expr, "12345" } diff --git a/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call3.snap b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call3.snap new file mode 100644 index 0000000000..20da75bae8 --- /dev/null +++ b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call3.snap @@ -0,0 +1,82 @@ +--- +source: crates/parser/tests/cases/parse_ast.rs +expression: "ast_string(stringify!(expr_call3), expressions::parse_expr,\n \"bing.foo(x:3)\")" + +--- +Node( + kind: Call( + func: Node( + kind: Attribute( + value: Node( + kind: Name("bing"), + span: Span( + start: 0, + end: 4, + ), + ), + attr: Node( + kind: "foo", + span: Span( + start: 5, + end: 8, + ), + ), + ), + span: Span( + start: 0, + end: 8, + ), + ), + generic_args: Some(Node( + kind: [ + TypeDesc(Node( + kind: Base( + base: "Bar", + ), + span: Span( + start: 9, + end: 12, + ), + )), + ], + span: Span( + start: 8, + end: 13, + ), + )), + args: Node( + kind: [ + Node( + kind: CallArg( + label: Some(Node( + kind: "x", + span: Span( + start: 14, + end: 15, + ), + )), + value: Node( + kind: Num("3"), + span: Span( + start: 16, + end: 17, + ), + ), + ), + span: Span( + start: 14, + end: 17, + ), + ), + ], + span: Span( + start: 13, + end: 18, + ), + ), + ), + span: Span( + start: 0, + end: 18, + ), +) diff --git a/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call4.snap b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call4.snap new file mode 100644 index 0000000000..80390780f2 --- /dev/null +++ b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_call4.snap @@ -0,0 +1,116 @@ +--- +source: crates/parser/tests/cases/parse_ast.rs +expression: "ast_string(stringify!(expr_call4), expressions::parse_expr,\n \"bang.bing.foo(26, 42)\")" + +--- +Node( + kind: Call( + func: Node( + kind: Attribute( + value: Node( + kind: Attribute( + value: Node( + kind: Name("bang"), + span: Span( + start: 0, + end: 4, + ), + ), + attr: Node( + kind: "bing", + span: Span( + start: 5, + end: 9, + ), + ), + ), + span: Span( + start: 0, + end: 9, + ), + ), + attr: Node( + kind: "foo", + span: Span( + start: 10, + end: 13, + ), + ), + ), + span: Span( + start: 0, + end: 13, + ), + ), + generic_args: Some(Node( + kind: [ + TypeDesc(Node( + kind: Base( + base: "Bar", + ), + span: Span( + start: 14, + end: 17, + ), + )), + TypeDesc(Node( + kind: Base( + base: "Baz", + ), + span: Span( + start: 19, + end: 22, + ), + )), + ], + span: Span( + start: 13, + end: 23, + ), + )), + args: Node( + kind: [ + Node( + kind: CallArg( + label: None, + value: Node( + kind: Num("26"), + span: Span( + start: 24, + end: 26, + ), + ), + ), + span: Span( + start: 24, + end: 26, + ), + ), + Node( + kind: CallArg( + label: None, + value: Node( + kind: Num("42"), + span: Span( + start: 28, + end: 30, + ), + ), + ), + span: Span( + start: 28, + end: 30, + ), + ), + ], + span: Span( + start: 23, + end: 31, + ), + ), + ), + span: Span( + start: 0, + end: 31, + ), +)