package ql.ast;
import ql.ast.expression.*;
import ql.ast.form.Form;
import ql.ast.statement.*;
import ql.ast.type.Type;
import ql.ast.type.TypeFactory;
import ql.util.StringHelper;
import org.antlr.v4.runtime.misc.NotNull;
/**
* Created by bore on 09/02/15.
*/
import ql.gen.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class AstBuilder extends QLBaseVisitor<AstNode>
{
@Override
public AstNode visitForm(@NotNull QLParser.FormContext context)
{
List<Statement> statements = new ArrayList<>();
for (QLParser.StatementContext statementContext : context.statement())
{
Statement s = (Statement)this.visit(statementContext);
statements.add(s);
}
String questionID = context.Identifier().getText();
int lineNumber = context.Identifier().getSymbol().getLine();
return new Form(questionID, statements, lineNumber);
}
@Override
public AstNode visitStatement(@NotNull QLParser.StatementContext context)
{
if (context.question() != null)
{
return visit(context.question());
}
if (context.ifCondition() != null)
{
return visit(context.ifCondition());
}
throw new IllegalArgumentException("Unknown statement type");
}
@Override
public AstNode visitQuestion(@NotNull QLParser.QuestionContext context)
{
String id = context.Identifier().getText();
Type questionType = TypeFactory.createType(context.QuestionType().getText());
String text = StringHelper.unescapeString(context.String().getText());
int lineNumber = context.Identifier().getSymbol().getLine();
if (context.expression() != null)
{
Expr expr = (Expr)visitExpression(context.expression());
return new CalculatedQuestion(id, questionType, text, lineNumber, expr);
}
return new Question(id, questionType, text, lineNumber);
}
@Override
public AstNode visitIfCondition(@NotNull QLParser.IfConditionContext context)
{
Expr expr = (Expr)visitExpression(context.expression());
List<Statement> ifStatements = new ArrayList<>();
for (QLParser.StatementContext statement : context.statement())
{
Statement s = (Statement)this.visit(statement);
ifStatements.add(s);
}
int lineNumber = context.getStart().getLine();
return new IfCondition(expr, ifStatements, lineNumber);
}
@Override
public AstNode visitExpression(@NotNull QLParser.ExpressionContext context)
{
if (context.parenthesis != null)
{
return this.visitExpression(context.parenthesis);
}
if (context.left != null && context.right != null)
{
return this.visitBinaryExpression(context.left, context.right, context.operator.getText());
}
if (context.operand != null)
{
return this.visitUnaryExpression(context.operand, context.operator.getText());
}
return this.visitConstantExpression(context);
}
public Expr visitBinaryExpression(QLParser.ExpressionContext lContext, QLParser.ExpressionContext rContext, String operator)
{
Expr left = (Expr)this.visit(lContext);
Expr right = (Expr)this.visit(rContext);
int lineNumber = lContext.getStart().getLine();
if (operator.equals("+")) { return new Add(left, right, lineNumber); }
if (operator.equals("-")) { return new Sub(left, right, lineNumber); }
if (operator.equals("*")) { return new Mul(left, right, lineNumber); }
if (operator.equals("/")) { return new Div(left, right, lineNumber); }
if (operator.equals(">")) { return new Gt(left, right, lineNumber); }
if (operator.equals("<")) { return new Lt(left, right, lineNumber); }
if (operator.equals(">=")) { return new GtEqu(left, right, lineNumber); }
if (operator.equals("<=")) { return new LtEqu(left, right, lineNumber); }
if (operator.equals("==")) { return new Equ(left, right, lineNumber); }
if (operator.equals("!=")) { return new NotEqu(left, right, lineNumber); }
if (operator.equals("&&")) { return new And(left, right, lineNumber); }
if (operator.equals("||")) { return new Or(left, right, lineNumber); }
throw new IllegalArgumentException("Unknown binary operator: " + operator);
}
public Expr visitUnaryExpression(QLParser.ExpressionContext operandContext, String operator)
{
Expr operand = (Expr)this.visit(operandContext);
int lineNumber = operandContext.getStart().getLine();
if (operator.equals("+")) { return new Pos(operand, lineNumber); }
if (operator.equals("-")) { return new Neg(operand, lineNumber); }
if (operator.equals("!")) { return new Not(operand, lineNumber); }
throw new IllegalArgumentException("Unknown unary operator: " + operator);
}
public Expr visitConstantExpression(QLParser.ExpressionContext operandContext)
{
int lineNumber = operandContext.getStart().getLine();
if (operandContext.Integer() != null)
{
int value = Integer.parseInt(operandContext.Integer().getText());
return new IntExpr(value, lineNumber);
}
if (operandContext.String() != null)
{
String s = StringHelper.unescapeString(operandContext.String().getText());
return new StrExpr(s, lineNumber);
}
if (operandContext.Identifier() != null)
{
return new Ident(operandContext.Identifier().getText(), lineNumber);
}
if (operandContext.Boolean() != null)
{
Boolean value = Boolean.parseBoolean(operandContext.Boolean().getText());
return new BoolExpr(value, lineNumber);
}
if (operandContext.Decimal() != null)
{
BigDecimal value = new BigDecimal(operandContext.Decimal().getText());
return new DecExpr(value, lineNumber);
}
throw new IllegalArgumentException("Unknown expression");
}
}