package nl.uva.sc.encoders.ql.parser;
import java.util.ArrayList;
import java.util.List;
import nl.uva.sc.encoders.ql.EncodersQLBaseVisitor;
import nl.uva.sc.encoders.ql.EncodersQLParser.AddSubContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.AndContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.BracedExpressionContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.ConditionalBlockContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.ExpressionContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.LiteralExpressionContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.LtGtLeGeContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.MulDivContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.NameExpressionContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.NeEqContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.NotContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.OrContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.QuestionContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.QuestionnaireContext;
import nl.uva.sc.encoders.ql.EncodersQLParser.StatementContext;
import nl.uva.sc.encoders.ql.ast.AstNode;
import nl.uva.sc.encoders.ql.ast.Questionnaire;
import nl.uva.sc.encoders.ql.ast.TextLocation;
import nl.uva.sc.encoders.ql.ast.expression.BinaryExpression;
import nl.uva.sc.encoders.ql.ast.expression.BracedExpression;
import nl.uva.sc.encoders.ql.ast.expression.Expression;
import nl.uva.sc.encoders.ql.ast.expression.LiteralExpression;
import nl.uva.sc.encoders.ql.ast.expression.NameExpression;
import nl.uva.sc.encoders.ql.ast.expression.UnaryExpression;
import nl.uva.sc.encoders.ql.ast.literal.Literal;
import nl.uva.sc.encoders.ql.ast.operator.AddOperator;
import nl.uva.sc.encoders.ql.ast.operator.AndOperator;
import nl.uva.sc.encoders.ql.ast.operator.BinaryOperator;
import nl.uva.sc.encoders.ql.ast.operator.DivideOperator;
import nl.uva.sc.encoders.ql.ast.operator.EqualsOperator;
import nl.uva.sc.encoders.ql.ast.operator.GreaterOrEqualOperator;
import nl.uva.sc.encoders.ql.ast.operator.GreaterThanOperator;
import nl.uva.sc.encoders.ql.ast.operator.LessOrEqualOperator;
import nl.uva.sc.encoders.ql.ast.operator.LessThanOperator;
import nl.uva.sc.encoders.ql.ast.operator.MultiplyOperator;
import nl.uva.sc.encoders.ql.ast.operator.NotEqualsOperator;
import nl.uva.sc.encoders.ql.ast.operator.NotOperator;
import nl.uva.sc.encoders.ql.ast.operator.OrOperator;
import nl.uva.sc.encoders.ql.ast.operator.SubstractOperator;
import nl.uva.sc.encoders.ql.ast.operator.UnaryOperator;
import nl.uva.sc.encoders.ql.ast.statement.ConditionalBlock;
import nl.uva.sc.encoders.ql.ast.statement.Question;
import nl.uva.sc.encoders.ql.ast.statement.Statement;
import nl.uva.sc.encoders.ql.ast.type.DataType;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
public class ParseTreeToAbstractSyntaxTree extends EncodersQLBaseVisitor<AstNode> {
private static final String ESCAPED_QUOTE = "\\\\\"";
private static final String UNESCAPED_QUOTE = "\\\"";
@Override
public Questionnaire visitQuestionnaire(QuestionnaireContext ctx) {
String name = ctx.name.getText();
List<Statement> statements = new ArrayList<>();
for (StatementContext statementContext : ctx.statement()) {
Statement statement = (Statement) statementContext.accept(this);
statements.add(statement);
}
TextLocation textLocation = getTextLocation(ctx);
Questionnaire questionnaire = new Questionnaire(textLocation, name, statements);
return questionnaire;
}
@Override
public ConditionalBlock visitConditionalBlock(ConditionalBlockContext ctx) {
Expression condition = (Expression) visit(ctx.expression());
List<Question> questions = new ArrayList<>();
for (QuestionContext questionContext : ctx.question()) {
Question question = (Question) visit(questionContext);
questions.add(question);
}
TextLocation textLocation = getTextLocation(ctx);
ConditionalBlock cb = new ConditionalBlock(textLocation, condition, questions);
return cb;
}
@Override
public Question visitQuestion(QuestionContext ctx) {
String questionName = ctx.name.getText();
DataType dataType = ctx.type.accept(new TypeParser());
String questionLabel = ctx.label.getText();
questionLabel = removeFirstAndListCharOfString(questionLabel);
questionLabel = unescapedString(questionLabel);
Expression computed = null;
TextLocation textLocation = getTextLocation(ctx);
ExpressionContext computedCtx = ctx.computed;
if (computedCtx != null) {
computed = (Expression) visit(computedCtx);
}
Question question = new Question(textLocation, questionName, dataType, questionLabel, computed);
return question;
}
private String removeFirstAndListCharOfString(String string) {
return string.substring(1, string.length() - 1);
}
private String unescapedString(String escapedString) {
return escapedString.replaceAll(ESCAPED_QUOTE, UNESCAPED_QUOTE);
}
@Override
public BracedExpression visitBracedExpression(BracedExpressionContext ctx) {
Expression expression = (Expression) visit(ctx.expression());
TextLocation textLocation = getTextLocation(ctx);
return new BracedExpression(textLocation, expression);
}
@Override
public NameExpression visitNameExpression(NameExpressionContext ctx) {
TextLocation textLocation = getTextLocation(ctx);
String text = ctx.name.getText();
return new NameExpression(textLocation, text);
}
@Override
public BinaryExpression visitNeEq(NeEqContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public BinaryExpression visitMulDiv(MulDivContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public BinaryExpression visitLtGtLeGe(LtGtLeGeContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public BinaryExpression visitOr(OrContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public BinaryExpression visitAddSub(AddSubContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public BinaryExpression visitAnd(AndContext ctx) {
String operator = ctx.operator.getText();
BinaryOperator binaryOperator = getBinaryOperator(operator);
Expression leftHand = (Expression) visit(ctx.leftHand);
Expression rightHand = (Expression) visit(ctx.rightHand);
TextLocation textLocation = getTextLocation(ctx);
return new BinaryExpression(textLocation, leftHand, rightHand, binaryOperator);
}
@Override
public UnaryExpression visitNot(NotContext ctx) {
String operator = ctx.operator.getText();
UnaryOperator unaryOperator = getUnaryOperator(operator);
Expression expression = (Expression) visit(ctx.expr);
TextLocation textLocation = getTextLocation(ctx);
return new UnaryExpression(textLocation, unaryOperator, expression);
}
@Override
public LiteralExpression visitLiteralExpression(LiteralExpressionContext ctx) {
TextLocation textLocation = getTextLocation(ctx);
Literal literal = ctx.literal().accept(new LiteralParser());
return new LiteralExpression(textLocation, literal);
}
private TextLocation getTextLocation(ParserRuleContext ctx) {
Token start = ctx.getStart();
int line = start.getLine();
int column = start.getCharPositionInLine();
return new TextLocation(line, column);
}
private BinaryOperator getBinaryOperator(String operator) {
switch (operator) {
case "*":
return new MultiplyOperator(operator);
case "/":
return new DivideOperator(operator);
case "+":
return new AddOperator(operator);
case "-":
return new SubstractOperator(operator);
case "&&":
return new AndOperator(operator);
case "||":
return new OrOperator(operator);
case "<":
return new LessThanOperator(operator);
case ">":
return new GreaterThanOperator(operator);
case "<=":
return new LessOrEqualOperator(operator);
case ">=":
return new GreaterOrEqualOperator(operator);
case "!=":
return new NotEqualsOperator(operator);
case "==":
return new EqualsOperator(operator);
default:
throw new AssertionError("Operator " + operator + " is not suppoerted.");
}
}
private UnaryOperator getUnaryOperator(String operator) {
switch (operator) {
case "!":
return new NotOperator(operator);
default:
throw new AssertionError("Operator " + operator + " is not suppoerted.");
}
}
}