Only allow parsing unset() as a top-level statement
E.g. `unset($x)/2` is a syntax error. Previously, this parser would not treat that as a syntax error. This is similar to how `echo` can only be used as a top level statement. - Tools using this parser may expect `unset` only as a top level statement See https://secure.php.net/manual/en/function.unset.php#refsect1-function.unset-notes
This commit is contained in:
Родитель
7ea773435b
Коммит
c9a8793682
|
@ -571,6 +571,9 @@ class Parser {
|
|||
|
||||
case TokenKind::ScriptSectionEndTag:
|
||||
return $this->parseInlineHtml($parentNode);
|
||||
|
||||
case TokenKind::UnsetKeyword:
|
||||
return $this->parseUnsetStatement($parentNode);
|
||||
}
|
||||
|
||||
$expressionStatement = new ExpressionStatement();
|
||||
|
@ -948,8 +951,6 @@ class Parser {
|
|||
// intrinsic-construct
|
||||
case TokenKind::ListKeyword:
|
||||
return $this->parseListIntrinsicExpression($parentNode);
|
||||
case TokenKind::UnsetKeyword:
|
||||
return $this->parseUnsetIntrinsicExpression($parentNode);
|
||||
|
||||
// intrinsic-operator
|
||||
case TokenKind::EmptyKeyword:
|
||||
|
@ -2210,6 +2211,19 @@ class Parser {
|
|||
return $expressionStatement;
|
||||
}
|
||||
|
||||
private function parseUnsetStatement($parentNode) {
|
||||
$expressionStatement = new ExpressionStatement();
|
||||
|
||||
// TODO: Could flatten into UnsetStatement instead?
|
||||
$unsetExpression = $this->parseUnsetIntrinsicExpression($expressionStatement);
|
||||
|
||||
$expressionStatement->parent = $parentNode;
|
||||
$expressionStatement->expression = $unsetExpression;
|
||||
$expressionStatement->semicolon = $this->eatSemicolonOrAbortStatement();
|
||||
|
||||
return $expressionStatement;
|
||||
}
|
||||
|
||||
private function parseListIntrinsicExpression($parentNode) {
|
||||
$listExpression = new ListIntrinsicExpression();
|
||||
$listExpression->parent = $parentNode;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
unset($x, $y)
|
||||
/ comment_fragment();
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
{
|
||||
"kind": 0,
|
||||
"message": "';' expected.",
|
||||
"start": 19,
|
||||
"length": 0
|
||||
},
|
||||
{
|
||||
"kind": 0,
|
||||
"message": "Unexpected '\/'",
|
||||
"start": 20,
|
||||
"length": 1
|
||||
}
|
||||
]
|
|
@ -0,0 +1,111 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"UnsetIntrinsicExpression": {
|
||||
"unsetKeyword": {
|
||||
"kind": "UnsetKeyword",
|
||||
"textLength": 5
|
||||
},
|
||||
"openParen": {
|
||||
"kind": "OpenParenToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "CommaToken",
|
||||
"textLength": 1
|
||||
},
|
||||
{
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"closeParen": {
|
||||
"kind": "CloseParenToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"error": "MissingToken",
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"error": "SkippedToken",
|
||||
"kind": "SlashToken",
|
||||
"textLength": 1
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"CallExpression": {
|
||||
"callableExpression": {
|
||||
"QualifiedName": {
|
||||
"globalSpecifier": null,
|
||||
"relativeSpecifier": null,
|
||||
"nameParts": [
|
||||
{
|
||||
"kind": "Name",
|
||||
"textLength": 16
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"openParen": {
|
||||
"kind": "OpenParenToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"argumentExpressionList": null,
|
||||
"closeParen": {
|
||||
"kind": "CloseParenToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
2 / unset($x);
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
{
|
||||
"kind": 0,
|
||||
"message": "'Expression' expected.",
|
||||
"start": 9,
|
||||
"length": 0
|
||||
},
|
||||
{
|
||||
"kind": 0,
|
||||
"message": "';' expected.",
|
||||
"start": 9,
|
||||
"length": 0
|
||||
}
|
||||
]
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"BinaryExpression": {
|
||||
"leftOperand": {
|
||||
"NumericLiteral": {
|
||||
"children": {
|
||||
"kind": "IntegerLiteralToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"kind": "SlashToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"rightOperand": {
|
||||
"error": "MissingToken",
|
||||
"kind": "Expression",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"error": "MissingToken",
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"UnsetIntrinsicExpression": {
|
||||
"unsetKeyword": {
|
||||
"kind": "UnsetKeyword",
|
||||
"textLength": 5
|
||||
},
|
||||
"openParen": {
|
||||
"kind": "OpenParenToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"closeParen": {
|
||||
"kind": "CloseParenToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче