|
|
@@ -20,8 +20,13 @@
|
|
|
package org.elasticsearch.painless.antlr;
|
|
|
|
|
|
import org.antlr.v4.runtime.ANTLRInputStream;
|
|
|
+import org.antlr.v4.runtime.BaseErrorListener;
|
|
|
import org.antlr.v4.runtime.CommonTokenStream;
|
|
|
+import org.antlr.v4.runtime.DiagnosticErrorListener;
|
|
|
import org.antlr.v4.runtime.ParserRuleContext;
|
|
|
+import org.antlr.v4.runtime.RecognitionException;
|
|
|
+import org.antlr.v4.runtime.Recognizer;
|
|
|
+import org.antlr.v4.runtime.atn.PredictionMode;
|
|
|
import org.elasticsearch.painless.CompilerSettings;
|
|
|
import org.elasticsearch.painless.Operation;
|
|
|
import org.elasticsearch.painless.Variables.Reserved;
|
|
|
@@ -29,51 +34,54 @@ import org.elasticsearch.painless.antlr.PainlessParser.AfterthoughtContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ArgumentsContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.AssignmentContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.BinaryContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.BlockContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.BoolContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.BraceaccessContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.BreakContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.CallinvokeContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.CastContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.ChainprecContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.CompContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ConditionalContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ContinueContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.DeclContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.DeclarationContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.DecltypeContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.DeclvarContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.DelimiterContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.DoContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.DynamicContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.EmptyContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.EmptyscopeContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ExprContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ExpressionContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkbraceContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkcallContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkcastContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkdotContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.ReadContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkfieldContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinknewContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkprecContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.ChainContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkstringContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.LinkvarContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.ExprprecContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.FalseContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.FieldaccessContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ForContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.GenericContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.IdentifierContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.IfContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.InitializerContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.MultipleContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.NewarrayContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.NewobjectContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.NullContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.NumericContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.PostincContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.PrecedenceContext;
|
|
|
-import org.elasticsearch.painless.antlr.PainlessParser.PreincContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.OperatorContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.PostContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.PreContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.ReadContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ReturnContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.SecondaryContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.SingleContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.SourceContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.StatementContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.StaticContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.StringContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.ThrowContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.TrailerContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.TrapContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.TrueContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.TryContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.UnaryContext;
|
|
|
+import org.elasticsearch.painless.antlr.PainlessParser.VariableContext;
|
|
|
import org.elasticsearch.painless.antlr.PainlessParser.WhileContext;
|
|
|
import org.elasticsearch.painless.node.AExpression;
|
|
|
import org.elasticsearch.painless.node.ALink;
|
|
|
@@ -82,11 +90,11 @@ import org.elasticsearch.painless.node.AStatement;
|
|
|
import org.elasticsearch.painless.node.EBinary;
|
|
|
import org.elasticsearch.painless.node.EBool;
|
|
|
import org.elasticsearch.painless.node.EBoolean;
|
|
|
-import org.elasticsearch.painless.node.EExplicit;
|
|
|
import org.elasticsearch.painless.node.EChain;
|
|
|
import org.elasticsearch.painless.node.EComp;
|
|
|
import org.elasticsearch.painless.node.EConditional;
|
|
|
import org.elasticsearch.painless.node.EDecimal;
|
|
|
+import org.elasticsearch.painless.node.EExplicit;
|
|
|
import org.elasticsearch.painless.node.ENull;
|
|
|
import org.elasticsearch.painless.node.ENumeric;
|
|
|
import org.elasticsearch.painless.node.EUnary;
|
|
|
@@ -96,21 +104,23 @@ import org.elasticsearch.painless.node.LCast;
|
|
|
import org.elasticsearch.painless.node.LField;
|
|
|
import org.elasticsearch.painless.node.LNewArray;
|
|
|
import org.elasticsearch.painless.node.LNewObj;
|
|
|
+import org.elasticsearch.painless.node.LStatic;
|
|
|
import org.elasticsearch.painless.node.LString;
|
|
|
import org.elasticsearch.painless.node.LVariable;
|
|
|
import org.elasticsearch.painless.node.SBlock;
|
|
|
import org.elasticsearch.painless.node.SBreak;
|
|
|
+import org.elasticsearch.painless.node.SCatch;
|
|
|
import org.elasticsearch.painless.node.SContinue;
|
|
|
import org.elasticsearch.painless.node.SDeclBlock;
|
|
|
import org.elasticsearch.painless.node.SDeclaration;
|
|
|
import org.elasticsearch.painless.node.SDo;
|
|
|
import org.elasticsearch.painless.node.SExpression;
|
|
|
import org.elasticsearch.painless.node.SFor;
|
|
|
+import org.elasticsearch.painless.node.SIf;
|
|
|
import org.elasticsearch.painless.node.SIfElse;
|
|
|
import org.elasticsearch.painless.node.SReturn;
|
|
|
import org.elasticsearch.painless.node.SSource;
|
|
|
import org.elasticsearch.painless.node.SThrow;
|
|
|
-import org.elasticsearch.painless.node.STrap;
|
|
|
import org.elasticsearch.painless.node.STry;
|
|
|
import org.elasticsearch.painless.node.SWhile;
|
|
|
|
|
|
@@ -120,7 +130,7 @@ import java.util.List;
|
|
|
/**
|
|
|
* Converts the ANTLR tree to a Painless tree.
|
|
|
*/
|
|
|
-public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
+public final class Walker extends PainlessParserBaseVisitor<Object> {
|
|
|
|
|
|
public static SSource buildPainlessTree(String source, Reserved reserved, CompilerSettings settings) {
|
|
|
return new Walker(source, reserved, settings).source;
|
|
|
@@ -136,329 +146,292 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
this.source = (SSource)visit(buildAntlrTree(source));
|
|
|
}
|
|
|
|
|
|
- private SourceContext buildAntlrTree(final String source) {
|
|
|
- final ANTLRInputStream stream = new ANTLRInputStream(source);
|
|
|
- final PainlessLexer lexer = new ErrorHandlingLexer(stream);
|
|
|
- final PainlessParser parser = new PainlessParser(new CommonTokenStream(lexer));
|
|
|
- final ParserErrorStrategy strategy = new ParserErrorStrategy();
|
|
|
+ private SourceContext buildAntlrTree(String source) {
|
|
|
+ ANTLRInputStream stream = new ANTLRInputStream(source);
|
|
|
+ PainlessLexer lexer = new ErrorHandlingLexer(stream);
|
|
|
+ PainlessParser parser = new PainlessParser(new CommonTokenStream(lexer));
|
|
|
+ ParserErrorStrategy strategy = new ParserErrorStrategy();
|
|
|
|
|
|
lexer.removeErrorListeners();
|
|
|
parser.removeErrorListeners();
|
|
|
+
|
|
|
+ if (settings.isPicky()) {
|
|
|
+ setupPicky(parser);
|
|
|
+ }
|
|
|
+
|
|
|
parser.setErrorHandler(strategy);
|
|
|
|
|
|
return parser.source();
|
|
|
}
|
|
|
|
|
|
- private int line(final ParserRuleContext ctx) {
|
|
|
+ private void setupPicky(PainlessParser parser) {
|
|
|
+ // Diagnostic listener invokes syntaxError on other listeners for ambiguity issues,
|
|
|
+ parser.addErrorListener(new DiagnosticErrorListener(true));
|
|
|
+ // a second listener to fail the test when the above happens.
|
|
|
+ parser.addErrorListener(new BaseErrorListener() {
|
|
|
+ @Override
|
|
|
+ public void syntaxError(final Recognizer<?,?> recognizer, final Object offendingSymbol, final int line,
|
|
|
+ final int charPositionInLine, final String msg, final RecognitionException e) {
|
|
|
+ throw new AssertionError("line: " + line + ", offset: " + charPositionInLine +
|
|
|
+ ", symbol:" + offendingSymbol + " " + msg);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Enable exact ambiguity detection (costly). we enable exact since its the default for
|
|
|
+ // DiagnosticErrorListener, life is too short to think about what 'inexact ambiguity' might mean.
|
|
|
+ parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int line(ParserRuleContext ctx) {
|
|
|
return ctx.getStart().getLine();
|
|
|
}
|
|
|
|
|
|
- private String location(final ParserRuleContext ctx) {
|
|
|
+ private int offset(ParserRuleContext ctx) {
|
|
|
+ return ctx.getStart().getStartIndex();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String location(ParserRuleContext ctx) {
|
|
|
return "[ " + ctx.getStart().getLine() + " : " + ctx.getStart().getCharPositionInLine() + " ]";
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitSource(final SourceContext ctx) {
|
|
|
- final List<AStatement> statements = new ArrayList<>();
|
|
|
+ public Object visitSource(SourceContext ctx) {
|
|
|
+ List<AStatement> statements = new ArrayList<>();
|
|
|
|
|
|
- for (final StatementContext statement : ctx.statement()) {
|
|
|
+ for (StatementContext statement : ctx.statement()) {
|
|
|
statements.add((AStatement)visit(statement));
|
|
|
}
|
|
|
|
|
|
- return new SSource(line(ctx), location(ctx), statements);
|
|
|
+ return new SSource(line(ctx), offset(ctx), location(ctx), statements);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitIf(final IfContext ctx) {
|
|
|
- final AExpression condition = (AExpression)visit(ctx.expression());
|
|
|
- final AStatement ifblock = (AStatement)visit(ctx.block(0));
|
|
|
- final AStatement elseblock = ctx.block(1) == null ? null : (AStatement)visit(ctx.block(1));
|
|
|
+ public Object visitIf(IfContext ctx) {
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
+ SBlock ifblock = (SBlock)visit(ctx.trailer(0));
|
|
|
|
|
|
- return new SIfElse(line(ctx), location(ctx), condition, ifblock, elseblock);
|
|
|
+ if (ctx.trailer().size() > 1) {
|
|
|
+ SBlock elseblock = (SBlock)visit(ctx.trailer(1));
|
|
|
+
|
|
|
+ return new SIfElse(line(ctx), offset(ctx), location(ctx), expression, ifblock, elseblock);
|
|
|
+ } else {
|
|
|
+ return new SIf(line(ctx), offset(ctx), location(ctx), expression, ifblock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitWhile(final WhileContext ctx) {
|
|
|
- final AExpression condition = (AExpression)visit(ctx.expression());
|
|
|
- final AStatement block = ctx.block() == null ? null : (AStatement)visit(ctx.block());
|
|
|
+ public Object visitWhile(WhileContext ctx) {
|
|
|
+ if (settings.getMaxLoopCounter() > 0) {
|
|
|
+ reserved.usesLoop();
|
|
|
+ }
|
|
|
|
|
|
- reserved.usesLoop();
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
|
|
|
- return new SWhile(line(ctx), location(ctx), condition, block, settings.getMaxLoopCounter());
|
|
|
+ if (ctx.trailer() != null) {
|
|
|
+ SBlock block = (SBlock)visit(ctx.trailer());
|
|
|
+
|
|
|
+ return new SWhile(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), expression, block);
|
|
|
+ } else if (ctx.empty() != null) {
|
|
|
+ return new SWhile(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), expression, null);
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitDo(final DoContext ctx) {
|
|
|
- final AStatement block = ctx.block() == null ? null : (AStatement)visit(ctx.block());
|
|
|
- final AExpression condition = (AExpression)visit(ctx.expression());
|
|
|
+ public Object visitDo(DoContext ctx) {
|
|
|
+ if (settings.getMaxLoopCounter() > 0) {
|
|
|
+ reserved.usesLoop();
|
|
|
+ }
|
|
|
|
|
|
- reserved.usesLoop();
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
+ SBlock block = (SBlock)visit(ctx.block());
|
|
|
|
|
|
- return new SDo(line(ctx), location(ctx), block, condition, settings.getMaxLoopCounter());
|
|
|
+ return new SDo(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), block, expression);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitFor(final ForContext ctx) {
|
|
|
- final ANode intializer = ctx.initializer() == null ? null : visit(ctx.initializer());
|
|
|
- final AExpression condition = ctx.expression() == null ? null : (AExpression)visit(ctx.expression());
|
|
|
- final AExpression afterthought = ctx.afterthought() == null ? null : (AExpression)visit(ctx.afterthought());
|
|
|
- final AStatement block = ctx.block() == null ? null : (AStatement)visit(ctx.block());
|
|
|
+ public Object visitFor(ForContext ctx) {
|
|
|
+ if (settings.getMaxLoopCounter() > 0) {
|
|
|
+ reserved.usesLoop();
|
|
|
+ }
|
|
|
+
|
|
|
+ ANode initializer = ctx.initializer() == null ? null : (ANode)visit(ctx.initializer());
|
|
|
+ AExpression expression = ctx.expression() == null ? null : (AExpression)visitExpression(ctx.expression());
|
|
|
+ AExpression afterthought = ctx.afterthought() == null ? null : (AExpression)visit(ctx.afterthought());
|
|
|
|
|
|
- reserved.usesLoop();
|
|
|
+ if (ctx.trailer() != null) {
|
|
|
+ SBlock block = (SBlock)visit(ctx.trailer());
|
|
|
|
|
|
- return new SFor(line(ctx), location(ctx), intializer, condition, afterthought, block, settings.getMaxLoopCounter());
|
|
|
+ return new SFor(line(ctx), offset(ctx), location(ctx),
|
|
|
+ settings.getMaxLoopCounter(), initializer, expression, afterthought, block);
|
|
|
+ } else if (ctx.empty() != null) {
|
|
|
+ return new SFor(line(ctx), offset(ctx), location(ctx),
|
|
|
+ settings.getMaxLoopCounter(), initializer, expression, afterthought, null);
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitDecl(final DeclContext ctx) {
|
|
|
+ public Object visitDecl(DeclContext ctx) {
|
|
|
return visit(ctx.declaration());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitContinue(final ContinueContext ctx) {
|
|
|
- return new SContinue(line(ctx), location(ctx));
|
|
|
+ public Object visitContinue(ContinueContext ctx) {
|
|
|
+ return new SContinue(line(ctx), offset(ctx), location(ctx));
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitBreak(final BreakContext ctx) {
|
|
|
- return new SBreak(line(ctx), location(ctx));
|
|
|
+ public Object visitBreak(BreakContext ctx) {
|
|
|
+ return new SBreak(line(ctx), offset(ctx), location(ctx));
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitReturn(final ReturnContext ctx) {
|
|
|
- final AExpression expression = (AExpression)visit(ctx.expression());
|
|
|
+ public Object visitReturn(ReturnContext ctx) {
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
|
|
|
- return new SReturn(line(ctx), location(ctx), expression);
|
|
|
+ return new SReturn(line(ctx), offset(ctx), location(ctx), expression);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitTry(final TryContext ctx) {
|
|
|
- final AStatement block = (AStatement)visit(ctx.block());
|
|
|
- final List<STrap> traps = new ArrayList<>();
|
|
|
+ public Object visitTry(TryContext ctx) {
|
|
|
+ SBlock block = (SBlock)visit(ctx.block());
|
|
|
+ List<SCatch> catches = new ArrayList<>();
|
|
|
|
|
|
- for (final TrapContext trap : ctx.trap()) {
|
|
|
- traps.add((STrap)visit(trap));
|
|
|
+ for (TrapContext trap : ctx.trap()) {
|
|
|
+ catches.add((SCatch)visit(trap));
|
|
|
}
|
|
|
|
|
|
- return new STry(line(ctx), location(ctx), block, traps);
|
|
|
+ return new STry(line(ctx), offset(ctx), location(ctx), block, catches);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitThrow(final ThrowContext ctx) {
|
|
|
- final AExpression expression = (AExpression)visit(ctx.expression());
|
|
|
+ public Object visitThrow(ThrowContext ctx) {
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
|
|
|
- return new SThrow(line(ctx), location(ctx), expression);
|
|
|
+ return new SThrow(line(ctx), offset(ctx), location(ctx), expression);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitExpr(final ExprContext ctx) {
|
|
|
- final AExpression expression = (AExpression)visit(ctx.expression());
|
|
|
+ public Object visitExpr(ExprContext ctx) {
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
|
|
|
- return new SExpression(line(ctx), location(ctx), expression);
|
|
|
+ return new SExpression(line(ctx), offset(ctx), location(ctx), expression);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitMultiple(final MultipleContext ctx) {
|
|
|
- final List<AStatement> statements = new ArrayList<>();
|
|
|
+ public Object visitTrailer(TrailerContext ctx) {
|
|
|
+ if (ctx.block() != null) {
|
|
|
+ return visit(ctx.block());
|
|
|
+ } else if (ctx.statement() != null) {
|
|
|
+ List<AStatement> statements = new ArrayList<>();
|
|
|
+ statements.add((AStatement)visit(ctx.statement()));
|
|
|
|
|
|
- for (final StatementContext statement : ctx.statement()) {
|
|
|
- statements.add((AStatement)visit(statement));
|
|
|
+ return new SBlock(line(ctx), offset(ctx), location(ctx), statements);
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
-
|
|
|
- return new SBlock(line(ctx), location(ctx), statements);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitSingle(final SingleContext ctx) {
|
|
|
- final List<AStatement> statements = new ArrayList<>();
|
|
|
- statements.add((AStatement)visit(ctx.statement()));
|
|
|
+ public Object visitBlock(BlockContext ctx) {
|
|
|
+ if (ctx.statement().isEmpty()) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ List<AStatement> statements = new ArrayList<>();
|
|
|
|
|
|
- return new SBlock(line(ctx), location(ctx), statements);
|
|
|
- }
|
|
|
+ for (StatementContext statement : ctx.statement()) {
|
|
|
+ statements.add((AStatement)visit(statement));
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public ANode visitEmpty(final EmptyContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ return new SBlock(line(ctx), offset(ctx), location(ctx), statements);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitEmptyscope(final EmptyscopeContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitEmpty(EmptyContext ctx) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitInitializer(final InitializerContext ctx) {
|
|
|
+ public Object visitInitializer(InitializerContext ctx) {
|
|
|
if (ctx.declaration() != null) {
|
|
|
return visit(ctx.declaration());
|
|
|
} else if (ctx.expression() != null) {
|
|
|
- return visit(ctx.expression());
|
|
|
- }
|
|
|
-
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitAfterthought(final AfterthoughtContext ctx) {
|
|
|
- return visit(ctx.expression());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitDeclaration(final DeclarationContext ctx) {
|
|
|
- final String type = ctx.decltype().getText();
|
|
|
- final List<SDeclaration> declarations = new ArrayList<>();
|
|
|
-
|
|
|
- for (final DeclvarContext declvar : ctx.declvar()) {
|
|
|
- final String name = declvar.identifier().getText();
|
|
|
- final AExpression expression = declvar.expression() == null ? null : (AExpression)visit(declvar.expression());
|
|
|
- declarations.add(new SDeclaration(line(ctx), location(ctx), type, name, expression));
|
|
|
+ return visitExpression(ctx.expression());
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
-
|
|
|
- return new SDeclBlock(line(ctx), location(ctx), declarations);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitDecltype(final DecltypeContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitAfterthought(AfterthoughtContext ctx) {
|
|
|
+ return visitExpression(ctx.expression());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitDeclvar(final DeclvarContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitTrap(final TrapContext ctx) {
|
|
|
- final String type = ctx.identifier(0).getText();
|
|
|
- final String name = ctx.identifier(1).getText();
|
|
|
- final AStatement block = ctx.block() == null ? null : (AStatement)visit(ctx.block());
|
|
|
+ public Object visitDeclaration(DeclarationContext ctx) {
|
|
|
+ String type = ctx.decltype().getText();
|
|
|
+ List<SDeclaration> declarations = new ArrayList<>();
|
|
|
|
|
|
- return new STrap(line(ctx), location(ctx), type, name, block);
|
|
|
- }
|
|
|
+ for (DeclvarContext declvar : ctx.declvar()) {
|
|
|
+ String name = declvar.ID().getText();
|
|
|
+ AExpression expression = declvar.expression() == null ? null : (AExpression)visitExpression(declvar.expression());
|
|
|
|
|
|
- @Override
|
|
|
- public ANode visitIdentifier(final IdentifierContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitGeneric(final GenericContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitPrecedence(final PrecedenceContext ctx) {
|
|
|
- return visit(ctx.expression());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ANode visitNumeric(final NumericContext ctx) {
|
|
|
- final boolean negate = ctx.parent instanceof UnaryContext && ((UnaryContext)ctx.parent).SUB() != null;
|
|
|
-
|
|
|
- if (ctx.DECIMAL() != null) {
|
|
|
- return new EDecimal(line(ctx), location(ctx), (negate ? "-" : "") + ctx.DECIMAL().getText());
|
|
|
- } else if (ctx.HEX() != null) {
|
|
|
- return new ENumeric(line(ctx), location(ctx), (negate ? "-" : "") + ctx.HEX().getText().substring(2), 16);
|
|
|
- } else if (ctx.INTEGER() != null) {
|
|
|
- return new ENumeric(line(ctx), location(ctx), (negate ? "-" : "") + ctx.INTEGER().getText(), 10);
|
|
|
- } else if (ctx.OCTAL() != null) {
|
|
|
- return new ENumeric(line(ctx), location(ctx), (negate ? "-" : "") + ctx.OCTAL().getText().substring(1), 8);
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ declarations.add(new SDeclaration(line(ctx), offset(ctx), location(ctx), type, name, expression));
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- @Override
|
|
|
- public ANode visitTrue(final TrueContext ctx) {
|
|
|
- return new EBoolean(line(ctx), location(ctx), true);
|
|
|
+ return new SDeclBlock(line(ctx), offset(ctx), location(ctx), declarations);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitFalse(FalseContext ctx) {
|
|
|
- return new EBoolean(line(ctx), location(ctx), false);
|
|
|
+ public Object visitDecltype(DecltypeContext ctx) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitNull(final NullContext ctx) {
|
|
|
- return new ENull(line(ctx), location(ctx));
|
|
|
+ public Object visitDeclvar(DeclvarContext ctx) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitPostinc(final PostincContext ctx) {
|
|
|
- final List<ALink> links = new ArrayList<>();
|
|
|
- final Operation operation;
|
|
|
-
|
|
|
- visitChain(ctx.chain(), links);
|
|
|
-
|
|
|
- if (ctx.INCR() != null) {
|
|
|
- operation = Operation.INCR;
|
|
|
- } else if (ctx.DECR() != null) {
|
|
|
- operation = Operation.DECR;
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
+ public Object visitTrap(TrapContext ctx) {
|
|
|
+ String type = ctx.TYPE().getText();
|
|
|
+ String name = ctx.ID().getText();
|
|
|
+ SBlock block = (SBlock)visit(ctx.block());
|
|
|
|
|
|
- return new EChain(line(ctx), location(ctx), links, false, true, operation, null);
|
|
|
+ return new SCatch(line(ctx), offset(ctx), location(ctx), type, name, block);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitPreinc(final PreincContext ctx) {
|
|
|
- final List<ALink> links = new ArrayList<>();
|
|
|
- final Operation operation;
|
|
|
-
|
|
|
- visitChain(ctx.chain(), links);
|
|
|
-
|
|
|
- if (ctx.INCR() != null) {
|
|
|
- operation = Operation.INCR;
|
|
|
- } else if (ctx.DECR() != null) {
|
|
|
- operation = Operation.DECR;
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- return new EChain(line(ctx), location(ctx), links, true, false, operation, null);
|
|
|
+ public Object visitDelimiter(DelimiterContext ctx) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public ANode visitRead(final ReadContext ctx) {
|
|
|
- final List<ALink> links = new ArrayList<>();
|
|
|
-
|
|
|
- visitChain(ctx.chain(), links);
|
|
|
+ private Object visitExpression(ExpressionContext ctx) {
|
|
|
+ Object expression = visit(ctx);
|
|
|
|
|
|
- return new EChain(line(ctx), location(ctx), links, false, false, null, null);
|
|
|
- }
|
|
|
+ if (expression instanceof List) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)expression;
|
|
|
|
|
|
- @Override
|
|
|
- public ANode visitUnary(final UnaryContext ctx) {
|
|
|
- if (ctx.SUB() != null && ctx.expression() instanceof NumericContext) {
|
|
|
- return visit(ctx.expression());
|
|
|
+ return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, null, null);
|
|
|
} else {
|
|
|
- final Operation operation;
|
|
|
-
|
|
|
- if (ctx.BOOLNOT() != null) {
|
|
|
- operation = Operation.NOT;
|
|
|
- } else if (ctx.BWNOT() != null) {
|
|
|
- operation = Operation.BWNOT;
|
|
|
- } else if (ctx.ADD() != null) {
|
|
|
- operation = Operation.ADD;
|
|
|
- } else if (ctx.SUB() != null) {
|
|
|
- operation = Operation.SUB;
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
-
|
|
|
- return new EUnary(line(ctx), location(ctx), operation, (AExpression)visit(ctx.expression()));
|
|
|
+ return expression;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitCast(final CastContext ctx) {
|
|
|
- return new EExplicit(line(ctx), location(ctx), ctx.decltype().getText(), (AExpression)visit(ctx.expression()));
|
|
|
+ public Object visitSingle(SingleContext ctx) {
|
|
|
+ return visit(ctx.unary());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitBinary(final BinaryContext ctx) {
|
|
|
- final AExpression left = (AExpression)visit(ctx.expression(0));
|
|
|
- final AExpression right = (AExpression)visit(ctx.expression(1));
|
|
|
+ public Object visitBinary(BinaryContext ctx) {
|
|
|
+ AExpression left = (AExpression)visitExpression(ctx.expression(0));
|
|
|
+ AExpression right = (AExpression)visitExpression(ctx.expression(1));
|
|
|
final Operation operation;
|
|
|
|
|
|
if (ctx.MUL() != null) {
|
|
|
@@ -487,13 +460,13 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
}
|
|
|
|
|
|
- return new EBinary(line(ctx), location(ctx), operation, left, right);
|
|
|
+ return new EBinary(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitComp(PainlessParser.CompContext ctx) {
|
|
|
- final AExpression left = (AExpression)visit(ctx.expression(0));
|
|
|
- final AExpression right = (AExpression)visit(ctx.expression(1));
|
|
|
+ public Object visitComp(CompContext ctx) {
|
|
|
+ AExpression left = (AExpression)visitExpression(ctx.expression(0));
|
|
|
+ AExpression right = (AExpression)visitExpression(ctx.expression(1));
|
|
|
final Operation operation;
|
|
|
|
|
|
if (ctx.LT() != null) {
|
|
|
@@ -516,13 +489,13 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
}
|
|
|
|
|
|
- return new EComp(line(ctx), location(ctx), operation, left, right);
|
|
|
+ return new EComp(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitBool(PainlessParser.BoolContext ctx) {
|
|
|
- final AExpression left = (AExpression)visit(ctx.expression(0));
|
|
|
- final AExpression right = (AExpression)visit(ctx.expression(1));
|
|
|
+ public Object visitBool(BoolContext ctx) {
|
|
|
+ AExpression left = (AExpression)visitExpression(ctx.expression(0));
|
|
|
+ AExpression right = (AExpression)visitExpression(ctx.expression(1));
|
|
|
final Operation operation;
|
|
|
|
|
|
if (ctx.BOOLAND() != null) {
|
|
|
@@ -533,27 +506,27 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
}
|
|
|
|
|
|
- return new EBool(line(ctx), location(ctx), operation, left, right);
|
|
|
+ return new EBool(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
@Override
|
|
|
- public ANode visitConditional(final ConditionalContext ctx) {
|
|
|
- final AExpression condition = (AExpression)visit(ctx.expression(0));
|
|
|
- final AExpression left = (AExpression)visit(ctx.expression(1));
|
|
|
- final AExpression right = (AExpression)visit(ctx.expression(2));
|
|
|
+ public Object visitConditional(ConditionalContext ctx) {
|
|
|
+ AExpression condition = (AExpression)visitExpression(ctx.expression(0));
|
|
|
+ AExpression left = (AExpression)visitExpression(ctx.expression(1));
|
|
|
+ AExpression right = (AExpression)visitExpression(ctx.expression(2));
|
|
|
|
|
|
- return new EConditional(line(ctx), location(ctx), condition, left, right);
|
|
|
+ return new EConditional(line(ctx), offset(ctx), location(ctx), condition, left, right);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitAssignment(final AssignmentContext ctx) {
|
|
|
- final List<ALink> links = new ArrayList<>();
|
|
|
+ public Object visitAssignment(AssignmentContext ctx) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)visit(ctx.chain());
|
|
|
final Operation operation;
|
|
|
|
|
|
- visitChain(ctx.chain(), links);
|
|
|
-
|
|
|
- if (ctx.AMUL() != null) {
|
|
|
+ if (ctx.ASSIGN() != null) {
|
|
|
+ operation = null;
|
|
|
+ } else if (ctx.AMUL() != null) {
|
|
|
operation = Operation.MUL;
|
|
|
} else if (ctx.ADIV() != null) {
|
|
|
operation = Operation.DIV;
|
|
|
@@ -576,222 +549,290 @@ public final class Walker extends PainlessParserBaseVisitor<ANode> {
|
|
|
} else if (ctx.AOR() != null) {
|
|
|
operation = Operation.BWOR;
|
|
|
} else {
|
|
|
- operation = null;
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
- return new EChain(line(ctx), location(ctx), links, false, false, operation, (AExpression)visit(ctx.expression()));
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
+
|
|
|
+ return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, operation, expression);
|
|
|
}
|
|
|
|
|
|
- private void visitChain(final ChainContext ctx, final List<ALink> links) {
|
|
|
- if (ctx.linkprec() != null) {
|
|
|
- visitLinkprec(ctx.linkprec(), links);
|
|
|
- } else if (ctx.linkcast() != null) {
|
|
|
- visitLinkcast(ctx.linkcast(), links);
|
|
|
- } else if (ctx.linkvar() != null) {
|
|
|
- visitLinkvar(ctx.linkvar(), links);
|
|
|
- } else if (ctx.linknew() != null) {
|
|
|
- visitLinknew(ctx.linknew(), links);
|
|
|
- } else if (ctx.linkstring() != null) {
|
|
|
- visitLinkstring(ctx.linkstring(), links);
|
|
|
+ private Object visitUnary(UnaryContext ctx) {
|
|
|
+ Object expression = visit(ctx);
|
|
|
+
|
|
|
+ if (expression instanceof List) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)expression;
|
|
|
+
|
|
|
+ return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, null, null);
|
|
|
} else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ return expression;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitChain(final ChainContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
+ public Object visitPre(PreContext ctx) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)visit(ctx.chain());
|
|
|
+ final Operation operation;
|
|
|
|
|
|
- private void visitLinkprec(final LinkprecContext ctx, final List<ALink> links) {
|
|
|
- if (ctx.linkprec() != null) {
|
|
|
- visitLinkprec(ctx.linkprec(), links);
|
|
|
- } else if (ctx.linkcast() != null) {
|
|
|
- visitLinkcast(ctx.linkcast(), links);
|
|
|
- } else if (ctx.linkvar() != null) {
|
|
|
- visitLinkvar(ctx.linkvar(), links);
|
|
|
- } else if (ctx.linknew() != null) {
|
|
|
- visitLinknew(ctx.linknew(), links);
|
|
|
- } else if (ctx.linkstring() != null) {
|
|
|
- visitLinkstring(ctx.linkstring(), links);
|
|
|
+ if (ctx.INCR() != null) {
|
|
|
+ operation = Operation.INCR;
|
|
|
+ } else if (ctx.DECR() != null) {
|
|
|
+ operation = Operation.DECR;
|
|
|
} else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
- }
|
|
|
+ return new EChain(line(ctx), offset(ctx), location(ctx), links, true, false, operation, null);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkprec(final LinkprecContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
- }
|
|
|
+ public Object visitPost(PostContext ctx) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)visit(ctx.chain());
|
|
|
+ final Operation operation;
|
|
|
|
|
|
- private void visitLinkcast(final LinkcastContext ctx, final List<ALink> links) {
|
|
|
- if (ctx.linkprec() != null) {
|
|
|
- visitLinkprec(ctx.linkprec(), links);
|
|
|
- } else if (ctx.linkcast() != null) {
|
|
|
- visitLinkcast(ctx.linkcast(), links);
|
|
|
- } else if (ctx.linkvar() != null) {
|
|
|
- visitLinkvar(ctx.linkvar(), links);
|
|
|
- } else if (ctx.linknew() != null) {
|
|
|
- visitLinknew(ctx.linknew(), links);
|
|
|
- } else if (ctx.linkstring() != null) {
|
|
|
- visitLinkstring(ctx.linkstring(), links);
|
|
|
+ if (ctx.INCR() != null) {
|
|
|
+ operation = Operation.INCR;
|
|
|
+ } else if (ctx.DECR() != null) {
|
|
|
+ operation = Operation.DECR;
|
|
|
} else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
|
|
}
|
|
|
|
|
|
- links.add(new LCast(line(ctx), location(ctx), ctx.decltype().getText()));
|
|
|
+ return new EChain(line(ctx), offset(ctx), location(ctx), links, false, true, operation, null);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkcast(final LinkcastContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitRead(ReadContext ctx) {
|
|
|
+ return visit(ctx.chain());
|
|
|
}
|
|
|
|
|
|
- private void visitLinkbrace(final LinkbraceContext ctx, final List<ALink> links) {
|
|
|
- links.add(new LBrace(line(ctx), location(ctx), (AExpression)visit(ctx.expression())));
|
|
|
+ @Override
|
|
|
+ public Object visitNumeric(NumericContext ctx) {
|
|
|
+ final boolean negate = ctx.parent instanceof OperatorContext && ((OperatorContext)ctx.parent).SUB() != null;
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ if (ctx.DECIMAL() != null) {
|
|
|
+ return new EDecimal(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.DECIMAL().getText());
|
|
|
+ } else if (ctx.HEX() != null) {
|
|
|
+ return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.HEX().getText().substring(2), 16);
|
|
|
+ } else if (ctx.INTEGER() != null) {
|
|
|
+ return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.INTEGER().getText(), 10);
|
|
|
+ } else if (ctx.OCTAL() != null) {
|
|
|
+ return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.OCTAL().getText().substring(1), 8);
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkbrace(final LinkbraceContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitTrue(TrueContext ctx) {
|
|
|
+ return new EBoolean(line(ctx), offset(ctx), location(ctx), true);
|
|
|
}
|
|
|
|
|
|
- private void visitLinkdot(final LinkdotContext ctx, final List<ALink> links) {
|
|
|
- if (ctx.linkcall() != null) {
|
|
|
- visitLinkcall(ctx.linkcall(), links);
|
|
|
- } else if (ctx.linkfield() != null) {
|
|
|
- visitLinkfield(ctx.linkfield(), links);
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public Object visitFalse(FalseContext ctx) {
|
|
|
+ return new EBoolean(line(ctx), offset(ctx), location(ctx), false);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkdot(final LinkdotContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitNull(NullContext ctx) {
|
|
|
+ return new ENull(line(ctx), offset(ctx), location(ctx));
|
|
|
}
|
|
|
|
|
|
- private void visitLinkcall(final LinkcallContext ctx, final List<ALink> links) {
|
|
|
- final List<AExpression> arguments = new ArrayList<>();
|
|
|
-
|
|
|
- for (final ExpressionContext expression : ctx.arguments().expression()) {
|
|
|
- arguments.add((AExpression)visit(expression));
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public Object visitOperator(OperatorContext ctx) {
|
|
|
+ if (ctx.SUB() != null && ctx.unary() instanceof NumericContext) {
|
|
|
+ return visit(ctx.unary());
|
|
|
+ } else {
|
|
|
+ AExpression expression = (AExpression)visitUnary(ctx.unary());
|
|
|
+ final Operation operation;
|
|
|
|
|
|
- links.add(new LCall(line(ctx), location(ctx), ctx.EXTID().getText(), arguments));
|
|
|
+ if (ctx.BOOLNOT() != null) {
|
|
|
+ operation = Operation.NOT;
|
|
|
+ } else if (ctx.BWNOT() != null) {
|
|
|
+ operation = Operation.BWNOT;
|
|
|
+ } else if (ctx.ADD() != null) {
|
|
|
+ operation = Operation.ADD;
|
|
|
+ } else if (ctx.SUB() != null) {
|
|
|
+ operation = Operation.SUB;
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
+ }
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ return new EUnary(line(ctx), offset(ctx), location(ctx), operation, expression);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkcall(final LinkcallContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitCast(CastContext ctx) {
|
|
|
+ String type = ctx.decltype().getText();
|
|
|
+ Object child = visit(ctx.unary());
|
|
|
+
|
|
|
+ if (child instanceof List) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)child;
|
|
|
+ links.add(new LCast(line(ctx), offset(ctx), location(ctx), type));
|
|
|
+
|
|
|
+ return links;
|
|
|
+ } else {
|
|
|
+ return new EExplicit(line(ctx), offset(ctx), location(ctx), type, (AExpression)child);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void visitLinkvar(final LinkvarContext ctx, final List<ALink> links) {
|
|
|
- final String name = ctx.identifier().getText();
|
|
|
+ @Override
|
|
|
+ public Object visitDynamic(DynamicContext ctx) {
|
|
|
+ Object child = visit(ctx.primary());
|
|
|
|
|
|
- reserved.markReserved(name);
|
|
|
+ if (child instanceof List) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ List<ALink> links = (List<ALink>)child;
|
|
|
|
|
|
- links.add(new LVariable(line(ctx), location(ctx), name));
|
|
|
+ for (SecondaryContext secondary : ctx.secondary()) {
|
|
|
+ links.add((ALink)visit(secondary));
|
|
|
+ }
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ return links;
|
|
|
+ } else if (!ctx.secondary().isEmpty()) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
+ } else {
|
|
|
+ return child;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkvar(final LinkvarContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitStatic(StaticContext ctx) {
|
|
|
+ String type = ctx.decltype().getText();
|
|
|
+ List<ALink> links = new ArrayList<>();
|
|
|
+
|
|
|
+ links.add(new LStatic(line(ctx), offset(ctx), location(ctx), type));
|
|
|
+ links.add((ALink)visit(ctx.dot()));
|
|
|
+
|
|
|
+ for (SecondaryContext secondary : ctx.secondary()) {
|
|
|
+ links.add((ALink)visit(secondary));
|
|
|
+ }
|
|
|
+
|
|
|
+ return links;
|
|
|
}
|
|
|
|
|
|
- private void visitLinkfield(final LinkfieldContext ctx, final List<ALink> links) {
|
|
|
- final String value;
|
|
|
+ @Override
|
|
|
+ public Object visitNewarray(NewarrayContext ctx) {
|
|
|
+ String type = ctx.TYPE().getText();
|
|
|
+ List<AExpression> expressions = new ArrayList<>();
|
|
|
|
|
|
- if (ctx.EXTID() != null) {
|
|
|
- value = ctx.EXTID().getText();
|
|
|
- } else if (ctx.EXTINTEGER() != null) {
|
|
|
- value = ctx.EXTINTEGER().getText();
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ for (ExpressionContext expression : ctx.expression()) {
|
|
|
+ expressions.add((AExpression)visitExpression(expression));
|
|
|
}
|
|
|
|
|
|
- links.add(new LField(line(ctx), location(ctx), value));
|
|
|
+ List<ALink> links = new ArrayList<>();
|
|
|
+ links.add(new LNewArray(line(ctx), offset(ctx), location(ctx), type, expressions));
|
|
|
+
|
|
|
+ if (ctx.dot() != null) {
|
|
|
+ links.add((ALink)visit(ctx.dot()));
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ for (SecondaryContext secondary : ctx.secondary()) {
|
|
|
+ links.add((ALink)visit(secondary));
|
|
|
+ }
|
|
|
+ } else if (!ctx.secondary().isEmpty()) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
+
|
|
|
+ return links;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkfield(final LinkfieldContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitExprprec(ExprprecContext ctx) {
|
|
|
+ return visit(ctx.expression());
|
|
|
}
|
|
|
|
|
|
- private void visitLinknew(final LinknewContext ctx, final List<ALink> links) {
|
|
|
- final List<AExpression> arguments = new ArrayList<>();
|
|
|
+ @Override
|
|
|
+ public Object visitChainprec(ChainprecContext ctx) {
|
|
|
+ return visit(ctx.unary());
|
|
|
+ }
|
|
|
|
|
|
- if (ctx.arguments() != null) {
|
|
|
- for (final ExpressionContext expression : ctx.arguments().expression()) {
|
|
|
- arguments.add((AExpression)visit(expression));
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public Object visitString(StringContext ctx) {
|
|
|
+ String string = ctx.STRING().getText().substring(1, ctx.STRING().getText().length() - 1);
|
|
|
+ List<ALink> links = new ArrayList<>();
|
|
|
+ links.add(new LString(line(ctx), offset(ctx), location(ctx), string));
|
|
|
|
|
|
- links.add(new LNewObj(line(ctx), location(ctx), ctx.identifier().getText(), arguments));
|
|
|
- } else if (ctx.expression().size() > 0) {
|
|
|
- for (final ExpressionContext expression : ctx.expression()) {
|
|
|
- arguments.add((AExpression)visit(expression));
|
|
|
- }
|
|
|
+ return links;
|
|
|
+ }
|
|
|
|
|
|
- links.add(new LNewArray(line(ctx), location(ctx), ctx.identifier().getText(), arguments));
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ @Override
|
|
|
+ public Object visitVariable(VariableContext ctx) {
|
|
|
+ String name = ctx.ID().getText();
|
|
|
+ List<ALink> links = new ArrayList<>();
|
|
|
+ links.add(new LVariable(line(ctx), offset(ctx), location(ctx), name));
|
|
|
+
|
|
|
+ reserved.markReserved(name);
|
|
|
+
|
|
|
+ return links;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Object visitNewobject(NewobjectContext ctx) {
|
|
|
+ String type = ctx.TYPE().getText();
|
|
|
+ List<AExpression> arguments = new ArrayList<>();
|
|
|
+
|
|
|
+ for (ExpressionContext expression : ctx.arguments().expression()) {
|
|
|
+ arguments.add((AExpression)visitExpression(expression));
|
|
|
}
|
|
|
|
|
|
- if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ List<ALink> links = new ArrayList<>();
|
|
|
+ links.add(new LNewObj(line(ctx), offset(ctx), location(ctx), type, arguments));
|
|
|
+
|
|
|
+ return links;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Object visitSecondary(SecondaryContext ctx) {
|
|
|
+ if (ctx.dot() != null) {
|
|
|
+ return visit(ctx.dot());
|
|
|
+ } else if (ctx.brace() != null) {
|
|
|
+ return visit(ctx.brace());
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinknew(final LinknewContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitCallinvoke(CallinvokeContext ctx) {
|
|
|
+ String name = ctx.DOTID().getText();
|
|
|
+ List<AExpression> arguments = new ArrayList<>();
|
|
|
+
|
|
|
+ for (ExpressionContext expression : ctx.arguments().expression()) {
|
|
|
+ arguments.add((AExpression)visitExpression(expression));
|
|
|
+ }
|
|
|
+
|
|
|
+ return new LCall(line(ctx), offset(ctx), location(ctx), name, arguments);
|
|
|
}
|
|
|
|
|
|
- private void visitLinkstring(final LinkstringContext ctx, final List<ALink> links) {
|
|
|
- links.add(new LString(line(ctx), location(ctx), ctx.STRING().getText().substring(1, ctx.STRING().getText().length() - 1)));
|
|
|
+ @Override
|
|
|
+ public Object visitFieldaccess(FieldaccessContext ctx) {
|
|
|
+ final String value;
|
|
|
|
|
|
- if (ctx.linkbrace() != null) {
|
|
|
- visitLinkbrace(ctx.linkbrace(), links);
|
|
|
- } else if (ctx.linkdot() != null) {
|
|
|
- visitLinkdot(ctx.linkdot(), links);
|
|
|
+ if (ctx.DOTID() != null) {
|
|
|
+ value = ctx.DOTID().getText();
|
|
|
+ } else if (ctx.DOTINTEGER() != null) {
|
|
|
+ value = ctx.DOTINTEGER().getText();
|
|
|
+ } else {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
+
|
|
|
+ return new LField(line(ctx), offset(ctx), location(ctx), value);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitLinkstring(final LinkstringContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitBraceaccess(BraceaccessContext ctx) {
|
|
|
+ AExpression expression = (AExpression)visitExpression(ctx.expression());
|
|
|
+
|
|
|
+ return new LBrace(line(ctx), offset(ctx), location(ctx), expression);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ANode visitArguments(final ArgumentsContext ctx) {
|
|
|
- throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
|
|
+ public Object visitArguments(ArgumentsContext ctx) {
|
|
|
+ throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
|
|
}
|
|
|
}
|