Skip to content

Commit

Permalink
Add information on expected tokens to syntax errors
Browse files Browse the repository at this point in the history
This now mimics the error messages provided by PHP itself (pre 5.4).
  • Loading branch information
nikic committed Jan 15, 2013
1 parent 222c961 commit fbaa1e5
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 11 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
@@ -1,7 +1,11 @@
Version 0.9.4-dev Version 0.9.4-dev
----------------- -----------------


Nothing yet. * Syntax errors now include information on expected tokens and mimic the format of PHP's own (pre 5.4) error messages.
Example:

Old: Unexpected token T_STATIC on line 1
New: Syntax error, unexpected T_STATIC, expecting T_STRING or T_NS_SEPARATOR or '{'


Version 0.9.3 (22.11.2012) Version 0.9.3 (22.11.2012)
-------------------------- --------------------------
Expand Down
29 changes: 28 additions & 1 deletion grammar/kmyacc.php.parser
Expand Up @@ -304,8 +304,35 @@ class #(-p)
$attributeStack[$this->stackPos] = $startAttributes; $attributeStack[$this->stackPos] = $startAttributes;
} else { } else {
/* error */ /* error */
$expected = array();

$base = self::$yybase[$state];
for ($i = 0; $i < self::TOKEN_MAP_SIZE; ++$i) {
$n = $base + $i;
if ($n >= 0 && $n < self::YYLAST && self::$yycheck[$n] == $i
|| $state < self::YY2TBLSTATE
&& ($n = self::$yybase[$state + self::YYNLSTATES] + $i)
&& $n < self::YYLAST && self::$yycheck[$n] == $i
) {
if (self::$yyaction[$n] != self::YYUNEXPECTED) {
if (count($expected) == 4) {
/* Too many expected tokens */
$expected = array();
break;
}

$expected[] = self::$terminals[$i];
}
}
}

$expectedString = '';
if ($expected) {
$expectedString = ', expecting ' . implode(' or ', $expected);
}

throw new PHPParser_Error( throw new PHPParser_Error(
'Unexpected token ' . self::$terminals[$tokenId], 'Syntax error, unexpected ' . self::$terminals[$tokenId] . $expectedString,
$startAttributes['startLine'] $startAttributes['startLine']
); );
} }
Expand Down
29 changes: 28 additions & 1 deletion lib/PHPParser/Parser.php
Expand Up @@ -1068,8 +1068,35 @@ public function parse($code) {
$attributeStack[$this->stackPos] = $startAttributes; $attributeStack[$this->stackPos] = $startAttributes;
} else { } else {
/* error */ /* error */
$expected = array();

$base = self::$yybase[$state];
for ($i = 0; $i < self::TOKEN_MAP_SIZE; ++$i) {
$n = $base + $i;
if ($n >= 0 && $n < self::YYLAST && self::$yycheck[$n] == $i
|| $state < self::YY2TBLSTATE
&& ($n = self::$yybase[$state + self::YYNLSTATES] + $i)
&& $n < self::YYLAST && self::$yycheck[$n] == $i
) {
if (self::$yyaction[$n] != self::YYUNEXPECTED) {
if (count($expected) == 4) {
/* Too many expected tokens */
$expected = array();
break;
}

$expected[] = self::$terminals[$i];
}
}
}

$expectedString = '';
if ($expected) {
$expectedString = ', expecting ' . implode(' or ', $expected);
}

throw new PHPParser_Error( throw new PHPParser_Error(
'Unexpected token ' . self::$terminals[$tokenId], 'Syntax error, unexpected ' . self::$terminals[$tokenId] . $expectedString,
$startAttributes['startLine'] $startAttributes['startLine']
); );
} }
Expand Down
2 changes: 1 addition & 1 deletion test/code/parser/stmt/class/modifier.test-fail
Expand Up @@ -26,4 +26,4 @@ Cannot use the final and abstract modifier at the same time on line 1
----- -----
<?php abstract final class A { } <?php abstract final class A { }
----- -----
Unexpected token T_FINAL on line 1 Syntax error, unexpected T_FINAL, expecting T_CLASS on line 1
10 changes: 5 additions & 5 deletions test/code/parser/stmt/class/name.test-fail
Expand Up @@ -10,7 +10,7 @@ Cannot use "parent" as class name as it is reserved on line 1
----- -----
<?php class static {} <?php class static {}
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING on line 1
----- -----
<?php class A extends self {} <?php class A extends self {}
----- -----
Expand All @@ -22,7 +22,7 @@ Cannot use "parent" as class name as it is reserved on line 1
----- -----
<?php class A extends static {} <?php class A extends static {}
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1
----- -----
<?php class A implements self {} <?php class A implements self {}
----- -----
Expand All @@ -34,7 +34,7 @@ Cannot use "parent" as interface name as it is reserved on line 1
----- -----
<?php class A implements static {} <?php class A implements static {}
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1
----- -----
<?php interface self {} <?php interface self {}
----- -----
Expand All @@ -46,7 +46,7 @@ Cannot use "parent" as interface name as it is reserved on line 1
----- -----
<?php interface static {} <?php interface static {}
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING on line 1
----- -----
<?php interface A extends self {} <?php interface A extends self {}
----- -----
Expand All @@ -58,4 +58,4 @@ Cannot use "parent" as interface name as it is reserved on line 1
----- -----
<?php interface A extends static {} <?php interface A extends static {}
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1
4 changes: 2 additions & 2 deletions test/code/parser/stmt/namespace/name.test-fail
Expand Up @@ -10,7 +10,7 @@ Cannot use "parent" as namespace name as it is reserved on line 1
----- -----
<?php namespace static; <?php namespace static;
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING or T_NS_SEPARATOR or '{' on line 1
----- -----
<?php use A as self; <?php use A as self;
----- -----
Expand All @@ -22,4 +22,4 @@ Cannot use "B" as "parent" because "parent" is a special class name on line 1
----- -----
<?php use C as static; <?php use C as static;
----- -----
Unexpected token T_STATIC on line 1 Syntax error, unexpected T_STATIC, expecting T_STRING on line 1

0 comments on commit fbaa1e5

Please sign in to comment.