Treat assignments as unary operators

Assignment expressions can be viewed as unary operators where
the whole "$x =" part is the operator.
This commit is contained in:
Nikita Popov 2022-07-23 21:53:48 +02:00
parent 7bf6348240
commit 59145a4443
2 changed files with 19 additions and 43 deletions

View File

@ -236,63 +236,63 @@ class Standard extends PrettyPrinterAbstract
// Assignments // Assignments
protected function pExpr_Assign(Expr\Assign $node) { protected function pExpr_Assign(Expr\Assign $node) {
return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr); return $this->pPrefixOp(Expr\Assign::class, $this->p($node->var) . ' = ', $node->expr);
} }
protected function pExpr_AssignRef(Expr\AssignRef $node) { protected function pExpr_AssignRef(Expr\AssignRef $node) {
return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr); return $this->pPrefixOp(Expr\AssignRef::class, $this->p($node->var) . ' =& ', $node->expr);
} }
protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) {
return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr); return $this->pPrefixOp(AssignOp\Plus::class, $this->p($node->var) . ' += ', $node->expr);
} }
protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) {
return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr); return $this->pPrefixOp(AssignOp\Minus::class, $this->p($node->var) . ' -= ', $node->expr);
} }
protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) {
return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr); return $this->pPrefixOp(AssignOp\Mul::class, $this->p($node->var) . ' *= ', $node->expr);
} }
protected function pExpr_AssignOp_Div(AssignOp\Div $node) { protected function pExpr_AssignOp_Div(AssignOp\Div $node) {
return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr); return $this->pPrefixOp(AssignOp\Div::class, $this->p($node->var) . ' /= ', $node->expr);
} }
protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) {
return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr); return $this->pPrefixOp(AssignOp\Concat::class, $this->p($node->var) . ' .= ', $node->expr);
} }
protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) {
return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr); return $this->pPrefixOp(AssignOp\Mod::class, $this->p($node->var) . ' %= ', $node->expr);
} }
protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) {
return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); return $this->pPrefixOp(AssignOp\BitwiseAnd::class, $this->p($node->var) . ' &= ', $node->expr);
} }
protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) {
return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); return $this->pPrefixOp(AssignOp\BitwiseOr::class, $this->p($node->var) . ' |= ', $node->expr);
} }
protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) {
return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); return $this->pPrefixOp(AssignOp\BitwiseXor::class, $this->p($node->var) . ' ^= ', $node->expr);
} }
protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) {
return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); return $this->pPrefixOp(AssignOp\ShiftLeft::class, $this->p($node->var) . ' <<= ', $node->expr);
} }
protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) {
return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); return $this->pPrefixOp(AssignOp\ShiftRight::class, $this->p($node->var) . ' >>= ', $node->expr);
} }
protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) {
return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr); return $this->pPrefixOp(AssignOp\Pow::class, $this->p($node->var) . ' **= ', $node->expr);
} }
protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) { protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) {
return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); return $this->pPrefixOp(AssignOp\Coalesce::class, $this->p($node->var) . ' ??= ', $node->expr);
} }
// Binary expressions // Binary expressions

View File

@ -63,7 +63,6 @@ abstract class PrettyPrinterAbstract
BinaryOp\BooleanOr::class => [130, -1], BinaryOp\BooleanOr::class => [130, -1],
BinaryOp\Coalesce::class => [140, 1], BinaryOp\Coalesce::class => [140, 1],
Expr\Ternary::class => [150, 0], Expr\Ternary::class => [150, 0],
// parser uses %left for assignments, but they really behave as %right
Expr\Assign::class => [160, 1], Expr\Assign::class => [160, 1],
Expr\AssignRef::class => [160, 1], Expr\AssignRef::class => [160, 1],
AssignOp\Plus::class => [160, 1], AssignOp\Plus::class => [160, 1],
@ -337,20 +336,6 @@ abstract class PrettyPrinterAbstract
return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); return $operatorString . $this->pPrec($node, $precedence, $associativity, 1);
} }
/**
* Pretty-print a postfix operation while taking precedence into account.
*
* @param string $class Node class of operator
* @param string $operatorString String representation of the operator
* @param Node $node Node
*
* @return string Pretty printed postfix operation
*/
protected function pPostfixOp(string $class, Node $node, string $operatorString) : string {
list($precedence, $associativity) = $this->precedenceMap[$class];
return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString;
}
/** /**
* Prints an expression node with the least amount of parentheses necessary to preserve the meaning. * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
* *
@ -1222,24 +1207,15 @@ abstract class PrettyPrinterAbstract
]; ];
} }
$assignOps = [
Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class,
AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class,
AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class,
AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class
];
foreach ($assignOps as $assignOp) {
$this->fixupMap[$assignOp] = [
'var' => self::FIXUP_PREC_LEFT,
'expr' => self::FIXUP_PREC_RIGHT,
];
}
$prefixOps = [ $prefixOps = [
Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class,
Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class,
Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class,
Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class,
Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class,
AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class,
AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class,
AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class
]; ];
foreach ($prefixOps as $prefixOp) { foreach ($prefixOps as $prefixOp) {
$this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT];