diff --git a/schala-lang/src/parsing/combinator.rs b/schala-lang/src/parsing/combinator.rs index ebe36ab..1d1643b 100644 --- a/schala-lang/src/parsing/combinator.rs +++ b/schala-lang/src/parsing/combinator.rs @@ -501,7 +501,15 @@ fn extended_expr_part(input: Span) -> ParseResult { } fn call_part(input: Span) -> ParseResult> { - delimited(tok(char('(')), separated_list0(tok(char(',')), invocation_argument), tok(char(')')))(input) + context( + "call-part", + //TODO generalize this `not` + delimited( + tok(char('(')), + separated_list0(tok(char(',')), preceded(not(tok(char(')'))), invocation_argument)), + tok(char(')')), + ), + )(input) } fn access_part(input: Span) -> ParseResult<&str> { @@ -517,14 +525,16 @@ fn extended_expr_part(input: Span) -> ParseResult { //TODO this shouldn't be an expression b/c type annotations disallowed here fn invocation_argument(input: Span) -> ParseResult { - alt(( - map(tok(char('_')), |_| InvocationArgument::Ignored), - map(tuple((identifier, tok(char('=')), expression)), |(name, _, expr)| InvocationArgument::Keyword { - name: rc_string(name.fragment()), - expr, - }), - map(expression, InvocationArgument::Positional), - ))(input) + context( + "invocation-argument", + cut(alt(( + map(tok(char('_')), |_| InvocationArgument::Ignored), + map(tuple((identifier, tok(char('=')), expression)), |(name, _, expr)| { + InvocationArgument::Keyword { name: rc_string(name.fragment()), expr } + }), + map(expression, InvocationArgument::Positional), + ))), + )(input) } fn primary_expr(allow_struct: bool) -> impl FnMut(Span) -> ParseResult { diff --git a/schala-lang/src/parsing/test.rs b/schala-lang/src/parsing/test.rs index fc10b70..14d8d88 100644 --- a/schala-lang/src/parsing/test.rs +++ b/schala-lang/src/parsing/test.rs @@ -125,6 +125,7 @@ macro_rules! assert_fail_comb { ($input:expr, $failure:expr) => { let mut parser = Parser::new(); let err = parser.parse_comb($input).unwrap_err(); + println!("assert_fail: {}", err.msg); assert_eq!(err.msg, $failure); }; } @@ -822,7 +823,8 @@ fn functions() { ] }) ); - assert_fail!("a(b,,c)","error at 1:5: expected one of \"(\", \".\", \"0b\", \"0x\", \"[\", \"\\\"\", \"_\", \"false\", \"for\", \"if\", \"true\", \"while\", ['+' | '-' | '!'], ['0' ..= '9'], ['a' ..= 'z' | 'A' ..= 'Z' | '_'], r#\"\\\"#"); + let err_msg = "0: at line 1, in Alpha:\na(b,,c)\n ^\n\n1: at line 1, in Alt:\na(b,,c)\n ^\n\n2: at line 1, in tok:\na(b,,c)\n ^\n\n3: at line 1, in identifier-expr:\na(b,,c)\n ^\n\n4: at line 1, in Alt:\na(b,,c)\n ^\n\n5: at line 1, in primary-expr:\na(b,,c)\n ^\n\n6: at line 1, in extended-expr:\na(b,,c)\n ^\n\n7: at line 1, in prefix-expr:\na(b,,c)\n ^\n\n8: at line 1, in expression-kind:\na(b,,c)\n ^\n\n9: at line 1, in Alt:\na(b,,c)\n ^\n\n10: at line 1, in invocation-argument:\na(b,,c)\n ^\n\n11: at line 1, in call-part:\na(b,,c)\n ^\n\n12: at line 1, in extended-expr:\na(b,,c)\n^\n\n13: at line 1, in prefix-expr:\na(b,,c)\n^\n\n14: at line 1, in expression-kind:\na(b,,c)\n^\n\n15: at line 1, in Parsing-statement:\na(b,,c)\n^\n\n16: at line 1, in AST:\na(b,,c)\n^\n\n"; + assert_fail_comb!("a(b,,c)", err_msg); assert_ast!( "fn a(b, c: Int): Int",