mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2024-11-26 20:14:46 +01:00
Recover from missing semicolons on statements
This commit is contained in:
parent
5b8182cc0a
commit
62877b5d14
@ -1,7 +1,9 @@
|
||||
Version 3.0.4-dev
|
||||
-----------------
|
||||
|
||||
Nothing yet.
|
||||
### Added
|
||||
|
||||
* Error recovery from missing semicolons is now supported in more cases.
|
||||
|
||||
Version 3.0.3 (2017-02-03)
|
||||
--------------------------
|
||||
|
@ -49,22 +49,27 @@ namespace_name:
|
||||
namespace_name_parts { $$ = Name[$1]; }
|
||||
;
|
||||
|
||||
semi:
|
||||
';' { /* nothing */ }
|
||||
| error { /* nothing */ }
|
||||
;
|
||||
|
||||
top_statement:
|
||||
statement { $$ = $1; }
|
||||
| function_declaration_statement { $$ = $1; }
|
||||
| class_declaration_statement { $$ = $1; }
|
||||
| T_HALT_COMPILER
|
||||
{ $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
|
||||
| T_NAMESPACE namespace_name ';'
|
||||
| T_NAMESPACE namespace_name semi
|
||||
{ $$ = Stmt\Namespace_[$2, null]; $this->checkNamespace($$); }
|
||||
| T_NAMESPACE namespace_name '{' top_statement_list '}'
|
||||
{ $$ = Stmt\Namespace_[$2, $4]; $this->checkNamespace($$); }
|
||||
| T_NAMESPACE '{' top_statement_list '}'
|
||||
{ $$ = Stmt\Namespace_[null, $3]; $this->checkNamespace($$); }
|
||||
| T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
|
||||
| T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; }
|
||||
| group_use_declaration ';' { $$ = $1; }
|
||||
| T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; }
|
||||
| T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
|
||||
| T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; }
|
||||
| group_use_declaration semi { $$ = $1; }
|
||||
| T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; }
|
||||
;
|
||||
|
||||
use_type:
|
||||
@ -165,15 +170,15 @@ non_empty_statement:
|
||||
| T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement
|
||||
{ $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
|
||||
| T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; }
|
||||
| T_BREAK optional_expr ';' { $$ = Stmt\Break_[$2]; }
|
||||
| T_CONTINUE optional_expr ';' { $$ = Stmt\Continue_[$2]; }
|
||||
| T_RETURN optional_expr ';' { $$ = Stmt\Return_[$2]; }
|
||||
| T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; }
|
||||
| T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; }
|
||||
| T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; }
|
||||
| T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; }
|
||||
| T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; }
|
||||
| T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; }
|
||||
| T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; }
|
||||
| T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; }
|
||||
| T_ECHO expr_list semi { $$ = Stmt\Echo_[$2]; }
|
||||
| T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; }
|
||||
| expr ';' { $$ = $1; }
|
||||
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; }
|
||||
| expr semi { $$ = $1; }
|
||||
| T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; }
|
||||
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
|
||||
{ $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; }
|
||||
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
|
||||
@ -181,10 +186,9 @@ non_empty_statement:
|
||||
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; }
|
||||
| T_TRY '{' inner_statement_list '}' catches optional_finally
|
||||
{ $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); }
|
||||
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
|
||||
| T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; }
|
||||
| T_THROW expr semi { $$ = Stmt\Throw_[$2]; }
|
||||
| T_GOTO T_STRING semi { $$ = Stmt\Goto_[$2]; }
|
||||
| T_STRING ':' { $$ = Stmt\Label[$1]; }
|
||||
| expr error { $$ = $1; }
|
||||
| error { $$ = array(); /* means: no statement */ }
|
||||
;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -373,3 +373,141 @@ array(
|
||||
)
|
||||
)
|
||||
)
|
||||
-----
|
||||
<?php
|
||||
namespace Foo
|
||||
use A
|
||||
use function a
|
||||
use A\{B}
|
||||
const A = 1
|
||||
break
|
||||
break 2
|
||||
continue
|
||||
continue 2
|
||||
return
|
||||
return 2
|
||||
echo $a
|
||||
unset($a)
|
||||
throw $x
|
||||
goto label
|
||||
-----
|
||||
!!php7
|
||||
Syntax error, unexpected T_USE, expecting ';' or '{' from 3:1 to 3:3
|
||||
Syntax error, unexpected T_USE, expecting ',' or ';' from 5:1 to 5:3
|
||||
Syntax error, unexpected T_CONST, expecting ';' from 6:1 to 6:5
|
||||
Syntax error, unexpected T_BREAK, expecting ',' or ';' from 7:1 to 7:5
|
||||
Syntax error, unexpected T_THROW, expecting ';' from 15:1 to 15:5
|
||||
array(
|
||||
0: Stmt_Namespace(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
stmts: array(
|
||||
0: Stmt_Use(
|
||||
type: TYPE_NORMAL (1)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
alias: A
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_Use(
|
||||
type: TYPE_FUNCTION (2)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: a
|
||||
)
|
||||
)
|
||||
alias: a
|
||||
)
|
||||
)
|
||||
)
|
||||
2: Stmt_GroupUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_NORMAL (1)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
)
|
||||
)
|
||||
alias: B
|
||||
)
|
||||
)
|
||||
)
|
||||
3: Stmt_Const(
|
||||
consts: array(
|
||||
0: Const(
|
||||
name: A
|
||||
value: Scalar_LNumber(
|
||||
value: 1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
4: Stmt_Break(
|
||||
num: null
|
||||
)
|
||||
5: Stmt_Break(
|
||||
num: Scalar_LNumber(
|
||||
value: 2
|
||||
)
|
||||
)
|
||||
6: Stmt_Continue(
|
||||
num: null
|
||||
)
|
||||
7: Stmt_Continue(
|
||||
num: Scalar_LNumber(
|
||||
value: 2
|
||||
)
|
||||
)
|
||||
8: Stmt_Return(
|
||||
expr: null
|
||||
)
|
||||
9: Stmt_Return(
|
||||
expr: Scalar_LNumber(
|
||||
value: 2
|
||||
)
|
||||
)
|
||||
10: Stmt_Echo(
|
||||
exprs: array(
|
||||
0: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
)
|
||||
)
|
||||
11: Stmt_Unset(
|
||||
vars: array(
|
||||
0: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
)
|
||||
)
|
||||
12: Stmt_Throw(
|
||||
expr: Expr_Variable(
|
||||
name: x
|
||||
)
|
||||
)
|
||||
13: Stmt_Goto(
|
||||
name: label
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
@ -6,7 +6,16 @@ global $$foo->bar;
|
||||
!!php7
|
||||
Syntax error, unexpected T_OBJECT_OPERATOR, expecting ',' or ';' from 2:13 to 2:14
|
||||
array(
|
||||
0: Expr_ConstFetch(
|
||||
0: Stmt_Global(
|
||||
vars: array(
|
||||
0: Expr_Variable(
|
||||
name: Expr_Variable(
|
||||
name: foo
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Expr_ConstFetch(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: bar
|
||||
|
@ -5,9 +5,32 @@ Invalid group use syntax
|
||||
use Foo\{Bar}
|
||||
use Bar\{Foo};
|
||||
-----
|
||||
!!php7
|
||||
Syntax error, unexpected T_USE, expecting ';' from 4:1 to 4:3
|
||||
array(
|
||||
0: Stmt_GroupUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_NORMAL (1)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Bar
|
||||
)
|
||||
)
|
||||
alias: Bar
|
||||
)
|
||||
)
|
||||
comments: array(
|
||||
0: // Missing semicolon
|
||||
)
|
||||
)
|
||||
1: Stmt_GroupUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
@ -32,16 +55,34 @@ array(
|
||||
// Missing NS separator
|
||||
use Foo {Bar, Baz};
|
||||
-----
|
||||
!!php7
|
||||
Syntax error, unexpected '{', expecting ',' or ';' from 3:9 to 3:9
|
||||
array(
|
||||
0: Expr_ConstFetch(
|
||||
0: Stmt_Use(
|
||||
type: TYPE_NORMAL (1)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
alias: Foo
|
||||
)
|
||||
)
|
||||
comments: array(
|
||||
0: // Missing NS separator
|
||||
)
|
||||
)
|
||||
1: Expr_ConstFetch(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Bar
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Expr_ConstFetch(
|
||||
2: Expr_ConstFetch(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Baz
|
||||
|
Loading…
Reference in New Issue
Block a user