mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-26 20:04:48 +01:00
Add support for finally clauses (PHP 5.5)
This adds a new finallyStmts subnode to the TryCatch node. If there is no finally clause it will be null.
This commit is contained in:
parent
f8f1e17e41
commit
ae3774f0f2
@ -1,6 +1,9 @@
|
||||
Version 0.9.3-dev
|
||||
-----------------
|
||||
|
||||
* [PHP 5.5] Add support for `finally`. This adds a new `finallyStmts` subnode to the `TryCatch` node. If there is no
|
||||
finally clause it will be `null`.
|
||||
|
||||
* [BC] [PHP 5.5] Add support for `list()` destructuring of `foreach` values.
|
||||
Example: `foreach ($coords as list($x, $y)) { ... }`
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
%token T_RETURN
|
||||
%token T_TRY
|
||||
%token T_CATCH
|
||||
%token T_FINALLY
|
||||
%token T_THROW
|
||||
%token T_USE
|
||||
%token T_INSTEADOF
|
||||
@ -195,14 +196,15 @@ statement:
|
||||
{ $$ = Stmt_Foreach[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; }
|
||||
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt_Declare[$3, $5]; }
|
||||
| ';' { $$ = array(); /* means: no statement */ }
|
||||
| T_TRY '{' inner_statement_list '}' catches { $$ = Stmt_TryCatch[$3, $5]; }
|
||||
| T_TRY '{' inner_statement_list '}' catches optional_finally
|
||||
{ $$ = Stmt_TryCatch[$3, $5, $6]; }
|
||||
| T_THROW expr ';' { $$ = Stmt_Throw[$2]; }
|
||||
| T_GOTO T_STRING ';' { $$ = Stmt_Goto[$2]; }
|
||||
| T_STRING ':' { $$ = Stmt_Label[$1]; }
|
||||
;
|
||||
|
||||
catches:
|
||||
catch { init($1); }
|
||||
/* empty */ { init(); }
|
||||
| catches catch { push($1, $2); }
|
||||
;
|
||||
|
||||
@ -211,6 +213,11 @@ catch:
|
||||
{ $$ = Stmt_Catch[$3, parseVar($4), $7]; }
|
||||
;
|
||||
|
||||
optional_finally:
|
||||
/* empty */ { $$ = null; }
|
||||
| T_FINALLY '{' inner_statement_list '}' { $$ = $3; }
|
||||
;
|
||||
|
||||
variables_list:
|
||||
variable { init($1); }
|
||||
| variables_list ',' variable { push($1, $3); }
|
||||
|
@ -11,31 +11,32 @@ class PHPParser_Lexer_Emulative extends PHPParser_Lexer
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$newKeywordsPerVersion = array(
|
||||
'5.5.0-dev' => array(
|
||||
'finally' => PHPParser_Parser::T_FINALLY,
|
||||
),
|
||||
'5.4.0-dev' => array(
|
||||
'callable' => PHPParser_Parser::T_CALLABLE,
|
||||
'insteadof' => PHPParser_Parser::T_INSTEADOF,
|
||||
'trait' => PHPParser_Parser::T_TRAIT,
|
||||
'__trait__' => PHPParser_Parser::T_TRAIT_C,
|
||||
),
|
||||
'5.3.0-dev' => array(
|
||||
'__dir__' => PHPParser_Parser::T_DIR,
|
||||
'goto' => PHPParser_Parser::T_GOTO,
|
||||
'namespace' => PHPParser_Parser::T_NAMESPACE,
|
||||
'__namespace__' => PHPParser_Parser::T_NS_C,
|
||||
),
|
||||
);
|
||||
|
||||
$this->newKeywords = array();
|
||||
foreach ($newKeywordsPerVersion as $version => $newKeywords) {
|
||||
if (version_compare(PHP_VERSION, $version, '>=')) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.4.0RC1', '>=')) {
|
||||
return;
|
||||
$this->newKeywords += $newKeywords;
|
||||
}
|
||||
|
||||
// new PHP 5.4 keywords
|
||||
$this->newKeywords += array(
|
||||
'callable' => PHPParser_Parser::T_CALLABLE,
|
||||
'insteadof' => PHPParser_Parser::T_INSTEADOF,
|
||||
'trait' => PHPParser_Parser::T_TRAIT,
|
||||
'__trait__' => PHPParser_Parser::T_TRAIT_C,
|
||||
);
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// new PHP 5.3 keywords
|
||||
$this->newKeywords += array(
|
||||
'__dir__' => PHPParser_Parser::T_DIR,
|
||||
'goto' => PHPParser_Parser::T_GOTO,
|
||||
'namespace' => PHPParser_Parser::T_NAMESPACE,
|
||||
'__namespace__' => PHPParser_Parser::T_NS_C,
|
||||
);
|
||||
}
|
||||
|
||||
public function startLexing($code) {
|
||||
|
@ -1,23 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @property PHPParser_Node[] $stmts Statements
|
||||
* @property PHPParser_Node_Stmt_Catch[] $catches Catches
|
||||
* @property PHPParser_Node[] $stmts Statements
|
||||
* @property PHPParser_Node_Stmt_Catch[] $catches Catches
|
||||
* @property PHPParser_Node[] $finallyStmts Finally statements
|
||||
*/
|
||||
class PHPParser_Node_Stmt_TryCatch extends PHPParser_Node_Stmt
|
||||
{
|
||||
/**
|
||||
* Constructs a try catch node.
|
||||
*
|
||||
* @param PHPParser_Node[] $stmts Statements
|
||||
* @param PHPParser_Node_Stmt_Catch[] $catches Catches
|
||||
* @param array $attributes Additional attributes
|
||||
* @param PHPParser_Node[] $stmts Statements
|
||||
* @param PHPParser_Node_Stmt_Catch[] $catches Catches
|
||||
* @param PHPParser_Node[] $finallyStmts Finally statements (null means no finally clause)
|
||||
* @param array|null $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $stmts, array $catches, array $attributes = array()) {
|
||||
public function __construct(array $stmts, array $catches, array $finallyStmts = null, array $attributes = array()) {
|
||||
if (empty($catches) && null === $finallyStmts) {
|
||||
throw new PHPParser_Error('Cannot use try without catch or finally');
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
array(
|
||||
'stmts' => $stmts,
|
||||
'catches' => $catches,
|
||||
'stmts' => $stmts,
|
||||
'catches' => $catches,
|
||||
'finallyStmts' => $finallyStmts,
|
||||
),
|
||||
$attributes
|
||||
);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,92 @@
|
||||
Try/catch
|
||||
-----
|
||||
<?php
|
||||
|
||||
try {
|
||||
|
||||
doTry();
|
||||
} catch (A $b) {
|
||||
|
||||
doCatchA();
|
||||
} catch (B $c) {
|
||||
|
||||
doCatchB();
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
|
||||
// no finally
|
||||
try { }
|
||||
catch (A $b) { }
|
||||
|
||||
// no catch
|
||||
try { }
|
||||
finally { }
|
||||
|
||||
-----
|
||||
array(
|
||||
0: Stmt_TryCatch(
|
||||
stmts: array(
|
||||
0: Expr_FuncCall(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: doTry
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
catches: array(
|
||||
0: Stmt_Catch(
|
||||
type: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
var: b
|
||||
stmts: array(
|
||||
0: Expr_FuncCall(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: doCatchA
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_Catch(
|
||||
type: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
)
|
||||
)
|
||||
var: c
|
||||
stmts: array(
|
||||
0: Expr_FuncCall(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: doCatchB
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
finallyStmts: array(
|
||||
0: Expr_FuncCall(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: doFinally
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_TryCatch(
|
||||
stmts: array(
|
||||
)
|
||||
catches: array(
|
||||
@ -24,16 +100,15 @@ array(
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
1: Stmt_Catch(
|
||||
type: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
)
|
||||
)
|
||||
var: c
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
finallyStmts: null
|
||||
)
|
||||
2: Stmt_TryCatch(
|
||||
stmts: array(
|
||||
)
|
||||
catches: array(
|
||||
)
|
||||
finallyStmts: array(
|
||||
)
|
||||
)
|
||||
)
|
7
test/code/parser/stmt/tryCatch.test-fail
Normal file
7
test/code/parser/stmt/tryCatch.test-fail
Normal file
@ -0,0 +1,7 @@
|
||||
Cannot use try without catch or finally
|
||||
-----
|
||||
<?php
|
||||
|
||||
try { }
|
||||
-----
|
||||
Cannot use try without catch or finally on line 3
|
Loading…
Reference in New Issue
Block a user