diff --git a/src/parser/internal/arrays.rs b/src/parser/internal/arrays.rs index e733f7d..83b24f7 100644 --- a/src/parser/internal/arrays.rs +++ b/src/parser/internal/arrays.rs @@ -163,7 +163,7 @@ impl Parser { }; value = self.expression(state, Precedence::Lowest)?; } - + Ok(ArrayItem { key, value, diff --git a/src/parser/internal/utils.rs b/src/parser/internal/utils.rs index f74f188..22a94c7 100644 --- a/src/parser/internal/utils.rs +++ b/src/parser/internal/utils.rs @@ -54,6 +54,10 @@ pub fn skip_right_parenthesis(state: &mut State) -> ParseResult { skip(state, TokenKind::RightParen) } +pub fn skip_left_bracket(state: &mut State) -> ParseResult { + skip(state, TokenKind::LeftBracket) +} + pub fn skip_right_bracket(state: &mut State) -> ParseResult { skip(state, TokenKind::RightBracket) } @@ -62,6 +66,10 @@ pub fn skip_double_arrow(state: &mut State) -> ParseResult { skip(state, TokenKind::DoubleArrow) } +pub fn skip_double_colon(state: &mut State) -> ParseResult { + skip(state, TokenKind::DoubleColon) +} + pub fn colon(state: &mut State) -> ParseResult { let span = skip(state, TokenKind::Colon)?; // A closing PHP tag is valid after a colon, since diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5fe9998..81f4a93 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -632,17 +632,41 @@ impl Parser { | TokenKind::FullyQualifiedIdentifier(_) => { Expression::Identifier(identifiers::full_name(state)?) } - TokenKind::Static => { - state.next(); - Expression::Static - } TokenKind::Self_ => { + if !state.has_class_scope { + return Err(ParseError::CannotFindTypeInCurrentScope( + state.current.kind.to_string(), + state.current.span, + )); + } + state.next(); - Expression::Self_ + + self.postfix(state, Expression::Self_, &TokenKind::DoubleColon)? + } + TokenKind::Static => { + if !state.has_class_scope { + return Err(ParseError::CannotFindTypeInCurrentScope( + state.current.kind.to_string(), + state.current.span, + )); + } + + state.next(); + + self.postfix(state, Expression::Static, &TokenKind::DoubleColon)? } TokenKind::Parent => { + if !state.has_class_parent_scope { + return Err(ParseError::CannotFindTypeInCurrentScope( + state.current.kind.to_string(), + state.current.span, + )); + } + state.next(); - Expression::Parent + + self.postfix(state, Expression::Parent, &TokenKind::DoubleColon)? } TokenKind::LiteralString(s) => { let e = Expression::LiteralString { value: s.clone() }; @@ -992,7 +1016,7 @@ impl Parser { } } TokenKind::LeftBracket => { - state.next(); + utils::skip_left_bracket(state)?; if state.current.kind == TokenKind::RightBracket { state.next(); @@ -1013,7 +1037,7 @@ impl Parser { } } TokenKind::DoubleColon => { - state.next(); + utils::skip_double_colon(state)?; let mut must_be_method_call = false; diff --git a/tests/fixtures/0270/code.php b/tests/fixtures/0270/code.php new file mode 100644 index 0000000..3983f91 --- /dev/null +++ b/tests/fixtures/0270/code.php @@ -0,0 +1,3 @@ + Parse Error: Cannot find type `static` in this scope on line 3 on column 6 diff --git a/tests/fixtures/0270/tokens.txt b/tests/fixtures/0270/tokens.txt new file mode 100644 index 0000000..eddf87b --- /dev/null +++ b/tests/fixtures/0270/tokens.txt @@ -0,0 +1,41 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Variable( + "a", + ), + span: ( + 3, + 1, + ), + }, + Token { + kind: Equals, + span: ( + 3, + 4, + ), + }, + Token { + kind: Static, + span: ( + 3, + 6, + ), + }, + Token { + kind: SemiColon, + span: ( + 3, + 12, + ), + }, +] diff --git a/tests/fixtures/0271/code.php b/tests/fixtures/0271/code.php new file mode 100644 index 0000000..87b47d4 --- /dev/null +++ b/tests/fixtures/0271/code.php @@ -0,0 +1,3 @@ + Parse Error: Cannot find type `static` in this scope on line 3 on column 6 diff --git a/tests/fixtures/0271/tokens.txt b/tests/fixtures/0271/tokens.txt new file mode 100644 index 0000000..ae1401c --- /dev/null +++ b/tests/fixtures/0271/tokens.txt @@ -0,0 +1,57 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Variable( + "a", + ), + span: ( + 3, + 1, + ), + }, + Token { + kind: Equals, + span: ( + 3, + 4, + ), + }, + Token { + kind: Static, + span: ( + 3, + 6, + ), + }, + Token { + kind: DoubleColon, + span: ( + 3, + 12, + ), + }, + Token { + kind: Identifier( + "foo", + ), + span: ( + 3, + 14, + ), + }, + Token { + kind: SemiColon, + span: ( + 3, + 17, + ), + }, +] diff --git a/tests/fixtures/0272/code.php b/tests/fixtures/0272/code.php new file mode 100644 index 0000000..3e8d99b --- /dev/null +++ b/tests/fixtures/0272/code.php @@ -0,0 +1,7 @@ + Parse Error: unexpected token `;`, expecting `::` on line 5 column 20 diff --git a/tests/fixtures/0272/tokens.txt b/tests/fixtures/0272/tokens.txt new file mode 100644 index 0000000..797fbd3 --- /dev/null +++ b/tests/fixtures/0272/tokens.txt @@ -0,0 +1,122 @@ +[ + Token { + kind: OpenTag( + Full, + ), + span: ( + 1, + 1, + ), + }, + Token { + kind: Class, + span: ( + 3, + 1, + ), + }, + Token { + kind: Identifier( + "a", + ), + span: ( + 3, + 7, + ), + }, + Token { + kind: LeftBrace, + span: ( + 3, + 9, + ), + }, + Token { + kind: Public, + span: ( + 4, + 5, + ), + }, + Token { + kind: Function, + span: ( + 4, + 12, + ), + }, + Token { + kind: Identifier( + "foo", + ), + span: ( + 4, + 21, + ), + }, + Token { + kind: LeftParen, + span: ( + 4, + 24, + ), + }, + Token { + kind: RightParen, + span: ( + 4, + 25, + ), + }, + Token { + kind: LeftBrace, + span: ( + 4, + 27, + ), + }, + Token { + kind: Variable( + "a", + ), + span: ( + 5, + 9, + ), + }, + Token { + kind: Equals, + span: ( + 5, + 12, + ), + }, + Token { + kind: Static, + span: ( + 5, + 14, + ), + }, + Token { + kind: SemiColon, + span: ( + 5, + 20, + ), + }, + Token { + kind: RightBrace, + span: ( + 6, + 5, + ), + }, + Token { + kind: RightBrace, + span: ( + 7, + 1, + ), + }, +] diff --git a/tests/fixtures/0273/ast.txt b/tests/fixtures/0273/ast.txt new file mode 100644 index 0000000..aceeda4 --- /dev/null +++ b/tests/fixtures/0273/ast.txt @@ -0,0 +1,113 @@ +[ + Class { + name: Identifier { + start: ( + 3, + 7, + ), + name: "a", + end: ( + 3, + 9, + ), + }, + attributes: [], + extends: None, + implements: [], + body: [ + Method( + Method { + start: ( + 4, + 5, + ), + end: ( + 6, + 5, + ), + name: Identifier { + start: ( + 4, + 21, + ), + name: "foo", + end: ( + 4, + 24, + ), + }, + attributes: [], + parameters: MethodParameterList { + start: ( + 4, + 24, + ), + end: ( + 4, + 27, + ), + members: [], + }, + body: Some( + [ + Expression { + expr: Infix { + lhs: Variable( + Variable { + start: ( + 5, + 9, + ), + name: "a", + end: ( + 5, + 12, + ), + }, + ), + op: Assign, + rhs: StaticMethodCall { + target: Static, + method: Identifier( + Identifier { + start: ( + 5, + 22, + ), + name: "bar", + end: ( + 5, + 25, + ), + }, + ), + args: [], + }, + }, + }, + ], + ), + modifiers: MethodModifierGroup { + modifiers: [ + Public { + start: ( + 4, + 5, + ), + end: ( + 4, + 12, + ), + }, + ], + }, + return_type: None, + by_ref: false, + }, + ), + ], + modifiers: ClassModifierGroup { + modifiers: [], + }, + }, +] diff --git a/tests/fixtures/0273/code.php b/tests/fixtures/0273/code.php new file mode 100644 index 0000000..2c442ca --- /dev/null +++ b/tests/fixtures/0273/code.php @@ -0,0 +1,7 @@ +