package ql.ast;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.misc.NotNull;
import ql.ast.expression.ExpressionInterface;
import ql.ast.expression.ExpressionParentheses;
import ql.ast.literal.LiteralBool;
import ql.ast.literal.LiteralInt;
import ql.ast.operator.OperatorAdd;
import ql.ast.operator.OperatorAnd;
import ql.ast.operator.OperatorDiv;
import ql.ast.operator.OperatorEq;
import ql.ast.operator.OperatorGt;
import ql.ast.operator.OperatorGtEq;
import ql.ast.operator.OperatorLt;
import ql.ast.operator.OperatorLtEq;
import ql.ast.operator.OperatorMod;
import ql.ast.operator.OperatorMul;
import ql.ast.operator.OperatorNeg;
import ql.ast.operator.OperatorNeq;
import ql.ast.operator.OperatorOr;
import ql.ast.operator.OperatorSub;
import ql.ast.statement.StatementAssignment;
import ql.ast.statement.StatementBoolean;
import ql.ast.statement.StatementExpressionAssignment;
import ql.ast.statement.StatementIf;
import ql.ast.statement.StatementInterface;
import ql.ast.statement.StatementMoney;
import ql.ast.statement.StatementString;
import ql.ast.statement.StatementTypeInterface;
import antlr4.TestBaseVisitor;
import antlr4.TestParser;
/**
* ASTVisitor class.
*
* Visits a given parse tree, and generates an AST.
*/
public class ASTVisitor extends TestBaseVisitor<Object> {
/* Constructor */
public ASTVisitor() { }
/* Visit a questionnare item */
@Override public Questionnaire visitQuestionnare(@NotNull TestParser.QuestionnareContext ctx) {
Questionnaire questionnaire = new Questionnaire();
/* For every 'form' object in the questionnare, add it to the Questionnare */
for(TestParser.FormContext frm : ctx.form()) {
questionnaire.add(this.visitForm(frm));
}
return questionnaire;
}
/* Visit a form rule */
@Override public Form visitForm(@NotNull TestParser.FormContext ctx) {
return new Form(ctx.ID().getText(), visitBlock(ctx.block()));
}
/* Visit a block rule */
@Override public List<StatementInterface> visitBlock(@NotNull TestParser.BlockContext ctx) {
List<StatementInterface> statements = new ArrayList<StatementInterface>();
/* Add all statements into a list */
for(TestParser.StatementContext stat : ctx.statement()) {
statements.add((StatementInterface)stat.accept(this));
}
return statements;
}
/* Visit the negation operator */
@Override public OperatorNeg visitNeg(@NotNull TestParser.NegContext ctx) {
return new OperatorNeg((ExpressionInterface) ctx.expr().accept(this));
}
/* Visit Parentheses */
@Override public ExpressionParentheses visitParentheses(@NotNull TestParser.ParenthesesContext ctx) {
return new ExpressionParentheses((ExpressionInterface) ctx.expr().accept(this));
}
/* Visit If statement */
@Override public StatementIf visitStatementIf(@NotNull TestParser.StatementIfContext ctx) {
return new StatementIf(
(ExpressionInterface) ctx.expr().accept(this),
visitBlock(ctx.block()),
new ArrayList<StatementInterface>() /* Empty, because no 'else' */
);
}
/* Visit an if-else statement operator */
@Override public StatementIf visitStatementIfElse(@NotNull TestParser.StatementIfElseContext ctx) {
return new StatementIf(
(ExpressionInterface) ctx.expr().accept(this),
visitBlock(ctx.block(1)),
visitBlock(ctx.block(1))
);
}
/* Visit a question assignment */
@Override public StatementAssignment visitStatementAssignment(@NotNull TestParser.StatementAssignmentContext ctx) {
String contents = ctx.STRING().getText();
return new StatementAssignment(
ctx.QUESTIONTITLE().getText(),
contents.substring(1, contents.length() - 1), // Remove the first and last char ("),
(StatementTypeInterface) ctx.qtype().accept(this)
);
}
/* Visit a question assignment with an expression */
@Override public StatementExpressionAssignment visitStatementExpressionAssignment(@NotNull TestParser.StatementExpressionAssignmentContext ctx) {
String contents = ctx.STRING().getText();
return new StatementExpressionAssignment(
ctx.QUESTIONTITLE().getText(),
contents.substring(1, contents.length() - 1), // Remove the first and last char ("),
(StatementTypeInterface) ctx.qtype().accept(this),
(ExpressionInterface) ctx.expr().accept(this)
);
}
/* Visit a boolean statement */
@Override public StatementBoolean visitStatementBoolean(@NotNull TestParser.StatementBooleanContext ctx) {
return new StatementBoolean();
}
/* Visit a string statement */
@Override public StatementString visitStatementString(@NotNull TestParser.StatementStringContext ctx) {
return new StatementString();
}
/* Visit a money statement */
@Override public StatementMoney visitStatementMoney(@NotNull TestParser.StatementMoneyContext ctx) {
return new StatementMoney();
}
/* Visit a logical AND operator */
@Override public OperatorAnd visitAnd(@NotNull TestParser.AndContext ctx) {
return new OperatorAnd(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit a logical OR operator*/
@Override public OperatorOr visitOr(@NotNull TestParser.OrContext ctx) {
return new OperatorOr(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit less than operator */
@Override public OperatorLt visitLt(@NotNull TestParser.LtContext ctx) {
return new OperatorLt(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit less than or equal operator */
@Override public OperatorLtEq visitLtEq(@NotNull TestParser.LtEqContext ctx) {
return new OperatorLtEq(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit greater than operator */
@Override public OperatorGt visitGt(@NotNull TestParser.GtContext ctx) {
return new OperatorGt(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit the greater than or equal operator */
@Override public Object visitGtEq(@NotNull TestParser.GtEqContext ctx) {
return new OperatorGtEq(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit not equal operator */
@Override public OperatorNeq visitNeq(@NotNull TestParser.NeqContext ctx) {
return new OperatorNeq(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit an equal to operator */
@Override public OperatorEq visitEq(@NotNull TestParser.EqContext ctx) {
return new OperatorEq(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit a modulo statement */
@Override public OperatorMod visitMod(@NotNull TestParser.ModContext ctx) {
return new OperatorMod(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit the addition operator */
@Override public OperatorAdd visitAdd(@NotNull TestParser.AddContext ctx) {
return new OperatorAdd(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit the subtraction operator */
@Override public OperatorSub visitSub(@NotNull TestParser.SubContext ctx) {
return new OperatorSub(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit a division statement */
@Override public OperatorDiv visitDiv(@NotNull TestParser.DivContext ctx) {
return new OperatorDiv(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit a multiply operator */
@Override public OperatorMul visitMul(@NotNull TestParser.MulContext ctx) {
return new OperatorMul(
(ExpressionInterface) ctx.expr(0).accept(this),
(ExpressionInterface) ctx.expr(1).accept(this)
);
}
/* Visit decimal literal */
@Override public BigDecimal visitDecimal(@NotNull TestParser.DecimalContext ctx) {
return new BigDecimal(ctx.getText());
}
/* Visit an integer literal */
@Override public Integer visitInteger(@NotNull TestParser.IntegerContext ctx) {
return Integer.parseInt(ctx.getText());
}
/* Visit the 'false' literal */
@Override public Boolean visitLiteralFalse(@NotNull TestParser.LiteralFalseContext ctx) {
return false;
}
/* Visit a bool literal */
@Override public LiteralBool visitLiteralBool(@NotNull TestParser.LiteralBoolContext ctx) {
return new LiteralBool((Boolean) ctx.boolLit().accept(this));
}
/* Visit an integer literal */
@Override public LiteralInt visitLiteralInt(@NotNull TestParser.LiteralIntContext ctx) {
return new LiteralInt((Integer) ctx.intLit().accept(this));
}
/* Visit the 'true' literal */
@Override public Boolean visitLiteralTrue(@NotNull TestParser.LiteralTrueContext ctx) {
return false;
}
}