Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement parser changes for spread operator in list-constructor-expr #35386

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -1981,7 +1981,7 @@ public BLangNode transform(ListConstructorExpressionNode listConstructorExprNode
List<BLangExpression> argExprList = new ArrayList<>();
BLangListConstructorExpr listConstructorExpr = (BLangListConstructorExpr)
TreeBuilder.createListConstructorExpressionNode();
for (Node expr : listConstructorExprNode.expressions()) {
for (Node expr : listConstructorExprNode.listMembers()) {
argExprList.add(createExpression(expr));
}
listConstructorExpr.exprs = argExprList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10079,53 +10079,90 @@ private STNode parseTrapKeyword() {
* Parse list constructor expression.
* <p>
* <code>
* list-constructor-expr := [ [ expr-list ] ]
* list-constructor-expr := [ [ list-members ] ]
* <br/>
* expr-list := expression (, expression)*
* list-members := list-member (, list-member)*
* <br/>
* list-member := expression | spread-member
* <br/>
* spread-member := ... expression
* </code>
*
* @return Parsed node
*/
private STNode parseListConstructorExpr() {
startContext(ParserRuleContext.LIST_CONSTRUCTOR);
STNode openBracket = parseOpenBracket();
STNode expressions = parseOptionalExpressionsList();
STNode listMembers = parseListMembers();
STNode closeBracket = parseCloseBracket();
endContext();
return STNodeFactory.createListConstructorExpressionNode(openBracket, expressions, closeBracket);
return STNodeFactory.createListConstructorExpressionNode(openBracket, listMembers, closeBracket);
}

/**
* Parse optional expression list.
* Parse optional list member list.
*
* @return Parsed node
*/
private STNode parseOptionalExpressionsList() {
List<STNode> expressions = new ArrayList<>();
private STNode parseListMembers() {
List<STNode> listMembers = new ArrayList<>();
if (isEndOfListConstructor(peek().kind)) {
return STNodeFactory.createEmptyNodeList();
}

STNode expr = parseExpression();
expressions.add(expr);
return parseOptionalExpressionsList(expressions);
STNode listMember = parseListMember();
listMembers.add(listMember);
return parseListMembers(listMembers);
}

private STNode parseOptionalExpressionsList(List<STNode> expressions) {
// Parse the remaining expressions
private STNode parseListMembers(List<STNode> listMembers) {
// Parse the remaining list members
STNode listConstructorMemberEnd;
while (!isEndOfListConstructor(peek().kind)) {
listConstructorMemberEnd = parseListConstructorMemberEnd();
if (listConstructorMemberEnd == null) {
break;
}
expressions.add(listConstructorMemberEnd);
listMembers.add(listConstructorMemberEnd);

STNode expr = parseExpression();
expressions.add(expr);
STNode listMember = parseListMember();
listMembers.add(listMember);
}

return STNodeFactory.createNodeList(expressions);
return STNodeFactory.createNodeList(listMembers);
}

/**
* Parse list member.
* <p>
* <code>
* list-member := expression | spread-member
* </code>
*
* @return Parsed node
*/
private STNode parseListMember() {
STToken nextToken = peek();
if (nextToken.kind == SyntaxKind.ELLIPSIS_TOKEN) {
return parseSpreadMember();
} else {
return parseExpression();
}
}

/**
* Parse spread member.
* <p>
* <code>
* spread-member := ... expression
* </code>
*
* @return Parsed node
*/
private STNode parseSpreadMember() {
STNode ellipsis = parseEllipsis();
STNode expr = parseExpression();
return STNodeFactory.createSpreadMemberNode(ellipsis, expr);
}

private boolean isEndOfListConstructor(SyntaxKind tokenKind) {
Expand Down Expand Up @@ -16860,9 +16897,9 @@ private STNode parseStatementStartsWithOpenBracket(STNode annots, boolean possib
return parseStatementStartsWithOpenBracket(annots, true, possibleMappingField);
}

private STNode parseMemberBracketedList(boolean possibleMappingField) {
private STNode parseMemberBracketedList() {
STNode annots = STNodeFactory.createEmptyNodeList();
return parseStatementStartsWithOpenBracket(annots, false, possibleMappingField);
return parseStatementStartsWithOpenBracket(annots, false, false);
}

/**
Expand Down Expand Up @@ -16938,7 +16975,7 @@ private STNode parseStatementStartBracketedListMember(List<STNode> qualifiers) {
switch (nextToken.kind) {
case OPEN_BRACKET_TOKEN:
reportInvalidQualifierList(qualifiers);
return parseMemberBracketedList(false);
return parseMemberBracketedList();
case IDENTIFIER_TOKEN:
reportInvalidQualifierList(qualifiers);
STNode identifier = parseQualifiedIdentifier(ParserRuleContext.VARIABLE_REF);
Expand Down Expand Up @@ -16973,8 +17010,9 @@ private STNode parseStatementStartBracketedListMember(List<STNode> qualifiers) {
// error-type-desc
return parseTypeDescriptor(ParserRuleContext.TYPE_DESC_IN_TUPLE);
case ELLIPSIS_TOKEN:
// could be rest-binding or list-rest-member
reportInvalidQualifierList(qualifiers);
return parseListBindingPatternMember();
return parseRestBindingOrSpreadMember();
case XML_KEYWORD:
case STRING_KEYWORD:
reportInvalidQualifierList(qualifiers);
Expand Down Expand Up @@ -17008,6 +17046,16 @@ private STNode parseStatementStartBracketedListMember(List<STNode> qualifiers) {
}
}

private STNode parseRestBindingOrSpreadMember() {
STNode ellipsis = parseEllipsis();
STNode expr = parseExpression();
if (expr.kind == SyntaxKind.SIMPLE_NAME_REFERENCE) {
return STNodeFactory.createRestBindingPatternNode(ellipsis, expr);
} else {
return STNodeFactory.createSpreadMemberNode(ellipsis, expr);
}
}

private STNode parseAsTupleTypeDescOrListConstructor(STNode annots, STNode openBracket, List<STNode> memberList,
STNode member, boolean isRoot) {
memberList.add(member);
Expand Down Expand Up @@ -17153,7 +17201,7 @@ private STNode parseTupleTypeDescOrListConstructorRhs(STNode openBracket, List<S
default:
if (isValidExprRhsStart(peek().kind, closeBracket.kind) ||
(isRoot && peek().kind == SyntaxKind.EQUAL_TOKEN)) {
members = getExpressionList(members);
members = getExpressionList(members, false);
STNode memberExpressions = STNodeFactory.createNodeList(members);
tupleTypeOrListConst = STNodeFactory.createListConstructorExpressionNode(openBracket,
memberExpressions, closeBracket);
Expand Down Expand Up @@ -17261,7 +17309,7 @@ private STNode parseAsListBindingPatternOrListConstructor(STNode openBracket, Li

private SyntaxKind getStmtStartBracketedListType(STNode memberNode) {
if (memberNode.kind.compareTo(SyntaxKind.RECORD_TYPE_DESC) >= 0 &&
memberNode.kind.compareTo(SyntaxKind.TYPEDESC_TYPE_DESC) <= 0) {
memberNode.kind.compareTo(SyntaxKind.FUTURE_TYPE_DESC) <= 0) {
return SyntaxKind.TUPLE_TYPE_DESC;
}

Expand All @@ -17271,15 +17319,16 @@ private SyntaxKind getStmtStartBracketedListType(STNode memberNode) {
case LIST_BINDING_PATTERN:
case MAPPING_BINDING_PATTERN:
case ERROR_BINDING_PATTERN:
case REST_BINDING_PATTERN:
return SyntaxKind.LIST_BINDING_PATTERN;
case QUALIFIED_NAME_REFERENCE: // a qualified-name-ref can only be a type-ref
case REST_TYPE:
return SyntaxKind.TUPLE_TYPE_DESC;
case LIST_CONSTRUCTOR:
case MAPPING_CONSTRUCTOR:
case SPREAD_MEMBER:
return SyntaxKind.LIST_CONSTRUCTOR;
case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
case REST_BINDING_PATTERN:
// can be either list-bp or list-constructor. Cannot be a tuple-type-desc
return SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR;
case SIMPLE_NAME_REFERENCE: // member is a simple type-ref/var-ref
Expand All @@ -17297,7 +17346,7 @@ private SyntaxKind getStmtStartBracketedListType(STNode memberNode) {
return SyntaxKind.LIST_CONSTRUCTOR;
}

// can be anyof the three.
// can be any of the three.
return SyntaxKind.NONE;
}
}
Expand Down Expand Up @@ -17605,7 +17654,7 @@ private STNode parseStmtAsMappingConstructorStart(STNode openBrace, STNode first
*/
private STNode parseAsMappingConstructor(STNode openBrace, List<STNode> members, STNode member) {
members.add(member);
members = getExpressionList(members);
members = getExpressionList(members, true);

// create mapping constructor
switchContext(ParserRuleContext.MAPPING_CONSTRUCTOR);
Expand Down Expand Up @@ -18152,7 +18201,7 @@ private STNode parseListBindingPatternOrListConstructorMember() {
case OPEN_BRACE_TOKEN:
return parseMappingBindingPatterOrMappingConstructor();
case ELLIPSIS_TOKEN:
return parseListBindingPatternMember();
return parseRestBindingOrSpreadMember();
default:
if (isValidExpressionStart(nextToken.kind, 1)) {
return parseExpression();
Expand All @@ -18167,28 +18216,29 @@ private SyntaxKind getParsingNodeTypeOfListBPOrListCons(STNode memberNode) {
switch (memberNode.kind) {
case CAPTURE_BINDING_PATTERN:
case LIST_BINDING_PATTERN:
case REST_BINDING_PATTERN:
case MAPPING_BINDING_PATTERN:
case WILDCARD_BINDING_PATTERN:
return SyntaxKind.LIST_BINDING_PATTERN;
case SIMPLE_NAME_REFERENCE: // member is a simple type-ref/var-ref
case LIST_BP_OR_LIST_CONSTRUCTOR: // member is again ambiguous
case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
case REST_BINDING_PATTERN:
return SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR;
case SPREAD_MEMBER:
default:
return SyntaxKind.LIST_CONSTRUCTOR;
}
}

private STNode parseAsListConstructor(STNode openBracket, List<STNode> memberList, STNode member, boolean isRoot) {
memberList.add(member);
memberList = getExpressionList(memberList);
memberList = getExpressionList(memberList, false);

switchContext(ParserRuleContext.LIST_CONSTRUCTOR);
STNode expressions = parseOptionalExpressionsList(memberList);
STNode listMembers = parseListMembers(memberList);
STNode closeBracket = parseCloseBracket();
STNode listConstructor =
STNodeFactory.createListConstructorExpressionNode(openBracket, expressions, closeBracket);
STNodeFactory.createListConstructorExpressionNode(openBracket, listMembers, closeBracket);
endContext();

STNode expr = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, listConstructor, false, true);
Expand Down Expand Up @@ -18217,7 +18267,7 @@ private STNode parseListBindingPatternOrListConstructor(STNode openBracket, List
SyntaxKind nextTokenKind = peek().kind;
if (isValidExprRhsStart(nextTokenKind, closeBracket.kind) ||
nextTokenKind == SyntaxKind.SEMICOLON_TOKEN && isRoot) { // [a, b, c];
members = getExpressionList(members);
members = getExpressionList(members, false);
STNode memberExpressions = STNodeFactory.createNodeList(members);
lbpOrListCons = STNodeFactory.createListConstructorExpressionNode(openBracket, memberExpressions,
closeBracket);
Expand Down Expand Up @@ -18591,15 +18641,19 @@ private STNode getBindingPattern(STNode ambiguousNode) {
}
}

private List<STNode> getExpressionList(List<STNode> ambibuousList) {
private List<STNode> getExpressionList(List<STNode> ambibuousList, boolean isMappingConstructor) {
List<STNode> exprList = new ArrayList<STNode>();
for (STNode item : ambibuousList) {
exprList.add(getExpression(item));
exprList.add(getExpression(item, isMappingConstructor));
}
return exprList;
}

private STNode getExpression(STNode ambiguousNode) {
return getExpression(ambiguousNode, false);
}

private STNode getExpression(STNode ambiguousNode, boolean isMappingConstructor) {
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved
if (isEmpty(ambiguousNode) ||
(isDefiniteExpr(ambiguousNode.kind) && ambiguousNode.kind != SyntaxKind.INDEXED_EXPRESSION) ||
isDefiniteAction(ambiguousNode.kind) || ambiguousNode.kind == SyntaxKind.COMMA_TOKEN) {
Expand All @@ -18611,7 +18665,7 @@ private STNode getExpression(STNode ambiguousNode) {
case LIST_BP_OR_LIST_CONSTRUCTOR:
case TUPLE_TYPE_DESC_OR_LIST_CONST:
STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) ambiguousNode;
STNode memberExprs = STNodeFactory.createNodeList(getExpressionList(innerList.members));
STNode memberExprs = STNodeFactory.createNodeList(getExpressionList(innerList.members, false));
return STNodeFactory.createListConstructorExpressionNode(innerList.collectionStartToken, memberExprs,
innerList.collectionEndToken);
case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
Expand All @@ -18628,7 +18682,7 @@ private STNode getExpression(STNode ambiguousNode) {
STNode valueExpr = getExpression(qualifiedNameRefNode.identifier);
fieldNode = STNodeFactory.createSpecificFieldNode(readOnlyKeyword, fieldName, colon, valueExpr);
} else {
fieldNode = getExpression(field);
fieldNode = getExpression(field, true);
}

fieldList.add(fieldNode);
Expand All @@ -18638,8 +18692,13 @@ private STNode getExpression(STNode ambiguousNode) {
innerList.collectionEndToken);
case REST_BINDING_PATTERN:
STRestBindingPatternNode restBindingPattern = (STRestBindingPatternNode) ambiguousNode;
return STNodeFactory.createSpreadFieldNode(restBindingPattern.ellipsisToken,
restBindingPattern.variableName);
if (isMappingConstructor) {
return STNodeFactory.createSpreadFieldNode(restBindingPattern.ellipsisToken,
restBindingPattern.variableName);
} else {
return STNodeFactory.createSpreadMemberNode(restBindingPattern.ellipsisToken,
restBindingPattern.variableName);
}
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved
case SPECIFIC_FIELD:
// Specific field is used to represent ambiguous scenarios. Hence it needs to be re-written.
STSpecificFieldNode field = (STSpecificFieldNode) ambiguousNode;
Expand Down Expand Up @@ -18675,6 +18734,7 @@ private STNode getExpression(STNode ambiguousNode) {
case QUALIFIED_NAME_REFERENCE:
case COMPUTED_NAME_FIELD:
case SPREAD_FIELD:
case SPREAD_MEMBER:
return ambiguousNode;
default:
STNode simpleVarRef = SyntaxErrors.createMissingTokenWithDiagnostics(SyntaxKind.IDENTIFIER_TOKEN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ public class BallerinaParserErrorHandler extends AbstractParserErrorHandler {
ParserRuleContext.MINUS_TOKEN, ParserRuleContext.NIL_LITERAL };

private static final ParserRuleContext[] LIST_CONSTRUCTOR_RHS =
{ ParserRuleContext.CLOSE_BRACKET, ParserRuleContext.EXPRESSION };
{ ParserRuleContext.CLOSE_BRACKET, ParserRuleContext.EXPRESSION, ParserRuleContext.ELLIPSIS };
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved

private static final ParserRuleContext[] TYPE_CAST_PARAM =
{ ParserRuleContext.TYPE_DESC_IN_ANGLE_BRACKETS, ParserRuleContext.ANNOTATIONS };
Expand Down Expand Up @@ -3097,6 +3097,7 @@ protected ParserRuleContext getNextRule(ParserRuleContext currentCtx, int nextLo
parentCtx = getParentContext();
switch (parentCtx) {
case MAPPING_CONSTRUCTOR:
case LIST_CONSTRUCTOR:
case ARG_LIST:
return ParserRuleContext.EXPRESSION;
case TYPE_DESC_IN_TUPLE:
Expand Down
Loading