package nl.uva.bromance.QL.ast;
import nl.uva.bromance.QL.ast.nodes.*;
import nl.uva.bromance.QL.controlstructures.Else;
import nl.uva.bromance.QL.controlstructures.ElseIf;
import nl.uva.bromance.QL.controlstructures.If;
import nl.uva.bromance.QL.controlstructures.IfSequence;
import nl.uva.bromance.QL.expressions.Expression;
import nl.uva.bromance.QL.expressions.binary.BinaryExpression;
import nl.uva.bromance.QL.expressions.binary.arithmetic.Addition;
import nl.uva.bromance.QL.expressions.binary.arithmetic.Division;
import nl.uva.bromance.QL.expressions.binary.arithmetic.Multiplication;
import nl.uva.bromance.QL.expressions.binary.arithmetic.Subtraction;
import nl.uva.bromance.QL.expressions.binary.logicalexpressions.*;
import nl.uva.bromance.QL.expressions.primitives.BooleanPrimitive;
import nl.uva.bromance.QL.expressions.primitives.NumberPrimitive;
import nl.uva.bromance.QL.expressions.primitives.StringPrimitive;
import nl.uva.bromance.QL.expressions.unary.Primitive;
import nl.uva.bromance.QL.expressions.unary.Variable;
import nl.uva.bromance.grammar.QL.QLBaseListener;
import nl.uva.bromance.grammar.QL.QLParser;
import org.antlr.v4.runtime.ParserRuleContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class QLParseTreeListener extends QLBaseListener
{
private Stack<QLNode> nodeStack = new Stack<>();
private Stack<String> identifiersStack = new Stack<>();
private Stack<Expression> expressions = new Stack<>();
private Map<String, Primitive> valueMap = new HashMap<>();
// Here to differentiate on where to add labelText
private boolean isQuestion;
private AST<QLNode> ast = null;
public AST<QLNode> getAST()
{
return ast;
}
public Map<String, Primitive> getIdentifierMap()
{
return this.valueMap;
}
@Override
public void enterQuestionnaire(QLParser.QuestionnaireContext ctx)
{
String identifier = ctx.identifier.getText().replace("\"", "");
Questionnaire questionnaire = new Questionnaire(identifier, getLine(ctx));
nodeStack.push(questionnaire);
}
@Override
public void exitQuestionnaire(QLParser.QuestionnaireContext ctx)
{
ast = new AST(nodeStack.pop());
}
@Override
public void enterForm(QLParser.FormContext ctx)
{
String identifier = removeQuotations(ctx.identifier.getText());
Form form = new Form(identifier, getLine(ctx));
nodeStack.push(form);
}
@Override
public void exitForm(QLParser.FormContext ctx)
{
Form f = (Form) nodeStack.pop();
nodeStack.peek().addChild(f);
}
@Override
public void enterQuestion(QLParser.QuestionContext ctx)
{
String identifier = removeQuotations(ctx.identifier.getText());
identifiersStack.push(identifier);
Question question = new Question(identifier, getLine(ctx));
nodeStack.push(question);
isQuestion = true;
}
@Override
public void exitQuestion(QLParser.QuestionContext ctx)
{
Question q = (Question) nodeStack.pop();
q.setType(valueMap.get(q.getIdentifier()));
nodeStack.peek().addChild(q);
isQuestion = false;
}
@Override
public void enterCalculation(QLParser.CalculationContext ctx)
{
Calculation calc = new Calculation(getLine(ctx), removeQuotations(ctx.identifier.getText()));
nodeStack.push(calc);
}
@Override
public void exitCalculation(QLParser.CalculationContext ctx)
{
Calculation calc = (Calculation) nodeStack.pop();
nodeStack.peek().addChild(calc);
}
@Override
public void enterTextLabel(QLParser.TextLabelContext ctx)
{
if (isQuestion) {
Question q = (Question) nodeStack.peek();
q.setText(removeQuotations(ctx.identifier.getText()));
}
}
@Override
public void exitIfStatement(QLParser.IfStatementContext ctx)
{
If iff = (If) nodeStack.pop();
nodeStack.peek().addChild(iff);
}
@Override
public void enterIfSequence(QLParser.IfSequenceContext ctx)
{
nodeStack.push(new IfSequence(getLine(ctx)));
}
@Override
public void exitIfSequence(QLParser.IfSequenceContext ctx)
{
IfSequence sequence = (IfSequence) nodeStack.pop();
nodeStack.peek().addChild(sequence);
}
@Override
public void exitIfCondition(QLParser.IfConditionContext ctx)
{
If iff = new If(getLine(ctx), expressions.pop());
nodeStack.push(iff);
}
@Override
public void enterElseStatement(QLParser.ElseStatementContext ctx)
{
Else _else = new Else(getLine(ctx));
nodeStack.push(_else);
}
@Override
public void exitElseStatement(QLParser.ElseStatementContext ctx)
{
Else _else = (Else) nodeStack.pop();
nodeStack.peek().addChild(_else);
}
@Override
public void exitElseIfCondition(QLParser.ElseIfConditionContext ctx)
{
ElseIf eif = new ElseIf(getLine(ctx), (LogicalExpression) expressions.pop());
nodeStack.push(eif);
}
@Override
public void exitElseIfStatement(QLParser.ElseIfStatementContext ctx)
{
ElseIf eif = (ElseIf) nodeStack.pop();
nodeStack.peek().addChild(eif);
}
@Override
public void enterQuestionAnswer(QLParser.QuestionAnswerContext ctx)
{
String identifier = identifiersStack.pop();
int line = getLine(ctx);
switch (ctx.type.getText())
{
case "integer":
valueMap.put(identifier, NumberPrimitive.defaultValue(line));
break;
case "string":
valueMap.put(identifier, StringPrimitive.defaultValue(line));
break;
case "boolean":
valueMap.put(identifier, BooleanPrimitive.defaultValue(line));
break;
default:
break;
}
}
@Override
public void exitVariable(QLParser.VariableContext ctx)
{
String identifier = removeQuotations(ctx.identifier.getText());
Variable v = new Variable(identifier, getLine(ctx));
expressions.push(v);
}
@Override
public void exitPrimitive(QLParser.PrimitiveContext ctx)
{
int line = getLine(ctx);
switch (ctx.value.getType())
{
case QLParser.STRING:
expressions.push(new StringPrimitive(ctx.value.getText().replace("\"", ""),line));
break;
case QLParser.NUMBER:
expressions.push(new NumberPrimitive(Integer.parseInt(ctx.value.getText()),line));
break;
case QLParser.BOOLEAN:
expressions.push(new BooleanPrimitive(Boolean.parseBoolean(ctx.value.getText()),line));
break;
}
}
@Override
public void enterInteger(QLParser.IntegerContext ctx)
{
expressions.push(new NumberPrimitive(Integer.parseInt(ctx.value.getText()),getLine(ctx)));
}
@Override
public void exitExpression(QLParser.ExpressionContext ctx) {
if (ctx.operator != null)
{
Expression expression = null;
Expression right = expressions.pop();
Expression left = expressions.pop();
int line = getLine(ctx);
switch (ctx.operator.getType())
{
case QLParser.ADDITION:
expression = new Addition(left, right, line);
break;
case QLParser.SUBTRACTION:
expression = new Subtraction(left, right, line);
break;
case QLParser.MULTIPLICATION:
expression = new Multiplication(left, right, line);
break;
case QLParser.DIVISION:
expression = new Division(left, right, line);
break;
case QLParser.AND:
expression = new And(left, right, line);
break;
case QLParser.OR:
expression = new Or(left, right, line);
break;
case QLParser.BIGGERTHANOREQUAL:
expression = new BiggerThanOrEqual(left, right, line);
break;
case QLParser.BIGGERTHAN:
expression = new BiggerThan(left, right, line);
break;
case QLParser.SMALLERTHANOREQUAL:
expression = new SmallerThanOrEqual(left, right, line);
break;
case QLParser.SMALLERTHAN:
expression = new SmallerThan(left, right, line);
break;
case QLParser.EQUALTO:
expression = new EqualTo(left, right, line);
break;
case QLParser.NOTEQUALTO:
expression = new NotEqualTo(left, right, line);
break;
}
this.expressions.push(expression);
}
}
private String removeQuotations(String string)
{
return string.replace("\"", "");
}
private int getLine(ParserRuleContext ctx)
{
return ctx.start.getLine();
}
}