Merge pull request #228 from TysonAndre/fix-unary-lhs-binary

For #19: Fix an edge case parsing `=` and `instanceof`
This commit is contained in:
Rob Lourens 2018-03-17 21:12:58 -06:00 коммит произвёл GitHub
Родитель 90dc39fb00 d996815820
Коммит 694b1538bb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 350 добавлений и 2 удалений

Просмотреть файл

@ -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
}
}
}