use of com.google.javascript.jscomp.parsing.parser.trees.OptionalMemberExpressionTree in project closure-compiler by google.
the class Parser method maybeParseOptionalExpression.
/**
* Tries to parse the expression as an optional expression.
*
* <p>`operand?.identifier` or `operand?.[expression]` or `operand?.(arg1, arg2)`
*
* <p>returns parse tree after trying to parse it as an optional expression
*/
private ParseTree maybeParseOptionalExpression(ParseTree operand) {
// The optional chain's source info should cover the lhs operand also
SourcePosition start = operand.location.start;
while (peek(TokenType.QUESTION_DOT)) {
eat(TokenType.QUESTION_DOT);
switch(peekType()) {
case OPEN_PAREN:
ArgumentListTree arguments = parseArguments();
operand = new OptChainCallExpressionTree(getTreeLocation(start), operand, arguments, /* isStartOfOptionalChain = */
true, arguments.hasTrailingComma);
break;
case OPEN_SQUARE:
eat(TokenType.OPEN_SQUARE);
ParseTree member = parseExpression();
eat(TokenType.CLOSE_SQUARE);
operand = new OptionalMemberLookupExpressionTree(getTreeLocation(start), operand, member, /* isStartOfOptionalChain = */
true);
break;
case NO_SUBSTITUTION_TEMPLATE:
case TEMPLATE_HEAD:
reportError("template literal cannot be used within optional chaining");
break;
default:
if (peekIdOrKeyword()) {
IdentifierToken id = eatIdOrKeywordAsId();
operand = new OptionalMemberExpressionTree(getTreeLocation(start), operand, id, /* isStartOfOptionalChain = */
true);
} else {
reportError("syntax error: %s not allowed in optional chain", peekType());
}
}
operand = parseRemainingOptionalChainSegment(operand);
}
return operand;
}
use of com.google.javascript.jscomp.parsing.parser.trees.OptionalMemberExpressionTree in project closure-compiler by google.
the class Parser method parseRemainingOptionalChainSegment.
/**
* Parses the remaining components of an optional chain till the current chain's end, or a new
* chain's start.
*
* <p>`optionalExpression.identifier`, `optionalExpression[expression]`, `optionalExpression(arg1,
* arg2)`, or `optionalExpression?.optionalExpression`
*
* <p>returns parse tree after trying to parse it as an optional chain
*/
private ParseTree parseRemainingOptionalChainSegment(ParseTree optionalExpression) {
// The optional chain's source info should cover the lhs operand also
SourcePosition start = optionalExpression.location.start;
while (peekOptionalChainSuffix()) {
if (peekType() == TokenType.NO_SUBSTITUTION_TEMPLATE || peekType() == TokenType.TEMPLATE_HEAD) {
reportError("template literal cannot be used within optional chaining");
break;
}
switch(peekType()) {
case PERIOD:
eat(TokenType.PERIOD);
IdentifierToken id = eatIdOrKeywordAsId();
optionalExpression = new OptionalMemberExpressionTree(getTreeLocation(start), optionalExpression, id, /*isStartOfOptionalChain=*/
false);
break;
case OPEN_PAREN:
ArgumentListTree arguments = parseArguments();
optionalExpression = new OptChainCallExpressionTree(getTreeLocation(start), optionalExpression, arguments, /* isStartOfOptionalChain = */
false, arguments.hasTrailingComma);
break;
case OPEN_SQUARE:
eat(TokenType.OPEN_SQUARE);
ParseTree member = parseExpression();
eat(TokenType.CLOSE_SQUARE);
optionalExpression = new OptionalMemberLookupExpressionTree(getTreeLocation(start), optionalExpression, member, /* isStartOfOptionalChain = */
false);
break;
default:
throw new AssertionError("unexpected case: " + peekType());
}
}
return optionalExpression;
}
Aggregations