Distinguish declare(); and declare(){}

It makes semantic difference and the latter form is actually
forbidden for strict_types.

This sets Declare->stmts to null for the body-less case.
This commit is contained in:
Nikita Popov 2015-12-07 12:12:00 +01:00
parent c542e5d86a
commit 719ca71d4a
9 changed files with 2943 additions and 2892 deletions

View File

@ -136,7 +136,7 @@ inner_statement:
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
;
statement:
non_empty_statement:
'{' inner_statement_list '}' { $$ = $2; }
| T_IF parentheses_expr statement elseif_list else_single
{ $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; }
@ -165,7 +165,6 @@ statement:
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_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 optional_finally
{ $$ = Stmt\TryCatch[$3, $5, $6]; }
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
@ -174,6 +173,11 @@ statement:
| error { $$ = array(); /* means: no statement */ }
;
statement:
non_empty_statement { $$ = $1; }
| ';' { $$ = array(); /* means: no statement */ }
;
catches:
/* empty */ { init(); }
| catches catch { push($1, $2); }
@ -255,7 +259,8 @@ foreach_statement:
;
declare_statement:
statement { $$ = toArray($1); }
non_empty_statement { $$ = toArray($1); }
| ';' { $$ = null; }
| ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
;

View File

@ -136,7 +136,7 @@ inner_statement:
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
;
statement:
non_empty_statement:
'{' inner_statement_list '}' { $$ = $2; }
| T_IF '(' expr ')' statement elseif_list else_single
{ $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; }
@ -161,7 +161,6 @@ statement:
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_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 optional_finally
{ $$ = Stmt\TryCatch[$3, $5, $6]; }
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
@ -170,6 +169,11 @@ statement:
| error { $$ = array(); /* means: no statement */ }
;
statement:
non_empty_statement { $$ = $1; }
| ';' { $$ = array(); /* means: no statement */ }
;
catches:
/* empty */ { init(); }
| catches catch { push($1, $2); }
@ -251,7 +255,8 @@ foreach_statement:
;
declare_statement:
statement { $$ = toArray($1); }
non_empty_statement { $$ = toArray($1); }
| ';' { $$ = null; }
| ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
;

View File

@ -14,10 +14,10 @@ class Declare_ extends Node\Stmt
* Constructs a declare node.
*
* @param DeclareDeclare[] $declares List of declares
* @param Node[] $stmts Statements
* @param Node[]|null $stmts Statements
* @param array $attributes Additional attributes
*/
public function __construct(array $declares, array $stmts, array $attributes = array()) {
public function __construct(array $declares, array $stmts = null, array $attributes = array()) {
parent::__construct($attributes);
$this->declares = $declares;
$this->stmts = $stmts;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -609,12 +609,12 @@ class Standard extends PrettyPrinterAbstract
}
public function pStmt_Declare(Stmt\Declare_ $node) {
return 'declare (' . $this->pCommaSeparated($node->declares) . ') {'
. $this->pStmts($node->stmts) . "\n" . '}';
return 'declare (' . $this->pCommaSeparated($node->declares) . ')'
. (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . "\n" . '}' : ';');
}
public function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) {
return $node->key . ' = ' . $this->p($node->value);
return $node->key . '=' . $this->p($node->value);
}
// Control flow

View File

@ -2,6 +2,8 @@ Declare
-----
<?php
declare (X='Y');
declare (A='B', C='D') {}
declare (A='B', C='D'):
@ -11,20 +13,13 @@ array(
0: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: A
key: X
value: Scalar_String(
value: B
)
)
1: Stmt_DeclareDeclare(
key: C
value: Scalar_String(
value: D
value: Y
)
)
)
stmts: array(
)
stmts: null
)
1: Stmt_Declare(
declares: array(
@ -44,4 +39,22 @@ array(
stmts: array(
)
)
2: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: A
value: Scalar_String(
value: B
)
)
1: Stmt_DeclareDeclare(
key: C
value: Scalar_String(
value: D
)
)
)
stmts: array(
)
)
)

View File

@ -19,8 +19,7 @@ array(
)
)
)
stmts: array(
)
stmts: null
)
1: Stmt_Namespace(
name: Name(

View File

@ -0,0 +1,17 @@
declare
-----
<?php
declare (strict_types=1);
declare (ticks=1) {
foo();
}
declare (ticks=2) {
}
-----
declare (strict_types=1);
declare (ticks=1) {
foo();
}
declare (ticks=2) {
}