Skip to content

Commit

Permalink
Decrement errorState when recovering from -> error
Browse files Browse the repository at this point in the history
It's likely that an error after -> will trigger another one due to
missing semicolon without shifting a single token. We prevent an
immediate failure in this case by manually setting errorState to 2,
which will suppress the duplicate error message, but allow error
recovery.
  • Loading branch information
nikic committed Jul 25, 2016
1 parent 09086fb commit 977cbab
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 9 deletions.
2 changes: 1 addition & 1 deletion grammar/php5.y
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ object_property:
T_STRING { $$ = $1; }
| '{' expr '}' { $$ = $2; }
| variable_without_objects { $$ = $1; }
| error { $$ = Expr\Error[]; }
| error { $$ = Expr\Error[]; $this->errorState = 2; }
;

list_expr:
Expand Down
2 changes: 1 addition & 1 deletion grammar/php7.y
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ property_name:
T_STRING { $$ = $1; }
| '{' expr '}' { $$ = $2; }
| simple_variable { $$ = Expr\Variable[$1]; }
| error { $$ = Expr\Error[]; }
| error { $$ = Expr\Error[]; $this->errorState = 2; }
;

list_expr:
Expand Down
2 changes: 1 addition & 1 deletion lib/PhpParser/Parser/Php5.php
Original file line number Diff line number Diff line change
Expand Up @@ -3009,7 +3009,7 @@ protected function reduceRule517() {
}

protected function reduceRule518() {
$this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
$this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
}

protected function reduceRule519() {
Expand Down
2 changes: 1 addition & 1 deletion lib/PhpParser/Parser/Php7.php
Original file line number Diff line number Diff line change
Expand Up @@ -2619,7 +2619,7 @@ protected function reduceRule452() {
}

protected function reduceRule453() {
$this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
$this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
}

protected function reduceRule454() {
Expand Down
12 changes: 7 additions & 5 deletions lib/PhpParser/ParserAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ abstract class ParserAbstract implements Parser
protected $throwOnError;
/** @var Error[] Errors collected during last parse */
protected $errors;
/** @var int Error state, used to avoid error floods */
protected $errorState;

/**
* Creates a parser instance.
Expand Down Expand Up @@ -157,7 +159,7 @@ public function parse($code) {
// Current position in the stack(s)
$this->stackPos = 0;

$errorState = 0;
$this->errorState = 0;

for (;;) {
//$this->traceNewState($state, $symbol);
Expand Down Expand Up @@ -216,8 +218,8 @@ public function parse($code) {
$this->endAttributes = $endAttributes;
$symbol = self::SYMBOL_NONE;

if ($errorState) {
--$errorState;
if ($this->errorState) {
--$this->errorState;
}

if ($action < $this->YYNLSTATES) {
Expand Down Expand Up @@ -274,7 +276,7 @@ public function parse($code) {
$this->semStack[$this->stackPos] = $this->semValue;
} else {
/* error */
switch ($errorState) {
switch ($this->errorState) {
case 0:
$msg = $this->getErrorMessage($symbol, $state);
$error = new Error($msg, $startAttributes + $endAttributes);
Expand All @@ -285,7 +287,7 @@ public function parse($code) {
// Break missing intentionally
case 1:
case 2:
$errorState = 3;
$this->errorState = 3;

// Pop until error-expecting state uncovered
while (!(
Expand Down
25 changes: 25 additions & 0 deletions test/code/parser/errorHandling/recovery.test
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,29 @@ array(
name: Expr_Error(
)
)
)
-----
<?php
function foo() {
$bar->
}
-----
Syntax error, unexpected '}' from 4:1 to 4:1
array(
0: Stmt_Function(
byRef: false
name: foo
params: array(
)
returnType: null
stmts: array(
0: Expr_PropertyFetch(
var: Expr_Variable(
name: bar
)
name: Expr_Error(
)
)
)
)
)

0 comments on commit 977cbab

Please sign in to comment.