package uva.ql.parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.TerminalNode;
import uva.ql.ast.Node;
import uva.ql.ast.CodeLines;
import uva.ql.ast.Form;
import uva.ql.ast.Prog;
import uva.ql.ast.expressions.Expression;
import uva.ql.ast.expressions.Operator;
import uva.ql.ast.expressions.literals.Identifier;
import uva.ql.ast.expressions.literals.IntLiteral;
import uva.ql.ast.expressions.logic.And;
import uva.ql.ast.expressions.logic.Equal;
import uva.ql.ast.expressions.logic.Greater;
import uva.ql.ast.expressions.logic.Greater_Eq;
import uva.ql.ast.expressions.logic.Less;
import uva.ql.ast.expressions.logic.Less_Eq;
import uva.ql.ast.expressions.logic.NotEqual;
import uva.ql.ast.expressions.logic.Or;
import uva.ql.ast.expressions.math.Addition;
import uva.ql.ast.expressions.math.Division;
import uva.ql.ast.expressions.math.Exponentiation;
import uva.ql.ast.expressions.math.Multiplication;
import uva.ql.ast.expressions.math.Substraction;
import uva.ql.parser.QLParser.FormContext;
import uva.ql.parser.QLParser.ProgContext;
import uva.ql.parser.QLParser.StatContext;
import uva.ql.ast.expressions.literals.*;
import uva.ql.ast.statements.Assign;
import uva.ql.ast.statements.IfStatement;
import uva.ql.ast.statements.Question;
import uva.ql.ast.statements.Statement;
import uva.ql.ast.type.*;
import java.util.*;
public class QLMainVisitor extends QLBaseVisitor<Node> {
@Override
public Node visitProg(ProgContext ctx) {
CodeLines codeLines = getCodeLines(ctx);
return new Prog(visitForm(ctx.form()), codeLines);
}
@Override
public Form visitForm(FormContext ctx) {
CodeLines codeLines = getCodeLines(ctx);
return new Form(this.visitIdentifier(ctx.Identifier(), codeLines), this.getStatementList(ctx.stms), codeLines);
}
public Statement visitStat(StatContext ctx) {
return (Statement)ctx.accept(this);
}
@Override
public Assign visitCtxAssign(QLParser.CtxAssignContext ctx) {
return (Assign)ctx.assign().accept(this);
}
@Override
public IfStatement visitCtxIfStatement(QLParser.CtxIfStatementContext ctx) {
return this.visitIfStatement(ctx.ifStatement());
}
@Override
public IfStatement visitIfStatement(QLParser.IfStatementContext ctx) {
return new IfStatement((Expression)ctx.expr().accept(this), this.getStatementList(ctx.stms), this.getCodeLines(ctx));
}
@Override
public Question visitCtxQuestion(QLParser.CtxQuestionContext ctx) {
return (Question)ctx.quest().accept(this);
}
@Override
public Question visitSimpleQuestion(QLParser.SimpleQuestionContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Identifier identifier = this.visitIdentifier(ctx.Identifier(), codeLines);
Type type = (Type)ctx.primitiveType().accept(this);
StringLiteral text = this.visitStringLiteral(ctx.STRING(), codeLines);
return new Question(type, identifier, text, codeLines);
}
@Override
public Question visitComputedQuestion(QLParser.ComputedQuestionContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Identifier identifier = this.visitIdentifier(ctx.Identifier(), codeLines);
Type type = (Type)ctx.primitiveType().accept(this);
StringLiteral text = this.visitStringLiteral(ctx.STRING(), codeLines);
Assign assign = this.visitAssign(ctx.assign());
return new Question(type, identifier, text, assign.getAssignExpression(), this.getCodeLines(ctx));
}
@Override
public Assign visitAssign(QLParser.AssignContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Expression expression = (Expression)ctx.expr().accept(this);
return new Assign(this.visitIdentifier(ctx.Identifier(), codeLines), expression, codeLines);
}
@Override
public Expression visitParenthesis(QLParser.ParenthesisContext ctx) {
return (Expression)ctx.expr().accept(this);
}
@Override
public Expression visitLessEqualGreaterEqual(QLParser.LessEqualGreaterEqualContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Operator operator = Operator.findOperator(ctx.op.getText());
if (operator == Operator.LESS){
return new Less((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.LESS_EQ){
return new Less_Eq((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.GREATER){
return new Greater((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.GREATER_EQ){
return new Greater_Eq((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
return null;
}
@Override
public Expression visitMulDiv(QLParser.MulDivContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Operator operator = Operator.findOperator(ctx.op.getText());
if (operator == Operator.MUL){
return new Multiplication((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.DIV){
return new Division((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
return null;
}
@Override
public Expression visitAddSub(QLParser.AddSubContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Operator operator = Operator.findOperator(ctx.op.getText());
if (operator == Operator.ADD){
return new Addition((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.SUB){
return new Substraction((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
return null;
}
@Override
public Or visitLogOr(QLParser.LogOrContext ctx) {
return new Or((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), this.getCodeLines(ctx));
}
@Override
public Expression visitExprLiteral(QLParser.ExprLiteralContext ctx) {
return (Literal)ctx.literal().accept(this);
}
@Override
public Exponentiation visitExponentiation(QLParser.ExponentiationContext ctx) {
return new Exponentiation((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), this.getCodeLines(ctx));
}
@Override
public Expression visitEqualNot(QLParser.EqualNotContext ctx) {
CodeLines codeLines = this.getCodeLines(ctx);
Operator operator = Operator.findOperator(ctx.op.getText());
if (operator == Operator.EQUAL){
return new Equal((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
else if (operator == Operator.NOT_EQUAL){
return new NotEqual((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), codeLines);
}
return null;
}
@Override
public And visitLogAnd(QLParser.LogAndContext ctx) {
return new And((Expression)ctx.x.accept(this), (Expression)ctx.y.accept(this), this.getCodeLines(ctx));
}
public Identifier visitIdentifier(TerminalNode identifier, CodeLines codeLines){
return new Identifier(identifier.getText(), codeLines);
}
@Override
public Identifier visitCtxIdentifier(QLParser.CtxIdentifierContext ctx) {
return this.visitIdentifier(ctx.Identifier(), this.getCodeLines(ctx));
}
@Override
public BooleanLiteral visitCtxBooleanLiteral(QLParser.CtxBooleanLiteralContext ctx) {
return new BooleanLiteral(Boolean.valueOf(ctx.getText()), this.getCodeLines(ctx));
}
@Override
public IntLiteral visitCtxIntLiteral(QLParser.CtxIntLiteralContext ctx) {
return new IntLiteral(Integer.valueOf(ctx.getText()), this.getCodeLines(ctx));
}
public StringLiteral visitStringLiteral(TerminalNode STRING, CodeLines codeLines){
return new StringLiteral(STRING.getText(), codeLines);
}
@Override
public MoneyLiteral visitCtxMoneyLiteral(QLParser.CtxMoneyLiteralContext ctx) {
return new MoneyLiteral(Integer.valueOf(ctx.getText()), this.getCodeLines(ctx));
}
public Type visitPrimitiveType(QLParser.PrimitiveTypeContext ctx){
return (Type)ctx.accept(this);
}
@Override
public TypeBoolean visitBooleanPrimitive(QLParser.BooleanPrimitiveContext ctx) {
return new TypeBoolean(this.getCodeLines(ctx));
}
@Override
public TypeMoney visitMoneyPrimitive(QLParser.MoneyPrimitiveContext ctx) {
return new TypeMoney(this.getCodeLines(ctx));
}
@Override
public TypeString visitStringPrimitive(QLParser.StringPrimitiveContext ctx) {
return new TypeString(this.getCodeLines(ctx));
}
@Override
public TypeInteger visitIntPrimitive(QLParser.IntPrimitiveContext ctx) {
return new TypeInteger(this.getCodeLines(ctx));
}
private CodeLines getCodeLines(ParserRuleContext ctx){
return new CodeLines(ctx.start.getLine(),ctx.stop.getLine());
}
private List<Statement> getStatementList(List<StatContext> stms){
List<Statement> statement = new ArrayList<Statement>();
for(StatContext s : stms)
statement.add((Statement)visitStat(s));
return statement;
}
}