1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\ExpressionParser\Infix;
13
14use Twig\Error\SyntaxError;
15use Twig\ExpressionParser\InfixAssociativity;
16use Twig\Node\Expression\AbstractExpression;
17use Twig\Node\Expression\ArrayExpression;
18use Twig\Node\Expression\Binary\AbstractBinary;
19use Twig\Node\Expression\Binary\ObjectDestructuringSetBinary;
20use Twig\Node\Expression\Binary\SequenceDestructuringSetBinary;
21use Twig\Node\Expression\Binary\SetBinary;
22use Twig\Node\Expression\Variable\ContextVariable;
23use Twig\Parser;
24use Twig\Token;
25
26/**
27 * @internal
28 */
29class AssignmentExpressionParser extends BinaryOperatorExpressionParser
30{
31    public function __construct(
32        string $name,
33    ) {
34        parent::__construct(SetBinary::class, $name, 0, InfixAssociativity::Right);
35    }
36
37    /**
38     * @return AbstractBinary
39     */
40    public function parse(Parser $parser, AbstractExpression $left, Token $token): AbstractExpression
41    {
42        if (!$left instanceof ContextVariable && !$left instanceof ArrayExpression) {
43            throw new SyntaxError(\sprintf('Cannot assign to "%s", only variables can be assigned.', $left::class), $token->getLine(), $parser->getStream()->getSourceContext());
44        }
45        $right = $parser->parseExpression(InfixAssociativity::Left === $this->getAssociativity() ? $this->getPrecedence() + 1 : $this->getPrecedence());
46        $right = match ($this->getName()) {
47            '=' => $right,
48            default => throw new \LogicException(\sprintf('Unknown operator: %s.', $this->getName())),
49        };
50
51        if ($left instanceof ArrayExpression) {
52            if ($left->isSequence()) {
53                return new SequenceDestructuringSetBinary($left, $right, $token->getLine());
54            }
55
56            return new ObjectDestructuringSetBinary($left, $right, $token->getLine());
57        }
58
59        return new SetBinary($left, $right, $token->getLine());
60    }
61
62    public function getDescription(): string
63    {
64        return 'Assignment operator';
65    }
66}
67