Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. Parser.php

function Parser::parseLeftHandSideExpression

Parses a left hand side expression

Return value

Node\Node|null

3 calls to Parser::parseLeftHandSideExpression()
Parser::parseClassHeritage in vendor/mck89/peast/lib/Peast/Syntax/Parser.php
Parses the class extends part
Parser::parseForNotVarLetConstStatement in vendor/mck89/peast/lib/Peast/Syntax/Parser.php
Parses a for statement that does not start with var, let or const
Parser::parsePostfixExpression in vendor/mck89/peast/lib/Peast/Syntax/Parser.php
Parses a postfix expression

File

vendor/mck89/peast/lib/Peast/Syntax/Parser.php, line 3307

Class

Parser
Parser class

Namespace

Peast\Syntax

Code

protected function parseLeftHandSideExpression() {
    $object = null;
    $newTokens = array();
    
    //Parse all occurrences of "new"
    if ($this->scanner
        ->isBefore(array(
        "new",
    ))) {
        while ($newToken = $this->scanner
            ->consume("new")) {
            if ($this->scanner
                ->consume(".")) {
                
                //new.target
                if (!$this->scanner
                    ->consume("target")) {
                    $this->error();
                }
                $node = $this->createNode("MetaProperty", $newToken);
                $node->setMeta("new");
                $node->setProperty("target");
                $object = $this->completeNode($node);
                break;
            }
            $newTokens[] = $newToken;
        }
    }
    elseif ($this->features->importMeta && $this->sourceType === \Peast\Peast::SOURCE_TYPE_MODULE && $this->scanner
        ->isBefore(array(
        array(
            "import",
            ".",
        ),
    ), true)) {
        
        //import.meta
        $importToken = $this->scanner
            ->consume("import");
        $this->scanner
            ->consume(".");
        if (!$this->scanner
            ->consume("meta")) {
            $this->error();
        }
        $node = $this->createNode("MetaProperty", $importToken);
        $node->setMeta("import");
        $node->setProperty("meta");
        $object = $this->completeNode($node);
    }
    $newTokensCount = count($newTokens);
    if (!$object && !($object = $this->parseSuperPropertyOrCall()) && !($this->features->dynamicImport && ($object = $this->parseImportCall())) && !($object = $this->parsePrimaryExpression())) {
        if ($newTokensCount) {
            $this->error();
        }
        return null;
    }
    $valid = true;
    $optionalChain = false;
    $properties = array();
    while (true) {
        $optional = false;
        if ($opToken = $this->scanner
            ->consumeOneOf(array(
            "?.",
            ".",
        ))) {
            $isOptChain = $opToken->value == "?.";
            if ($isOptChain) {
                $optionalChain = $optional = true;
            }
            if ($this->features->privateMethodsAndFields && ($property = $this->parsePrivateIdentifier()) || ($property = $this->parseIdentifier(static::$identifierName))) {
                $valid = true;
                $properties[] = array(
                    "type" => "id",
                    "info" => $property,
                    "optional" => $optional,
                );
                continue;
            }
            else {
                $valid = false;
                if (!$isOptChain) {
                    break;
                }
            }
        }
        if ($this->scanner
            ->consume("[")) {
            if (($property = $this->isolateContext(array(
                "allowIn" => true,
            ), "parseExpression")) && $this->scanner
                ->consume("]")) {
                $valid = true;
                $properties[] = array(
                    "type" => "computed",
                    "info" => array(
                        $property,
                        $this->scanner
                            ->getPosition(),
                    ),
                    "optional" => $optional,
                );
            }
            else {
                $valid = false;
                break;
            }
        }
        elseif ($property = $this->parseTemplateLiteral(true)) {
            if ($optionalChain) {
                $this->error("Optional chain can't appear in tagged template expressions");
            }
            $valid = true;
            $properties[] = array(
                "type" => "template",
                "info" => $property,
                "optional" => $optional,
            );
        }
        elseif (($args = $this->parseArguments()) !== null) {
            $valid = true;
            $properties[] = array(
                "type" => "args",
                "info" => array(
                    $args,
                    $this->scanner
                        ->getPosition(),
                ),
                "optional" => $optional,
            );
        }
        else {
            break;
        }
    }
    $propCount = count($properties);
    if (!$valid) {
        $this->error();
    }
    elseif (!$propCount && !$newTokensCount) {
        return $object;
    }
    $node = null;
    $endPos = $object->location->end;
    $optionalChainStarted = false;
    foreach ($properties as $i => $property) {
        $lastNode = $node ?: $object;
        if ($property["optional"]) {
            $optionalChainStarted = true;
        }
        if ($property["type"] === "args") {
            if ($newTokensCount) {
                if ($optionalChainStarted) {
                    $this->error("Optional chain can't appear in new expressions");
                }
                $node = $this->createNode("NewExpression", array_pop($newTokens));
                $newTokensCount--;
            }
            else {
                $node = $this->createNode("CallExpression", $lastNode);
                $node->setOptional($property["optional"]);
            }
            $node->setCallee($lastNode);
            $node->setArguments($property["info"][0]);
            $endPos = $property["info"][1];
        }
        elseif ($property["type"] === "id") {
            $node = $this->createNode("MemberExpression", $lastNode);
            $node->setObject($lastNode);
            $node->setOptional($property["optional"]);
            $node->setProperty($property["info"]);
            $endPos = $property["info"]->location->end;
        }
        elseif ($property["type"] === "computed") {
            $node = $this->createNode("MemberExpression", $lastNode);
            $node->setObject($lastNode);
            $node->setProperty($property["info"][0]);
            $node->setOptional($property["optional"]);
            $node->setComputed(true);
            $endPos = $property["info"][1];
        }
        elseif ($property["type"] === "template") {
            $node = $this->createNode("TaggedTemplateExpression", $object);
            $node->setTag($lastNode);
            $node->setQuasi($property["info"]);
            $endPos = $property["info"]->location->end;
        }
        $node = $this->completeNode($node, $endPos);
    }
    
    //Wrap the result in multiple NewExpression if there are "new" tokens
    if ($newTokensCount) {
        for ($i = $newTokensCount - 1; $i >= 0; $i--) {
            $lastNode = $node ?: $object;
            $node = $this->createNode("NewExpression", $newTokens[$i]);
            $node->setCallee($lastNode);
            $node = $this->completeNode($node);
        }
    }
    
    //Wrap the result in a chain expression if required
    if ($optionalChain) {
        $prevNode = $node;
        $node = $this->createNode("ChainExpression", $prevNode);
        $node->setExpression($prevNode);
        $node = $this->completeNode($node);
    }
    return $node;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal