From 1b7dacd2175ef17c919a46030b46034ee699735a Mon Sep 17 00:00:00 2001 From: azjezz Date: Fri, 2 Dec 2022 23:12:12 +0100 Subject: [PATCH] fix: require comma between parameters Signed-off-by: azjezz --- src/parser/internal/functions.rs | 16 ---- src/parser/internal/params.rs | 12 ++- src/parser/internal/punc.rs | 26 +++---- tests/0174/code.php | 6 ++ tests/0174/parser-error.txt | 1 + tests/0174/tokens.txt | 89 +++++++++++++++++++++ tests/0175/code.php | 7 ++ tests/0175/parser-error.txt | 1 + tests/0175/tokens.txt | 116 +++++++++++++++++++++++++++ tests/0176/ast.txt | 48 ++++++++++++ tests/0176/code.php | 7 ++ tests/0176/tokens.txt | 130 +++++++++++++++++++++++++++++++ tests/0177/ast.txt | 48 ++++++++++++ tests/0177/code.php | 7 ++ tests/0177/tokens.txt | 123 +++++++++++++++++++++++++++++ 15 files changed, 603 insertions(+), 34 deletions(-) create mode 100644 tests/0174/code.php create mode 100644 tests/0174/parser-error.txt create mode 100644 tests/0174/tokens.txt create mode 100644 tests/0175/code.php create mode 100644 tests/0175/parser-error.txt create mode 100644 tests/0175/tokens.txt create mode 100644 tests/0176/ast.txt create mode 100644 tests/0176/code.php create mode 100644 tests/0176/tokens.txt create mode 100644 tests/0177/ast.txt create mode 100644 tests/0177/code.php create mode 100644 tests/0177/tokens.txt diff --git a/src/parser/internal/functions.rs b/src/parser/internal/functions.rs index 186f8fbb..d1224441 100644 --- a/src/parser/internal/functions.rs +++ b/src/parser/internal/functions.rs @@ -37,12 +37,8 @@ impl Parser { }; scoped!(state, Scope::AnonymousFunction(is_static), { - self.lparen(state)?; - let params = self.param_list(state)?; - self.rparen(state)?; - let mut uses = vec![]; if state.current.kind == TokenKind::Use { state.next(); @@ -118,12 +114,8 @@ impl Parser { }; scoped!(state, Scope::ArrowFunction(is_static), { - self.lparen(state)?; - let params = self.param_list(state)?; - self.rparen(state)?; - let mut return_type = None; if state.current.kind == TokenKind::Colon { self.colon(state)?; @@ -158,12 +150,8 @@ impl Parser { let name = self.ident(state)?; scoped!(state, Scope::Function(name.clone()), { - self.lparen(state)?; - let params = self.param_list(state)?; - self.rparen(state)?; - let mut return_type = None; if state.current.kind == TokenKind::Colon { @@ -230,12 +218,8 @@ impl Parser { ], state); scoped!(state, Scope::Method(name.clone(), flags.clone()), { - self.lparen(state)?; - let params = self.param_list(state)?; - self.rparen(state)?; - let mut return_type = None; if state.current.kind == TokenKind::Colon { diff --git a/src/parser/internal/params.rs b/src/parser/internal/params.rs index 56ee1279..232adcd7 100644 --- a/src/parser/internal/params.rs +++ b/src/parser/internal/params.rs @@ -52,6 +52,8 @@ impl Parser { _ => unreachable!(), }; + self.lparen(state)?; + while !state.is_eof() && state.current.kind != TokenKind::RightParen { let flags: Vec = self .promoted_property_flags(state)? @@ -136,11 +138,15 @@ impl Parser { by_ref, }); - // TODO: bug! this allows `function foo(string $a ...$b &$c) {}` - // TODO: if `,` is found, look for next param, otherwise break out of the loop. - self.optional_comma(state)?; + if state.current.kind == TokenKind::Comma { + self.comma(state)?; + } else { + break; + } } + self.rparen(state)?; + Ok(params) } diff --git a/src/parser/internal/punc.rs b/src/parser/internal/punc.rs index e8a060d5..da779596 100644 --- a/src/parser/internal/punc.rs +++ b/src/parser/internal/punc.rs @@ -7,33 +7,31 @@ use crate::expect_token; impl Parser { pub(in crate::parser) fn semi(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::SemiColon], state, "`;`"); - Ok(()) + expect_token!([TokenKind::SemiColon => Ok(())], state, "`;`") } pub(in crate::parser) fn lbrace(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::LeftBrace], state, "`{`"); - Ok(()) + expect_token!([TokenKind::LeftBrace => Ok(())], state, "`{`") } pub(in crate::parser) fn rbrace(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::RightBrace], state, "`}`"); - Ok(()) + expect_token!([TokenKind::RightBrace => Ok(())], state, "`}`") } pub(in crate::parser) fn lparen(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::LeftParen], state, "`(`"); - Ok(()) + expect_token!([TokenKind::LeftParen => Ok(())], state, "`(`") } pub(in crate::parser) fn rparen(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::RightParen], state, "`)`"); - Ok(()) + expect_token!([TokenKind::RightParen => Ok(())], state, "`)`") } pub(in crate::parser) fn rbracket(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::RightBracket], state, "`]`"); - Ok(()) + expect_token!([TokenKind::RightBracket => Ok(())], state, "`]`") + } + + pub(in crate::parser) fn comma(&self, state: &mut State) -> ParseResult<()> { + expect_token!([TokenKind::Comma => Ok(())], state, "`,`") } pub(in crate::parser) fn optional_comma(&self, state: &mut State) -> ParseResult<()> { @@ -45,8 +43,6 @@ impl Parser { } pub(in crate::parser) fn colon(&self, state: &mut State) -> ParseResult<()> { - expect_token!([TokenKind::Colon], state, "`:`"); - - Ok(()) + expect_token!([TokenKind::Colon => Ok(())], state, "`:`") } } diff --git a/tests/0174/code.php b/tests/0174/code.php new file mode 100644 index 00000000..1051bc62 --- /dev/null +++ b/tests/0174/code.php @@ -0,0 +1,6 @@ + Parse Error: unexpected token `...`, expecting `)` on line 5 column 5 diff --git a/tests/0174/tokens.txt b/tests/0174/tokens.txt new file mode 100644 index 00000000..209d72d6 --- /dev/null +++ b/tests/0174/tokens.txt @@ -0,0 +1,89 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Function, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "foo", + ), + span: ( + 3, + 10, + ), + }, + Token { + kind: LeftParen, + span: ( + 3, + 13, + ), + }, + Token { + kind: Identifier( + "string", + ), + span: ( + 4, + 5, + ), + }, + Token { + kind: Variable( + "a", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Ellipsis, + span: ( + 5, + 5, + ), + }, + Token { + kind: Variable( + "bar", + ), + span: ( + 5, + 8, + ), + }, + Token { + kind: RightParen, + span: ( + 6, + 1, + ), + }, + Token { + kind: LeftBrace, + span: ( + 6, + 3, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 4, + ), + }, +] diff --git a/tests/0175/code.php b/tests/0175/code.php new file mode 100644 index 00000000..64fa6148 --- /dev/null +++ b/tests/0175/code.php @@ -0,0 +1,7 @@ + Parse Error: unexpected token `float`, expecting `)` on line 6 column 5 diff --git a/tests/0175/tokens.txt b/tests/0175/tokens.txt new file mode 100644 index 00000000..6c65a0c9 --- /dev/null +++ b/tests/0175/tokens.txt @@ -0,0 +1,116 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Function, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "foo", + ), + span: ( + 3, + 10, + ), + }, + Token { + kind: LeftParen, + span: ( + 3, + 13, + ), + }, + Token { + kind: Identifier( + "string", + ), + span: ( + 4, + 5, + ), + }, + Token { + kind: Variable( + "a", + ), + span: ( + 4, + 12, + ), + }, + Token { + kind: Comma, + span: ( + 4, + 14, + ), + }, + Token { + kind: Identifier( + "int", + ), + span: ( + 5, + 5, + ), + }, + Token { + kind: Variable( + "bar", + ), + span: ( + 5, + 9, + ), + }, + Token { + kind: Identifier( + "float", + ), + span: ( + 6, + 5, + ), + }, + Token { + kind: Variable( + "baz", + ), + span: ( + 6, + 11, + ), + }, + Token { + kind: RightParen, + span: ( + 7, + 1, + ), + }, + Token { + kind: LeftBrace, + span: ( + 7, + 3, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 4, + ), + }, +] diff --git a/tests/0176/ast.txt b/tests/0176/ast.txt new file mode 100644 index 00000000..4536cb23 --- /dev/null +++ b/tests/0176/ast.txt @@ -0,0 +1,48 @@ +[ + Function { + name: Identifier { + name: "foo", + }, + params: [ + Param { + name: Variable { + name: "a", + }, + type: Some( + String, + ), + variadic: false, + default: None, + flags: [], + by_ref: false, + }, + Param { + name: Variable { + name: "bar", + }, + type: Some( + Integer, + ), + variadic: false, + default: None, + flags: [], + by_ref: false, + }, + Param { + name: Variable { + name: "baz", + }, + type: Some( + Float, + ), + variadic: false, + default: None, + flags: [], + by_ref: false, + }, + ], + body: [], + return_type: None, + by_ref: false, + }, +] diff --git a/tests/0176/code.php b/tests/0176/code.php new file mode 100644 index 00000000..62c54f33 --- /dev/null +++ b/tests/0176/code.php @@ -0,0 +1,7 @@ +