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\SyntaxCode
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;
}