use of org.apache.groovy.parser.antlr4.GroovyLexer.PUBLIC in project groovy by apache.
the class AstBuilder method visitGstring.
// } literal ---------------------------------------------------------------
// gstring { ---------------------------------------------------------------
@Override
public GStringExpression visitGstring(final GstringContext ctx) {
final List<ConstantExpression> stringLiteralList = new LinkedList<>();
final String begin = ctx.GStringBegin().getText();
final String beginQuotation = beginQuotation(begin);
stringLiteralList.add(configureAST(new ConstantExpression(parseGStringBegin(ctx, beginQuotation)), ctx.GStringBegin()));
List<ConstantExpression> partStrings = ctx.GStringPart().stream().map(e -> configureAST(new ConstantExpression(parseGStringPart(e, beginQuotation)), e)).collect(Collectors.toList());
stringLiteralList.addAll(partStrings);
stringLiteralList.add(configureAST(new ConstantExpression(parseGStringEnd(ctx, beginQuotation)), ctx.GStringEnd()));
List<Expression> values = ctx.gstringValue().stream().map(this::visitGstringValue).collect(Collectors.toList());
StringBuilder verbatimText = new StringBuilder(ctx.getText().length());
for (int i = 0, n = stringLiteralList.size(), s = values.size(); i < n; i += 1) {
verbatimText.append(stringLiteralList.get(i).getValue());
if (i == s) {
continue;
}
Expression value = values.get(i);
if (!asBoolean(value)) {
continue;
}
boolean isVariableExpression = value instanceof VariableExpression;
verbatimText.append(DOLLAR_STR);
if (!isVariableExpression)
verbatimText.append('{');
verbatimText.append(value.getText());
if (!isVariableExpression)
verbatimText.append('}');
}
return configureAST(new GStringExpression(verbatimText.toString(), stringLiteralList, values), ctx);
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.PUBLIC in project groovy by apache.
the class AstBuilder method visitTryCatchStatement.
@Override
public Statement visitTryCatchStatement(final TryCatchStatementContext ctx) {
boolean resourcesExists = asBoolean(ctx.resources());
boolean catchExists = asBoolean(ctx.catchClause());
boolean finallyExists = asBoolean(ctx.finallyBlock());
if (!(resourcesExists || catchExists || finallyExists)) {
throw createParsingFailedException("Either a catch or finally clause or both is required for a try-catch-finally statement", ctx);
}
TryCatchStatement tryCatchStatement = new TryCatchStatement((Statement) this.visit(ctx.block()), this.visitFinallyBlock(ctx.finallyBlock()));
if (resourcesExists) {
this.visitResources(ctx.resources()).forEach(tryCatchStatement::addResource);
}
ctx.catchClause().stream().map(this::visitCatchClause).reduce(new LinkedList<>(), (r, e) -> {
// merge several LinkedList<CatchStatement> instances into one LinkedList<CatchStatement> instance
r.addAll(e);
return r;
}).forEach(tryCatchStatement::addCatch);
return configureAST(tryWithResourcesASTTransformation.transform(configureAST(tryCatchStatement, ctx)), ctx);
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.PUBLIC in project groovy by apache.
the class AstBuilder method visitPathElement.
@Override
public Expression visitPathElement(final PathElementContext ctx) {
Expression baseExpr = ctx.getNodeMetaData(PATH_EXPRESSION_BASE_EXPR);
Objects.requireNonNull(baseExpr, "baseExpr is required!");
if (asBoolean(ctx.namePart())) {
Expression namePartExpr = this.visitNamePart(ctx.namePart());
GenericsType[] genericsTypes = this.visitNonWildcardTypeArguments(ctx.nonWildcardTypeArguments());
if (asBoolean(ctx.DOT())) {
boolean isSafeChain = this.isTrue(baseExpr, PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
return this.createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, isSafeChain);
} else if (asBoolean(ctx.SAFE_DOT())) {
return this.createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, true);
} else if (asBoolean(ctx.SAFE_CHAIN_DOT())) {
// e.g. obj??.a OR obj??.@a
Expression expression = createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, true);
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, true);
return expression;
} else if (asBoolean(ctx.METHOD_POINTER())) {
// e.g. obj.&m
return configureAST(new MethodPointerExpression(baseExpr, namePartExpr), ctx);
} else if (asBoolean(ctx.METHOD_REFERENCE())) {
// e.g. obj::m
return configureAST(new MethodReferenceExpression(baseExpr, namePartExpr), ctx);
} else if (asBoolean(ctx.SPREAD_DOT())) {
if (asBoolean(ctx.AT())) {
// e.g. obj*.@a
AttributeExpression attributeExpression = new AttributeExpression(baseExpr, namePartExpr, true);
attributeExpression.setSpreadSafe(true);
return configureAST(attributeExpression, ctx);
} else {
// e.g. obj*.p
PropertyExpression propertyExpression = new PropertyExpression(baseExpr, namePartExpr, true);
propertyExpression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES, genericsTypes);
propertyExpression.setSpreadSafe(true);
return configureAST(propertyExpression, ctx);
}
}
} else if (asBoolean(ctx.creator())) {
CreatorContext creatorContext = ctx.creator();
creatorContext.putNodeMetaData(ENCLOSING_INSTANCE_EXPRESSION, baseExpr);
return configureAST(this.visitCreator(creatorContext), ctx);
} else if (asBoolean(ctx.indexPropertyArgs())) {
// e.g. list[1, 3, 5]
Tuple2<Token, Expression> tuple = this.visitIndexPropertyArgs(ctx.indexPropertyArgs());
boolean isSafeChain = this.isTrue(baseExpr, PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
return configureAST(new BinaryExpression(baseExpr, createGroovyToken(tuple.getV1()), tuple.getV2(), isSafeChain || asBoolean(ctx.indexPropertyArgs().SAFE_INDEX())), ctx);
} else if (asBoolean(ctx.namedPropertyArgs())) {
// this is a special way to signify a cast, e.g. Person[name: 'Daniel.Sun', location: 'Shanghai']
List<MapEntryExpression> mapEntryExpressionList = this.visitNamedPropertyArgs(ctx.namedPropertyArgs());
Expression right;
Expression firstKeyExpression;
int mapEntryExpressionListSize = mapEntryExpressionList.size();
if (mapEntryExpressionListSize == 0) {
// expecting list of MapEntryExpressions later so use SpreadMap to smuggle empty MapExpression to later stages
right = configureAST(new SpreadMapExpression(configureAST(new MapExpression(), ctx.namedPropertyArgs())), ctx.namedPropertyArgs());
} else if (mapEntryExpressionListSize == 1 && (firstKeyExpression = mapEntryExpressionList.get(0).getKeyExpression()) instanceof SpreadMapExpression) {
right = firstKeyExpression;
} else {
ListExpression listExpression = configureAST(new ListExpression(mapEntryExpressionList.stream().map(e -> {
if (e.getKeyExpression() instanceof SpreadMapExpression) {
return e.getKeyExpression();
}
return e;
}).collect(Collectors.toList())), ctx.namedPropertyArgs());
listExpression.setWrapped(true);
right = listExpression;
}
NamedPropertyArgsContext namedPropertyArgsContext = ctx.namedPropertyArgs();
Token token = (namedPropertyArgsContext.LBRACK() == null ? namedPropertyArgsContext.SAFE_INDEX() : namedPropertyArgsContext.LBRACK()).getSymbol();
return configureAST(new BinaryExpression(baseExpr, createGroovyToken(token), right), ctx);
} else if (asBoolean(ctx.arguments())) {
Expression argumentsExpr = this.visitArguments(ctx.arguments());
configureAST(argumentsExpr, ctx);
if (isInsideParentheses(baseExpr)) {
// e.g. (obj.x)(), (obj.@x)()
return configureAST(createCallMethodCallExpression(baseExpr, argumentsExpr), ctx);
}
if (baseExpr instanceof AttributeExpression) {
// e.g. obj.@a(1, 2)
AttributeExpression attributeExpression = (AttributeExpression) baseExpr;
// whether attributeExpression is spread safe or not, we must reset it as false
attributeExpression.setSpreadSafe(false);
return configureAST(createCallMethodCallExpression(attributeExpression, argumentsExpr, true), ctx);
}
if (baseExpr instanceof PropertyExpression) {
// e.g. obj.a(1, 2)
MethodCallExpression methodCallExpression = this.createMethodCallExpression((PropertyExpression) baseExpr, argumentsExpr);
return configureAST(methodCallExpression, ctx);
}
if (baseExpr instanceof VariableExpression) {
// void and primitive type AST node must be an instance of VariableExpression
String baseExprText = baseExpr.getText();
if (VOID_STR.equals(baseExprText)) {
// e.g. void()
return configureAST(this.createCallMethodCallExpression(this.createConstantExpression(baseExpr), argumentsExpr), ctx);
} else if (isPrimitiveType(baseExprText)) {
// e.g. int(), long(), float(), etc.
throw this.createParsingFailedException("Primitive type literal: " + baseExprText + " cannot be used as a method name", ctx);
}
}
if (// e.g. m()
baseExpr instanceof VariableExpression || // e.g. "$m"()
baseExpr instanceof GStringExpression || (baseExpr instanceof ConstantExpression && this.isTrue(baseExpr, IS_STRING))) {
// e.g. "m"()
String baseExprText = baseExpr.getText();
if (THIS_STR.equals(baseExprText) || SUPER_STR.equals(baseExprText)) {
// @MapConstructor(pre={ super(args?.first, args?.last); args = args ?: [:] }, post = { first = first?.toUpperCase() })
if (visitingClosureCount > 0) {
return configureAST(new MethodCallExpression(baseExpr, baseExprText, argumentsExpr), ctx);
}
return configureAST(new ConstructorCallExpression(SUPER_STR.equals(baseExprText) ? ClassNode.SUPER : ClassNode.THIS, argumentsExpr), ctx);
}
MethodCallExpression methodCallExpression = this.createMethodCallExpression(baseExpr, argumentsExpr);
return configureAST(methodCallExpression, ctx);
}
// e.g. 1(), 1.1(), ((int) 1 / 2)(1, 2), {a, b -> a + b }(1, 2), m()()
return configureAST(this.createCallMethodCallExpression(baseExpr, argumentsExpr), ctx);
} else if (asBoolean(ctx.closureOrLambdaExpression())) {
ClosureExpression closureExpression = this.visitClosureOrLambdaExpression(ctx.closureOrLambdaExpression());
if (baseExpr instanceof MethodCallExpression) {
MethodCallExpression methodCallExpression = (MethodCallExpression) baseExpr;
Expression argumentsExpression = methodCallExpression.getArguments();
if (argumentsExpression instanceof ArgumentListExpression) {
// normal arguments, e.g. 1, 2
ArgumentListExpression argumentListExpression = (ArgumentListExpression) argumentsExpression;
argumentListExpression.getExpressions().add(closureExpression);
return configureAST(methodCallExpression, ctx);
}
if (argumentsExpression instanceof TupleExpression) {
// named arguments, e.g. x: 1, y: 2
TupleExpression tupleExpression = (TupleExpression) argumentsExpression;
NamedArgumentListExpression namedArgumentListExpression = (NamedArgumentListExpression) tupleExpression.getExpression(0);
if (asBoolean(tupleExpression.getExpressions())) {
methodCallExpression.setArguments(configureAST(new ArgumentListExpression(configureAST(new MapExpression(namedArgumentListExpression.getMapEntryExpressions()), namedArgumentListExpression), closureExpression), tupleExpression));
} else {
// the branch should never reach, because named arguments must not be empty
methodCallExpression.setArguments(configureAST(new ArgumentListExpression(closureExpression), tupleExpression));
}
return configureAST(methodCallExpression, ctx);
}
}
if (baseExpr instanceof PropertyExpression) {
// e.g. obj.m { }
MethodCallExpression methodCallExpression = this.createMethodCallExpression((PropertyExpression) baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
if (// e.g. m { }
baseExpr instanceof VariableExpression || // e.g. "$m" { }
baseExpr instanceof GStringExpression || (baseExpr instanceof ConstantExpression && this.isTrue(baseExpr, IS_STRING))) {
// e.g. "m" { }
MethodCallExpression methodCallExpression = this.createMethodCallExpression(baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
// e.g. 1 { }, 1.1 { }, (1 / 2) { }, m() { }, { -> ... } { }
MethodCallExpression methodCallExpression = this.createCallMethodCallExpression(baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
throw createParsingFailedException("Unsupported path element: " + ctx.getText(), ctx);
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.PUBLIC in project groovy by apache.
the class AstBuilder method visitSwitchExpression.
/**
* <pre>
* switch(a) {
* case 0, 1 -> 'a';
* case 2 -> 'b';
* default -> 'z';
* }
* </pre>
* the above code will be transformed to:
* <pre>
* {->
* switch(a) {
* case 0:
* case 1: return 'a';
* case 2: return 'b';
* default: return 'z';
* }
* }()
* </pre>
*
* @param ctx the parse tree
* @return {@link MethodCallExpression} instance
*/
@Override
public MethodCallExpression visitSwitchExpression(SwitchExpressionContext ctx) {
switchExpressionRuleContextStack.push(ctx);
try {
validateSwitchExpressionLabels(ctx);
List<Tuple3<List<Statement>, Boolean, Boolean>> statementInfoList = ctx.switchBlockStatementExpressionGroup().stream().map(e -> this.visitSwitchBlockStatementExpressionGroup(e)).collect(Collectors.toList());
if (statementInfoList.isEmpty()) {
throw createParsingFailedException("`case` or `default` branches are expected", ctx.LBRACE());
}
Boolean isArrow = statementInfoList.get(0).getV2();
if (!isArrow && statementInfoList.stream().noneMatch(e -> {
Boolean hasYieldOrThrowStatement = e.getV3();
return hasYieldOrThrowStatement;
})) {
throw createParsingFailedException("`yield` or `throw` is expected", ctx);
}
List<Statement> statementList = statementInfoList.stream().map(e -> e.getV1()).reduce(new LinkedList<>(), (r, e) -> {
r.addAll(e);
return r;
});
List<CaseStatement> caseStatementList = new LinkedList<>();
List<Statement> defaultStatementList = new LinkedList<>();
statementList.forEach(e -> {
if (e instanceof CaseStatement) {
caseStatementList.add((CaseStatement) e);
} else if (isTrue(e, IS_SWITCH_DEFAULT)) {
defaultStatementList.add(e);
}
});
int defaultStatementListSize = defaultStatementList.size();
if (defaultStatementListSize > 1) {
throw createParsingFailedException("switch expression should have only one default case, which should appear at last", defaultStatementList.get(0));
}
if (defaultStatementListSize > 0 && last(statementList) instanceof CaseStatement) {
throw createParsingFailedException("default case should appear at last", defaultStatementList.get(0));
}
String variableName = "__$$sev" + switchExpressionVariableSeq++;
Statement declarationStatement = declS(localVarX(variableName), this.visitExpressionInPar(ctx.expressionInPar()));
SwitchStatement switchStatement = configureAST(new SwitchStatement(varX(variableName), caseStatementList, defaultStatementListSize == 0 ? EmptyStatement.INSTANCE : defaultStatementList.get(0)), ctx);
MethodCallExpression callClosure = callX(configureAST(closureX(null, createBlockStatement(declarationStatement, switchStatement)), ctx), "call");
callClosure.setImplicitThis(false);
return configureAST(callClosure, ctx);
} finally {
switchExpressionRuleContextStack.pop();
}
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.PUBLIC in project groovy by apache.
the class AstBuilder method visitEnumConstants.
@Override
public List<FieldNode> visitEnumConstants(final EnumConstantsContext ctx) {
ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
Objects.requireNonNull(classNode, "classNode should not be null");
return ctx.enumConstant().stream().map(e -> {
e.putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
return this.visitEnumConstant(e);
}).collect(Collectors.toList());
}
Aggregations