@@ -15,6 +15,7 @@ class Lexer
15
15
16
16
protected $ tokenMap ;
17
17
protected $ dropTokens ;
18
+ protected $ identifierTokens ;
18
19
19
20
private $ attributeStartLineUsed ;
20
21
private $ attributeEndLineUsed ;
@@ -37,6 +38,7 @@ public function __construct(array $options = []) {
37
38
// Create Map from internal tokens to PhpParser tokens.
38
39
$ this ->defineCompatibilityTokens ();
39
40
$ this ->tokenMap = $ this ->createTokenMap ();
41
+ $ this ->identifierTokens = $ this ->createIdentifierTokenMap ();
40
42
41
43
// map of tokens to drop while lexing (the map is only used for isset lookup,
42
44
// that's why the value is simply set to 1; the value is never actually used.)
@@ -170,14 +172,13 @@ protected function postprocessTokens(ErrorHandler $errorHandler) {
170
172
171
173
// Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
172
174
// into a single token.
173
- // TODO: Also handle reserved keywords in namespaced names.
174
175
if (\is_array ($ token )
175
- && ($ token [0 ] === \T_NS_SEPARATOR || $ token [ 0 ] === \ T_STRING || $ token [0 ] === \ T_NAMESPACE )) {
176
+ && ($ token [0 ] === \T_NS_SEPARATOR || isset ( $ this -> identifierTokens [ $ token [0 ]]) )) {
176
177
$ lastWasSeparator = $ token [0 ] === \T_NS_SEPARATOR ;
177
178
$ text = $ token [1 ];
178
179
for ($ j = $ i + 1 ; isset ($ this ->tokens [$ j ]); $ j ++) {
179
180
if ($ lastWasSeparator ) {
180
- if ($ this ->tokens [$ j ][0 ] !== \ T_STRING ) {
181
+ if (! isset ( $ this ->identifierTokens [ $ this -> tokens [$ j ][0 ]]) ) {
181
182
break ;
182
183
}
183
184
$ lastWasSeparator = false ;
@@ -488,4 +489,19 @@ protected function createTokenMap() : array {
488
489
489
490
return $ tokenMap ;
490
491
}
492
+
493
+ private function createIdentifierTokenMap (): array {
494
+ // Based on semi_reserved production.
495
+ return array_fill_keys ([
496
+ \T_STRING ,
497
+ \T_INCLUDE , \T_INCLUDE_ONCE , \T_EVAL , \T_REQUIRE , \T_REQUIRE_ONCE , \T_LOGICAL_OR , \T_LOGICAL_XOR , \T_LOGICAL_AND ,
498
+ \T_INSTANCEOF , \T_NEW , \T_CLONE , \T_EXIT , \T_IF , \T_ELSEIF , \T_ELSE , \T_ENDIF , \T_ECHO , \T_DO , \T_WHILE ,
499
+ \T_ENDWHILE , \T_FOR , \T_ENDFOR , \T_FOREACH , \T_ENDFOREACH , \T_DECLARE , \T_ENDDECLARE , \T_AS , \T_TRY , \T_CATCH ,
500
+ \T_FINALLY , \T_THROW , \T_USE , \T_INSTEADOF , \T_GLOBAL , \T_VAR , \T_UNSET , \T_ISSET , \T_EMPTY , \T_CONTINUE , \T_GOTO ,
501
+ \T_FUNCTION , \T_CONST , \T_RETURN , \T_PRINT , \T_YIELD , \T_LIST , \T_SWITCH , \T_ENDSWITCH , \T_CASE , \T_DEFAULT ,
502
+ \T_BREAK , \T_ARRAY , \T_CALLABLE , \T_EXTENDS , \T_IMPLEMENTS , \T_NAMESPACE , \T_TRAIT , \T_INTERFACE , \T_CLASS ,
503
+ \T_CLASS_C , \T_TRAIT_C , \T_FUNC_C , \T_METHOD_C , \T_LINE , \T_FILE , \T_DIR , \T_NS_C , \T_HALT_COMPILER , \T_FN ,
504
+ \T_MATCH ,
505
+ ], true );
506
+ }
491
507
}
0 commit comments