Merge pull request #228 from TysonAndre/fix-unary-lhs-binary
For #19: Fix an edge case parsing `=` and `instanceof`
This commit is contained in:
Коммит
694b1538bb
|
@ -1686,8 +1686,35 @@ class Parser {
|
|||
//
|
||||
// After we finish building the BinaryExpression, we rebuild the UnaryExpression so that it includes
|
||||
// the original operator, and the newly constructed exponentiation-expression as the operand.
|
||||
$shouldOperatorTakePrecedenceOverUnary =
|
||||
$token->kind === TokenKind::AsteriskAsteriskToken && $leftOperand instanceof UnaryExpression;
|
||||
$shouldOperatorTakePrecedenceOverUnary = false;
|
||||
switch ($token->kind) {
|
||||
case TokenKind::AsteriskAsteriskToken:
|
||||
$shouldOperatorTakePrecedenceOverUnary = $leftOperand instanceof UnaryExpression;
|
||||
break;
|
||||
case TokenKind::EqualsToken:
|
||||
case TokenKind::AsteriskAsteriskEqualsToken:
|
||||
case TokenKind::AsteriskEqualsToken:
|
||||
case TokenKind::SlashEqualsToken:
|
||||
case TokenKind::PercentEqualsToken:
|
||||
case TokenKind::PlusEqualsToken:
|
||||
case TokenKind::MinusEqualsToken:
|
||||
case TokenKind::DotEqualsToken:
|
||||
case TokenKind::LessThanLessThanEqualsToken:
|
||||
case TokenKind::GreaterThanGreaterThanEqualsToken:
|
||||
case TokenKind::AmpersandEqualsToken:
|
||||
case TokenKind::CaretEqualsToken:
|
||||
case TokenKind::BarEqualsToken:
|
||||
case TokenKind::InstanceOfKeyword:
|
||||
// Workarounds for https://github.com/Microsoft/tolerant-php-parser/issues/19#issue-201714377
|
||||
// Parse `!$a = $b` as `!($a = $b)` - PHP constrains the Left Hand Side of an assignment to a variable. A unary operator (`@`, `!`, etc.) is not a variable.
|
||||
// Instanceof has similar constraints for the LHS.
|
||||
// So does `!$a += $b`
|
||||
// TODO: Any other operators?
|
||||
if ($leftOperand instanceof UnaryOpExpression) {
|
||||
$shouldOperatorTakePrecedenceOverUnary = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($shouldOperatorTakePrecedenceOverUnary) {
|
||||
$unaryExpression = $leftOperand;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
echo ~$b = $c;
|
|
@ -0,0 +1 @@
|
|||
[]
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"EchoExpression": {
|
||||
"echoKeyword": {
|
||||
"kind": "EchoKeyword",
|
||||
"textLength": 4
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"UnaryOpExpression": {
|
||||
"operator": {
|
||||
"kind": "TildeToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"operand": {
|
||||
"AssignmentExpression": {
|
||||
"leftOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"kind": "EqualsToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"byRef": null,
|
||||
"rightOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
echo !$b += $c;
|
|
@ -0,0 +1 @@
|
|||
[]
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"EchoExpression": {
|
||||
"echoKeyword": {
|
||||
"kind": "EchoKeyword",
|
||||
"textLength": 4
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"UnaryOpExpression": {
|
||||
"operator": {
|
||||
"kind": "ExclamationToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"operand": {
|
||||
"BinaryExpression": {
|
||||
"leftOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"kind": "PlusEqualsToken",
|
||||
"textLength": 2
|
||||
},
|
||||
"rightOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
echo !$b instanceof $c;
|
|
@ -0,0 +1 @@
|
|||
[]
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"EchoExpression": {
|
||||
"echoKeyword": {
|
||||
"kind": "EchoKeyword",
|
||||
"textLength": 4
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"UnaryOpExpression": {
|
||||
"operator": {
|
||||
"kind": "ExclamationToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"operand": {
|
||||
"BinaryExpression": {
|
||||
"leftOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"kind": "InstanceOfKeyword",
|
||||
"textLength": 10
|
||||
},
|
||||
"rightOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
echo -$b ^= $c;
|
|
@ -0,0 +1 @@
|
|||
[]
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"SourceFileNode": {
|
||||
"statementList": [
|
||||
{
|
||||
"InlineHtml": {
|
||||
"scriptSectionEndTag": null,
|
||||
"text": null,
|
||||
"scriptSectionStartTag": {
|
||||
"kind": "ScriptSectionStartTag",
|
||||
"textLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ExpressionStatement": {
|
||||
"expression": {
|
||||
"EchoExpression": {
|
||||
"echoKeyword": {
|
||||
"kind": "EchoKeyword",
|
||||
"textLength": 4
|
||||
},
|
||||
"expressions": {
|
||||
"ExpressionList": {
|
||||
"children": [
|
||||
{
|
||||
"UnaryOpExpression": {
|
||||
"operator": {
|
||||
"kind": "MinusToken",
|
||||
"textLength": 1
|
||||
},
|
||||
"operand": {
|
||||
"BinaryExpression": {
|
||||
"leftOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"kind": "CaretEqualsToken",
|
||||
"textLength": 2
|
||||
},
|
||||
"rightOperand": {
|
||||
"Variable": {
|
||||
"dollar": null,
|
||||
"name": {
|
||||
"kind": "VariableName",
|
||||
"textLength": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"semicolon": {
|
||||
"kind": "SemicolonToken",
|
||||
"textLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"endOfFileToken": {
|
||||
"kind": "EndOfFileToken",
|
||||
"textLength": 0
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче