Improve output of tokens in Parse Errors

Currently, unexpected tokens in the parser are shown as the text
found, plus the internal token name, including the notorious
"unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)".

This commit replaces that with a more user-friendly format, with
two main types of token:

* Tokens which always represent the same text are shown like
  'unexpected token "::"' and 'expected "::"'
* Tokens which have variable text are given a user-friendly
  name, and show like 'unexpected identifier "foo"', and
  'expected identifer'.

A few tokens have special cases:

* unexpected token """ -> unexpected double-quote mark
* unexpected quoted string "'foo'" -> unexpected single-quoted
  string "foo"
* unexpected quoted string ""foo"" -> unexpected double-quoted
  string "foo"
* unexpected illegal character "_" -> unexpected character 0xNN
  (where _ is almost certainly a control character, and NN is the
   hexadecimal value of the byte)

The \ token has a special case in the implementation just to stop
bison making a mess of escaping it and it coming out as \\
This commit is contained in:
Rowan Tommins 2020-06-11 20:56:22 +01:00 committed by Nikita Popov
parent d4fdf79add
commit 55a15f32ce
53 changed files with 317 additions and 238 deletions

View file

@ -8,4 +8,4 @@ class A {}
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '$x' (T_VARIABLE), expecting identifier (T_STRING) or static (T_STATIC) or namespace (T_NAMESPACE) or \\ (T_NS_SEPARATOR) in %s on line %d Parse error: syntax error, unexpected variable "$x", expecting identifier or "static" or "namespace" or "\" in %s on line %d

View file

@ -8,4 +8,4 @@ $foo = 'bar';
var_dump(new namespace::$foo); var_dump(new namespace::$foo);
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: %s error%sexpecting%sT_NS_SEPARATOR%sin %sbug43343.php on line 5 Parse error: %s error%sexpecting%s"\"%sin %sbug43343.php on line 5

View file

@ -7,4 +7,4 @@ $"*** Testing function() : ***\n";
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '"*** Testing function() : ***' (T_CONSTANT_ENCAPSED_STRING), expecting variable (T_VARIABLE) or '{' or '$' in %s on line %d Parse error: syntax error, unexpected double-quoted string "*** Testing function() : ***\n", expecting variable or "{" or "$" in %s on line %d

View file

@ -24,5 +24,5 @@ try {
?> ?>
--EXPECT-- --EXPECT--
string(41) "syntax error, unexpected 'FOO' (T_STRING)" string(41) "syntax error, unexpected identifier "FOO""
string(41) "syntax error, unexpected 'FOO' (T_STRING)" string(41) "syntax error, unexpected identifier "FOO""

View file

@ -4,4 +4,4 @@ Bug #77993 (Wrong parse error for invalid hex literal on Windows)
<?php <?php
0xg10; 0xg10;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'xg10' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "xg10" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid consecutive numeric separators after hex literal
<?php <?php
0x0__F; 0x0__F;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '__F' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "__F" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid consecutive numeric separators after binary literal
<?php <?php
0b0__1 0b0__1
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '__1' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "__1" in %s on line %d

View file

@ -9,4 +9,4 @@ class Test {
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'static' (T_STATIC), expecting variable (T_VARIABLE) in %s on line %d Parse error: syntax error, unexpected token "static", expecting variable in %s on line %d

View file

@ -8,4 +8,4 @@ Note: the closing ?> has been deliberately elided.
echo <<<END echo <<<END
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) in %s on line %d Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" in %s on line %d

View file

@ -8,4 +8,4 @@ Note: the closing ?> has been deliberately elided.
echo <<<'END' echo <<<'END'
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) in %s on line %d Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" in %s on line %d

View file

@ -8,4 +8,4 @@ eval('<<<\'end\'
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) in %s on line %d Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" in %s on line %d

View file

@ -5,4 +5,4 @@ Leading commas in function calls is not allowed
foo(,$foo); foo(,$foo);
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',' in %s on line %d Parse error: syntax error, unexpected token "," in %s on line %d

View file

@ -5,4 +5,4 @@ Multiple inner commas in function calls is not allowed
foo($foo,,$bar); foo($foo,,$bar);
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting ')' in %s on line %d Parse error: syntax error, unexpected token ",", expecting ")" in %s on line %d

View file

@ -5,4 +5,4 @@ Multiple trailing commas in function calls is not allowed
foo($foo,,); foo($foo,,);
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting ')' in %s on line %d Parse error: syntax error, unexpected token ",", expecting ")" in %s on line %d

View file

@ -5,4 +5,4 @@ Single comma in function calls is not allowed
foo(,); foo(,);
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',' in %s on line %d Parse error: syntax error, unexpected token "," in %s on line %d

View file

@ -11,4 +11,4 @@ class Obj
function echo(){} // not valid function echo(){} // not valid
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'echo' (T_ECHO), expecting %s in %s on line 9 Parse error: syntax error, unexpected token "echo", expecting "(" in %s on line %d

View file

@ -10,4 +10,4 @@ class Obj
const return = 'nope'; const return = 'nope';
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'return' (T_RETURN), expecting identifier (T_STRING) in %s on line 8 Parse error: syntax error, unexpected token "return", expecting identifier in %s on line %d

View file

@ -9,4 +9,4 @@ class A {
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'FOREACH' (T_FOREACH), expecting ']' in %s on line %d Parse error: syntax error, unexpected token "foreach", expecting "]" in %s on line %d

View file

@ -7,4 +7,4 @@ var_dump(list(1, 2, 3));
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ')', expecting '=' in %s on line %d Parse error: syntax error, unexpected token ")", expecting "=" in %s on line %d

View file

@ -14,4 +14,4 @@ namespace Fiz\Biz\Buz {
} }
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '{', expecting '}' in %sns_088.php on line 5 Parse error: syntax error, unexpected token "{", expecting "}" in %s on line %d

View file

@ -11,4 +11,4 @@ use const Foo\Bar\{
function C function C
}; };
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'const' (T_CONST), expecting '}' in %s on line 7 Parse error: syntax error, unexpected token "const", expecting "}" in %s on line %d

View file

@ -7,4 +7,4 @@ use Foo\Bar\{\Baz};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '\' (T_NS_SEPARATOR), expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line 3 Parse error: syntax error, unexpected token "\", expecting identifier or "function" or "const" in %s on line %d

View file

@ -5,4 +5,4 @@ Group use declarations mustn't be empty
use Baz\{}; use Baz\{};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '}', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d Parse error: syntax error, unexpected token "}", expecting identifier or "function" or "const" in %s on line %d

View file

@ -5,4 +5,4 @@ Group use declarations mustn't contain just a comma
use Baz\{,}; use Baz\{,};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d Parse error: syntax error, unexpected token ",", expecting identifier or "function" or "const" in %s on line %d

View file

@ -5,4 +5,4 @@ Group use declarations mustn't allow more than one comma
use Baz\{Foo,,}; use Baz\{Foo,,};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d Parse error: syntax error, unexpected token ",", expecting "}" in %s on line %d

View file

@ -5,4 +5,4 @@ Group use declarations mustn't begin with a comma
use Baz\{,Foo}; use Baz\{,Foo};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) in %s on line %d Parse error: syntax error, unexpected token ",", expecting identifier or "function" or "const" in %s on line %d

View file

@ -5,4 +5,4 @@ Group use declarations mustn't contain two commas mid-list
use Baz\{Foo,,Bar}; use Baz\{Foo,,Bar};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d Parse error: syntax error, unexpected token ",", expecting "}" in %s on line %d

View file

@ -5,4 +5,4 @@ Unmixed group use declarations mustn't allow more than one comma
use const Baz\{Foo,,}; use const Baz\{Foo,,};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d Parse error: syntax error, unexpected token ",", expecting "}" in %s on line %d

View file

@ -5,4 +5,4 @@ Unmixed group use declarations mustn't begin with a comma
use function Baz\{,Foo}; use function Baz\{,Foo};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting identifier (T_STRING) in %s on line %d Parse error: syntax error, unexpected token ",", expecting identifier in %s on line %d

View file

@ -5,4 +5,4 @@ Unmixed group use declarations mustn't contain two commas mid-list
use const Baz\{Foo,,Bar}; use const Baz\{Foo,,Bar};
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected ',', expecting '}' in %s on line %d Parse error: syntax error, unexpected token ",", expecting "}" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: trailing underscore
<?php <?php
100_; 100_;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '_' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "_" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: adjacent underscores
<?php <?php
10__0; 10__0;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '__0' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "__0" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore left of period
<?php <?php
100_.0; 100_.0;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '_' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "_" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore right of period
<?php <?php
100._0; 100._0;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '_0' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "_0" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore next to 0x
<?php <?php
0x_0123; 0x_0123;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'x_0123' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "x_0123" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore next to 0b
<?php <?php
0b_0101; 0b_0101;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'b_0101' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "b_0101" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore left of e
<?php <?php
1_e2; 1_e2;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '_e2' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "_e2" in %s on line %d

View file

@ -4,4 +4,4 @@ Invalid use: underscore right of e
<?php <?php
1e_2; 1e_2;
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'e_2' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "e_2" in %s on line %d

View file

@ -45,7 +45,7 @@ var_dump("\u{ffffff}");');
Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0 Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0
Unclosed '{' on line 2 Unclosed '{' on line 2
Unclosed '{' on line 3 Unclosed '{' on line 3
syntax error, unexpected end of file, expecting '(' on line 2 syntax error, unexpected end of file, expecting "(" on line 2
Invalid numeric literal on line 2 Invalid numeric literal on line 2
Invalid UTF-8 codepoint escape sequence on line 2 Invalid UTF-8 codepoint escape sequence on line 2
Invalid UTF-8 codepoint escape sequence: Codepoint too large on line 2 Invalid UTF-8 codepoint escape sequence: Codepoint too large on line 2

View file

@ -12,4 +12,4 @@ trait Foo extends Base {
echo 'DONE'; echo 'DONE';
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'extends' (T_EXTENDS), expecting '{' in %s on line %d Parse error: syntax error, unexpected token "extends", expecting "{" in %s on line %d

View file

@ -16,4 +16,4 @@ trait THello implements MyInterface {
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'implements' (T_IMPLEMENTS), expecting '{' in %s on line %d Parse error: syntax error, unexpected token "implements", expecting "{" in %s on line %d

View file

@ -7,4 +7,4 @@ $foo = (mixed) 12;
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '12' (T_LNUMBER) in %s on line %d Parse error: syntax error, unexpected integer "12" in %s on line %d

View file

@ -12,4 +12,4 @@ class Test {
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'static' (T_STATIC), expecting variable (T_VARIABLE) in %s on line %d Parse error: syntax error, unexpected token "static", expecting variable in %s on line %d

View file

@ -10,4 +10,4 @@ class Test {
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'static' (T_STATIC) in %s on line %d Parse error: syntax error, unexpected token "static" in %s on line %d

View file

@ -8,4 +8,4 @@ class Foo {
} }
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'int' (T_STRING), expecting variable (T_VARIABLE) in %s on line 4 Parse error: syntax error, unexpected identifier "int", expecting variable in %s on line %d

View file

@ -7,4 +7,4 @@ global $$foo->bar;
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ';' or ',' in %s on line %d Parse error: syntax error, unexpected token "->", expecting ";" or "," in %s on line %d

View file

@ -86,146 +86,146 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%precedence T_ELSEIF %precedence T_ELSEIF
%precedence T_ELSE %precedence T_ELSE
%token <ast> T_LNUMBER "integer number (T_LNUMBER)" %token <ast> T_LNUMBER "integer"
%token <ast> T_DNUMBER "floating-point number (T_DNUMBER)" %token <ast> T_DNUMBER "floating-point number"
%token <ast> T_STRING "identifier (T_STRING)" %token <ast> T_STRING "identifier"
%token <ast> T_VARIABLE "variable (T_VARIABLE)" %token <ast> T_VARIABLE "variable"
%token <ast> T_INLINE_HTML %token <ast> T_INLINE_HTML
%token <ast> T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)" %token <ast> T_ENCAPSED_AND_WHITESPACE "string content"
%token <ast> T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)" %token <ast> T_CONSTANT_ENCAPSED_STRING "quoted string"
%token <ast> T_STRING_VARNAME "variable name (T_STRING_VARNAME)" %token <ast> T_STRING_VARNAME "variable name"
%token <ast> T_NUM_STRING "number (T_NUM_STRING)" %token <ast> T_NUM_STRING "number"
%token <ident> T_INCLUDE "include (T_INCLUDE)" %token <ident> T_INCLUDE "'include'"
%token <ident> T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)" %token <ident> T_INCLUDE_ONCE "'include_once'"
%token <ident> T_EVAL "eval (T_EVAL)" %token <ident> T_EVAL "'eval'"
%token <ident> T_REQUIRE "require (T_REQUIRE)" %token <ident> T_REQUIRE "'require'"
%token <ident> T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)" %token <ident> T_REQUIRE_ONCE "'require_once'"
%token <ident> T_LOGICAL_OR "or (T_LOGICAL_OR)" %token <ident> T_LOGICAL_OR "'or'"
%token <ident> T_LOGICAL_XOR "xor (T_LOGICAL_XOR)" %token <ident> T_LOGICAL_XOR "'xor'"
%token <ident> T_LOGICAL_AND "and (T_LOGICAL_AND)" %token <ident> T_LOGICAL_AND "'and'"
%token <ident> T_PRINT "print (T_PRINT)" %token <ident> T_PRINT "'print'"
%token <ident> T_YIELD "yield (T_YIELD)" %token <ident> T_YIELD "'yield'"
%token <ident> T_YIELD_FROM "yield from (T_YIELD_FROM)" %token <ident> T_YIELD_FROM "'yield from'"
%token <ident> T_INSTANCEOF "instanceof (T_INSTANCEOF)" %token <ident> T_INSTANCEOF "'instanceof'"
%token <ident> T_NEW "new (T_NEW)" %token <ident> T_NEW "'new'"
%token <ident> T_CLONE "clone (T_CLONE)" %token <ident> T_CLONE "'clone'"
%token <ident> T_EXIT "exit (T_EXIT)" %token <ident> T_EXIT "'exit'"
%token <ident> T_IF "if (T_IF)" %token <ident> T_IF "'if'"
%token <ident> T_ELSEIF "elseif (T_ELSEIF)" %token <ident> T_ELSEIF "'elseif'"
%token <ident> T_ELSE "else (T_ELSE)" %token <ident> T_ELSE "'else'"
%token <ident> T_ENDIF "endif (T_ENDIF)" %token <ident> T_ENDIF "'endif'"
%token <ident> T_ECHO "echo (T_ECHO)" %token <ident> T_ECHO "'echo'"
%token <ident> T_DO "do (T_DO)" %token <ident> T_DO "'do'"
%token <ident> T_WHILE "while (T_WHILE)" %token <ident> T_WHILE "'while'"
%token <ident> T_ENDWHILE "endwhile (T_ENDWHILE)" %token <ident> T_ENDWHILE "'endwhile'"
%token <ident> T_FOR "for (T_FOR)" %token <ident> T_FOR "'for'"
%token <ident> T_ENDFOR "endfor (T_ENDFOR)" %token <ident> T_ENDFOR "'endfor'"
%token <ident> T_FOREACH "foreach (T_FOREACH)" %token <ident> T_FOREACH "'foreach'"
%token <ident> T_ENDFOREACH "endforeach (T_ENDFOREACH)" %token <ident> T_ENDFOREACH "'endforeach'"
%token <ident> T_DECLARE "declare (T_DECLARE)" %token <ident> T_DECLARE "'declare'"
%token <ident> T_ENDDECLARE "enddeclare (T_ENDDECLARE)" %token <ident> T_ENDDECLARE "'enddeclare'"
%token <ident> T_AS "as (T_AS)" %token <ident> T_AS "'as'"
%token <ident> T_SWITCH "switch (T_SWITCH)" %token <ident> T_SWITCH "'switch'"
%token <ident> T_ENDSWITCH "endswitch (T_ENDSWITCH)" %token <ident> T_ENDSWITCH "'endswitch'"
%token <ident> T_CASE "case (T_CASE)" %token <ident> T_CASE "'case'"
%token <ident> T_DEFAULT "default (T_DEFAULT)" %token <ident> T_DEFAULT "'default'"
%token <ident> T_MATCH "match (T_MATCH)" %token <ident> T_MATCH "'match'"
%token <ident> T_BREAK "break (T_BREAK)" %token <ident> T_BREAK "'break'"
%token <ident> T_CONTINUE "continue (T_CONTINUE)" %token <ident> T_CONTINUE "'continue'"
%token <ident> T_GOTO "goto (T_GOTO)" %token <ident> T_GOTO "'goto'"
%token <ident> T_FUNCTION "function (T_FUNCTION)" %token <ident> T_FUNCTION "'function'"
%token <ident> T_FN "fn (T_FN)" %token <ident> T_FN "'fn'"
%token <ident> T_CONST "const (T_CONST)" %token <ident> T_CONST "'const'"
%token <ident> T_RETURN "return (T_RETURN)" %token <ident> T_RETURN "'return'"
%token <ident> T_TRY "try (T_TRY)" %token <ident> T_TRY "'try'"
%token <ident> T_CATCH "catch (T_CATCH)" %token <ident> T_CATCH "'catch'"
%token <ident> T_FINALLY "finally (T_FINALLY)" %token <ident> T_FINALLY "'finally'"
%token <ident> T_THROW "throw (T_THROW)" %token <ident> T_THROW "'throw'"
%token <ident> T_USE "use (T_USE)" %token <ident> T_USE "'use'"
%token <ident> T_INSTEADOF "insteadof (T_INSTEADOF)" %token <ident> T_INSTEADOF "'insteadof'"
%token <ident> T_GLOBAL "global (T_GLOBAL)" %token <ident> T_GLOBAL "'global'"
%token <ident> T_STATIC "static (T_STATIC)" %token <ident> T_STATIC "'static'"
%token <ident> T_ABSTRACT "abstract (T_ABSTRACT)" %token <ident> T_ABSTRACT "'abstract'"
%token <ident> T_FINAL "final (T_FINAL)" %token <ident> T_FINAL "'final'"
%token <ident> T_PRIVATE "private (T_PRIVATE)" %token <ident> T_PRIVATE "'private'"
%token <ident> T_PROTECTED "protected (T_PROTECTED)" %token <ident> T_PROTECTED "'protected'"
%token <ident> T_PUBLIC "public (T_PUBLIC)" %token <ident> T_PUBLIC "'public'"
%token <ident> T_VAR "var (T_VAR)" %token <ident> T_VAR "'var'"
%token <ident> T_UNSET "unset (T_UNSET)" %token <ident> T_UNSET "'unset'"
%token <ident> T_ISSET "isset (T_ISSET)" %token <ident> T_ISSET "'isset'"
%token <ident> T_EMPTY "empty (T_EMPTY)" %token <ident> T_EMPTY "'empty'"
%token <ident> T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)" %token <ident> T_HALT_COMPILER "'__halt_compiler'"
%token <ident> T_CLASS "class (T_CLASS)" %token <ident> T_CLASS "'class'"
%token <ident> T_TRAIT "trait (T_TRAIT)" %token <ident> T_TRAIT "'trait'"
%token <ident> T_INTERFACE "interface (T_INTERFACE)" %token <ident> T_INTERFACE "'interface'"
%token <ident> T_EXTENDS "extends (T_EXTENDS)" %token <ident> T_EXTENDS "'extends'"
%token <ident> T_IMPLEMENTS "implements (T_IMPLEMENTS)" %token <ident> T_IMPLEMENTS "'implements'"
%token <ident> T_NAMESPACE "namespace (T_NAMESPACE)" %token <ident> T_NAMESPACE "'namespace'"
%token <ident> T_LIST "list (T_LIST)" %token <ident> T_LIST "'list'"
%token <ident> T_ARRAY "array (T_ARRAY)" %token <ident> T_ARRAY "'array'"
%token <ident> T_CALLABLE "callable (T_CALLABLE)" %token <ident> T_CALLABLE "'callable'"
%token <ident> T_LINE "__LINE__ (T_LINE)" %token <ident> T_LINE "'__LINE__'"
%token <ident> T_FILE "__FILE__ (T_FILE)" %token <ident> T_FILE "'__FILE__'"
%token <ident> T_DIR "__DIR__ (T_DIR)" %token <ident> T_DIR "'__DIR__'"
%token <ident> T_CLASS_C "__CLASS__ (T_CLASS_C)" %token <ident> T_CLASS_C "'__CLASS__'"
%token <ident> T_TRAIT_C "__TRAIT__ (T_TRAIT_C)" %token <ident> T_TRAIT_C "'__TRAIT__'"
%token <ident> T_METHOD_C "__METHOD__ (T_METHOD_C)" %token <ident> T_METHOD_C "'__METHOD__'"
%token <ident> T_FUNC_C "__FUNCTION__ (T_FUNC_C)" %token <ident> T_FUNC_C "'__FUNCTION__'"
%token <ident> T_NS_C "__NAMESPACE__ (T_NS_C)" %token <ident> T_NS_C "'__NAMESPACE__'"
%token END 0 "end of file" %token END 0 "end of file"
%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)" %token T_PLUS_EQUAL "'+='"
%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)" %token T_MINUS_EQUAL "'-='"
%token T_MUL_EQUAL "*= (T_MUL_EQUAL)" %token T_MUL_EQUAL "'*='"
%token T_DIV_EQUAL "/= (T_DIV_EQUAL)" %token T_DIV_EQUAL "'/='"
%token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)" %token T_CONCAT_EQUAL "'.='"
%token T_MOD_EQUAL "%= (T_MOD_EQUAL)" %token T_MOD_EQUAL "'%='"
%token T_AND_EQUAL "&= (T_AND_EQUAL)" %token T_AND_EQUAL "'&='"
%token T_OR_EQUAL "|= (T_OR_EQUAL)" %token T_OR_EQUAL "'|='"
%token T_XOR_EQUAL "^= (T_XOR_EQUAL)" %token T_XOR_EQUAL "'^='"
%token T_SL_EQUAL "<<= (T_SL_EQUAL)" %token T_SL_EQUAL "'<<='"
%token T_SR_EQUAL ">>= (T_SR_EQUAL)" %token T_SR_EQUAL "'>>='"
%token T_COALESCE_EQUAL "??= (T_COALESCE_EQUAL)" %token T_COALESCE_EQUAL "'??='"
%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)" %token T_BOOLEAN_OR "'||'"
%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)" %token T_BOOLEAN_AND "'&&'"
%token T_IS_EQUAL "== (T_IS_EQUAL)" %token T_IS_EQUAL "'=='"
%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)" %token T_IS_NOT_EQUAL "'!='"
%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)" %token T_IS_IDENTICAL "'==='"
%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)" %token T_IS_NOT_IDENTICAL "'!=='"
%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)" %token T_IS_SMALLER_OR_EQUAL "'<='"
%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)" %token T_IS_GREATER_OR_EQUAL "'>='"
%token T_SPACESHIP "<=> (T_SPACESHIP)" %token T_SPACESHIP "'<=>'"
%token T_SL "<< (T_SL)" %token T_SL "'<<'"
%token T_SR ">> (T_SR)" %token T_SR "'>>'"
%token T_INC "++ (T_INC)" %token T_INC "'++'"
%token T_DEC "-- (T_DEC)" %token T_DEC "'--'"
%token T_INT_CAST "(int) (T_INT_CAST)" %token T_INT_CAST "'(int)'"
%token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)" %token T_DOUBLE_CAST "'(double)'"
%token T_STRING_CAST "(string) (T_STRING_CAST)" %token T_STRING_CAST "'(string)'"
%token T_ARRAY_CAST "(array) (T_ARRAY_CAST)" %token T_ARRAY_CAST "'(array)'"
%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)" %token T_OBJECT_CAST "'(object)'"
%token T_BOOL_CAST "(bool) (T_BOOL_CAST)" %token T_BOOL_CAST "'(bool)'"
%token T_UNSET_CAST "(unset) (T_UNSET_CAST)" %token T_UNSET_CAST "'(unset)'"
%token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)" %token T_OBJECT_OPERATOR "'->'"
%token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)" %token T_DOUBLE_ARROW "'=>'"
%token T_COMMENT "comment (T_COMMENT)" %token T_COMMENT "comment"
%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)" %token T_DOC_COMMENT "doc comment"
%token T_OPEN_TAG "open tag (T_OPEN_TAG)" %token T_OPEN_TAG "open tag"
%token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)" %token T_OPEN_TAG_WITH_ECHO "'<?='"
%token T_CLOSE_TAG "close tag (T_CLOSE_TAG)" %token T_CLOSE_TAG "'?>'"
%token T_WHITESPACE "whitespace (T_WHITESPACE)" %token T_WHITESPACE "whitespace"
%token T_START_HEREDOC "heredoc start (T_START_HEREDOC)" %token T_START_HEREDOC "heredoc start"
%token T_END_HEREDOC "heredoc end (T_END_HEREDOC)" %token T_END_HEREDOC "heredoc end"
%token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)" %token T_DOLLAR_OPEN_CURLY_BRACES "'${'"
%token T_CURLY_OPEN "{$ (T_CURLY_OPEN)" %token T_CURLY_OPEN "'{$'"
%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)" %token T_PAAMAYIM_NEKUDOTAYIM "'::'"
%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)" %token T_NS_SEPARATOR "'\\'"
%token T_ELLIPSIS "... (T_ELLIPSIS)" %token T_ELLIPSIS "'...'"
%token T_COALESCE "?? (T_COALESCE)" %token T_COALESCE "'??'"
%token T_POW "** (T_POW)" %token T_POW "'**'"
%token T_POW_EQUAL "**= (T_POW_EQUAL)" %token T_POW_EQUAL "'**='"
%token T_BAD_CHARACTER "invalid character (T_BAD_CHARACTER)" %token T_BAD_CHARACTER "invalid character"
/* Token used to force a parse error from the lexer */ /* Token used to force a parse error from the lexer */
%token T_ERROR %token T_ERROR
@ -1438,15 +1438,16 @@ isset_variable:
%% %%
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary /* Over-ride Bison formatting routine to give better token descriptions.
quotes and backslashes, so that it's suitable for yyerror. The Copy to YYRES the contents of YYSTR for use in yyerror.
heuristic is that double-quoting is unnecessary unless the string YYSTR is taken from yytname, from the %token declaration.
contains an apostrophe, a comma, or backslash (other than If YYRES is null, do not copy; instead, return the length of what
backslash-backslash). YYSTR is taken from yytname. If YYRES is the result would have been. */
null, do not copy; instead, return the length of what the result
would have been. */
static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
{ {
const char *toktype = yystr;
size_t toktype_len = strlen(toktype);
/* CG(parse_error) states: /* CG(parse_error) states:
* 0 => yyres = NULL, yystr is the unexpected token * 0 => yyres = NULL, yystr is the unexpected token
* 1 => yyres = NULL, yystr is one of the expected tokens * 1 => yyres = NULL, yystr is one of the expected tokens
@ -1460,63 +1461,141 @@ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
if (CG(parse_error) % 2 == 0) { if (CG(parse_error) % 2 == 0) {
/* The unexpected token */ /* The unexpected token */
char buffer[120]; char buffer[120];
const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL; const unsigned char *tokcontent, *tokcontent_end;
unsigned int len = 0, toklen = 0, yystr_len; size_t tokcontent_len;
CG(parse_error)++; CG(parse_error)++;
if (LANG_SCNG(yy_text)[0] == 0 && if (LANG_SCNG(yy_text)[0] == 0 &&
LANG_SCNG(yy_leng) == 1 && LANG_SCNG(yy_leng) == 1 &&
strcmp(yystr, "\"end of file\"") == 0) { strcmp(toktype, "\"end of file\"") == 0) {
if (yyres) { if (yyres) {
yystpcpy(yyres, "end of file"); yystpcpy(yyres, "end of file");
} }
return sizeof("end of file")-1; return sizeof("end of file")-1;
} }
str = LANG_SCNG(yy_text); /* Prevent the backslash getting doubled in the output (eugh) */
end = memchr(str, '\n', LANG_SCNG(yy_leng)); if (strcmp(toktype, "\"'\\\\'\"") == 0) {
yystr_len = (unsigned int)strlen(yystr); if (yyres) {
yystpcpy(yyres, "token \"\\\"");
if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL
&& (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) {
toklen = (tok2 - tok1) + 1;
} else {
tok1 = tok2 = NULL;
toklen = 0;
}
if (end == NULL) {
len = LANG_SCNG(yy_leng) > 30 ? 30 : LANG_SCNG(yy_leng);
} else {
len = (end - str) > 30 ? 30 : (end - str);
}
if (yyres) {
if (toklen) {
snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1);
} else {
snprintf(buffer, sizeof(buffer), "'%.*s'", len, str);
} }
return sizeof("token \"\\\"")-1;
}
/* Avoid unreadable """ */
/* "'" would theoretically be just as bad, but is never currently parsed as a separate token */
if (strcmp(toktype, "'\"'") == 0) {
if (yyres) {
yystpcpy(yyres, "double-quote mark");
}
return sizeof("double-quote mark")-1;
}
/* Strip off the outer quote marks */
if (toktype_len >= 2 && *toktype == '"') {
toktype++;
toktype_len -= 2;
}
/* If the token always has one form, the %token line should have a single-quoted name */
/* The parser rules also include single-character un-named tokens which will be single-quoted here */
/* We re-format this with double quotes here to ensure everything's consistent */
if (toktype_len > 0 && *toktype == '\'') {
if (yyres) {
snprintf(buffer, sizeof(buffer), "token \"%.*s\"", (int)toktype_len-2, toktype+1);
yystpcpy(yyres, buffer);
}
return toktype_len + sizeof("token ")-1;
}
/* Fetch the content of the last seen token from global lexer state */
tokcontent = LANG_SCNG(yy_text);
tokcontent_len = LANG_SCNG(yy_leng);
/* For T_BAD_CHARACTER, the content probably won't be a printable char */
/* Also, "unexpected invalid character" sounds a bit redundant */
if (tokcontent_len == 1 && strcmp(yystr, "\"invalid character\"") == 0) {
if (yyres) {
snprintf(buffer, sizeof(buffer), "character 0x%02hhX", *tokcontent);
yystpcpy(yyres, buffer);
}
return sizeof("character 0x00")-1;
}
/* Truncate at line end to avoid messing up log formats */
tokcontent_end = memchr(tokcontent, '\n', tokcontent_len);
if (tokcontent_end != NULL) {
tokcontent_len = (tokcontent_end - tokcontent);
}
/* Try to be helpful about what kind of string was found, before stripping the quotes */
if (tokcontent_len > 0 && strcmp(yystr, "\"quoted string\"") == 0) {
if (*tokcontent == '"') {
toktype = "double-quoted string";
toktype_len = sizeof("double-quoted string")-1;
}
else if (*tokcontent == '\'') {
toktype = "single-quoted string";
toktype_len = sizeof("single-quoted string")-1;
}
}
/* For quoted strings, strip off another layer of quotes to avoid putting quotes inside quotes */
if (tokcontent_len > 0 && (*tokcontent == '\'' || *tokcontent=='"')) {
tokcontent++;
tokcontent_len--;
}
if (tokcontent_len > 0 && (tokcontent[tokcontent_len-1] == '\'' || tokcontent[tokcontent_len-1] == '"')) {
tokcontent_len--;
}
/* Truncate to 30 characters and add a ... */
if (tokcontent_len > 30 + sizeof("...")-1) {
if (yyres) {
snprintf(buffer, sizeof(buffer), "%.*s \"%.*s...\"", (int)toktype_len, toktype, 30, tokcontent);
yystpcpy(yyres, buffer);
}
return toktype_len + 30 + sizeof(" \"...\"")-1;
}
if (yyres) {
snprintf(buffer, sizeof(buffer), "%.*s \"%.*s\"", (int)toktype_len, toktype, (int)tokcontent_len, tokcontent);
yystpcpy(yyres, buffer); yystpcpy(yyres, buffer);
} }
return len + (toklen ? toklen + 1 : 0) + 2; return toktype_len + tokcontent_len + sizeof(" \"\"")-1;
} }
/* One of the expected tokens */ /* One of the expected tokens */
if (!yyres) {
return strlen(yystr) - (*yystr == '"' ? 2 : 0);
}
if (*yystr == '"') { /* Prevent the backslash getting doubled in the output (eugh) */
YYSIZE_T yyn = 0; if (strcmp(toktype, "\"'\\\\'\"") == 0) {
const char *yyp = yystr; if (yyres) {
yystpcpy(yyres, "\"\\\"");
for (; *++yyp != '"'; ++yyn) {
yyres[yyn] = *yyp;
} }
yyres[yyn] = '\0'; return sizeof("\"\\\"")-1;
return yyn;
} }
yystpcpy(yyres, yystr);
return strlen(yystr); /* Strip off the outer quote marks */
if (toktype_len >= 2 && *toktype == '"') {
toktype++;
toktype_len -= 2;
}
if (yyres) {
YYSIZE_T yyn = 0;
for (; yyn < toktype_len; ++yyn) {
/* Replace single quotes with double for consistency */
if (toktype[yyn] == '\'') {
yyres[yyn] = '"';
}
else {
yyres[yyn] = toktype[yyn];
}
}
yyres[toktype_len] = '\0';
}
return toktype_len;
} }

View file

@ -14,4 +14,4 @@ function load_file() {
} }
?> ?>
--EXPECT-- --EXPECT--
ParseError: syntax error, unexpected 'if' (T_IF), expecting function (T_FUNCTION) or const (T_CONST) ParseError: syntax error, unexpected token "if", expecting "function" or "const"

View file

@ -14,4 +14,4 @@ new Foo;
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected 'ha' (T_STRING) in %s on line %d Parse error: syntax error, unexpected identifier "ha" in %s on line %d

View file

@ -15,5 +15,5 @@ echo "Done";
?> ?>
--EXPECT-- --EXPECT--
syntax error, unexpected 'code' (T_STRING) syntax error, unexpected identifier "code"
Done Done

View file

@ -326,11 +326,11 @@ Line 2: T_END_HEREDOC (' INNER_END')
Test case 5 Test case 5
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) on line 2 Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" on line 2
Test case 6 Test case 6
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) on line 2 Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" on line 2
Test case 7 Test case 7
@ -409,8 +409,8 @@ Line 3: T_END_HEREDOC (' INNER_END')
Test case 17 Test case 17
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) on line 4 Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" on line 4
Test case 18 Test case 18
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) on line 4 Parse error: syntax error, unexpected end of file, expecting variable or heredoc end or "${" or "{$" on line 4

View file

@ -10,4 +10,4 @@ echo "$arr['foo']";
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: %s error, %s(T_STRING)%s(T_VARIABLE)%s(T_NUM_STRING)%sin %sbug21820.php on line %d Parse error: %s error, %sidentifier%svariable%snumber%sin %sbug21820.php on line %d

View file

@ -10,4 +10,4 @@ eval("
?> ?>
--EXPECTF-- --EXPECTF--
Parse error: syntax error, unexpected '%s' (T_BAD_CHARACTER) in %s on line %d Parse error: syntax error, unexpected character 0x7F in %s on line %d