package org.nlamah.QL.Builders;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.tree.ParseTree;
import org.nlamah.QBase.Constants.QBaseQuestionType;
import org.nlamah.QBase.Error.EnumRecognitionError;
import org.nlamah.QBase.Error.QBaseError;
import org.nlamah.QBase.Model.QBaseNode;
import org.nlamah.QBase.Tools.StringTools;
import org.nlamah.QL.QLBaseVisitor;
import org.nlamah.QL.QLParser;
import org.nlamah.QL.Model.Expression.Abstract.Expression;
import org.nlamah.QL.Model.Expression.Binary.AddExpression;
import org.nlamah.QL.Model.Expression.Binary.AndExpression;
import org.nlamah.QL.Model.Expression.Binary.DivideExpression;
import org.nlamah.QL.Model.Expression.Binary.EqualExpression;
import org.nlamah.QL.Model.Expression.Binary.GreaterThanEqualExpression;
import org.nlamah.QL.Model.Expression.Binary.GreaterThanExpression;
import org.nlamah.QL.Model.Expression.Binary.MultiplyExpression;
import org.nlamah.QL.Model.Expression.Binary.OrExpression;
import org.nlamah.QL.Model.Expression.Binary.SmallerThanEqualExpression;
import org.nlamah.QL.Model.Expression.Binary.SmallerThanExpression;
import org.nlamah.QL.Model.Expression.Binary.SubtractExpression;
import org.nlamah.QL.Model.Expression.Binary.UnEqualExpression;
import org.nlamah.QL.Model.Expression.Literal.BooleanLiteral;
import org.nlamah.QL.Model.Expression.Literal.IdentifierLiteral;
import org.nlamah.QL.Model.Expression.Literal.NumberLiteral;
import org.nlamah.QL.Model.Expression.Literal.TextLiteral;
import org.nlamah.QL.Model.Expression.Unary.MinusExpression;
import org.nlamah.QL.Model.Expression.Unary.NotExpression;
import org.nlamah.QL.Model.Expression.Unary.PlusExpression;
import org.nlamah.QL.Model.Form.ComputedQuestion;
import org.nlamah.QL.Model.Form.ConditionalBlock;
import org.nlamah.QL.Model.Form.ElseIfThenBlock;
import org.nlamah.QL.Model.Form.ElseThenBlock;
import org.nlamah.QL.Model.Form.Form;
import org.nlamah.QL.Model.Form.IfThenBlock;
import org.nlamah.QL.Model.Form.InputQuestion;
import org.nlamah.QL.Model.Form.Abstract.FormElement;
import org.nlamah.QL.Model.Form.Abstract.QLNode;
import org.nlamah.QL.Model.Form.Abstract.FormQuestion;
public class RawFormBuilder extends QLBaseVisitor<QLNode>
{
private List<QBaseError> errors;
public RawFormBuilder()
{
errors = new ArrayList<QBaseError>();
}
public Form buildForm(ParseTree tree)
{
return (Form) tree.accept(this);
}
public List<QBaseError> errors()
{
return this.errors;
}
@Override
public QLNode visitForm(QLParser.FormContext ctx)
{
String formName = ctx.Identifier().getText();
List<FormElement> formElements = new ArrayList<FormElement>();
for (QLParser.FormElementContext contextualFormElement : ctx.formElement())
{
FormElement formElement = (FormElement) contextualFormElement.accept(this);
formElements.add(formElement);
}
Form form = new Form(formName, formElements);
QBaseNode.addSourceCodePosition(form, ctx);
return form;
}
@Override
public QLNode visitComputedQuestion(QLParser.ComputedQuestionContext ctx)
{
IdentifierLiteral identifier = new IdentifierLiteral(ctx.Identifier().getText());
QBaseNode.addSourceCodePosition(identifier, ctx);
TextLiteral questionText = new TextLiteral(StringTools.removeSurroundingQuotes(ctx.Text().getText()));
QBaseNode.addSourceCodePosition(questionText, ctx);
String type = ctx.type.getText().toUpperCase();
QBaseQuestionType returnType = QBaseQuestionType.TEXT;
try
{
returnType = QBaseQuestionType.valueOf(type);
}
catch(Exception ex)
{
errors.add(new EnumRecognitionError(type, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine()));
}
Expression expression = (Expression) ctx.expression().accept(this);
FormQuestion question = null;
if (expression != null)
{
question = new ComputedQuestion(identifier, questionText, returnType, expression);
QBaseNode.addSourceCodePosition(question, ctx);
}
return question;
}
@Override
public QLNode visitBooleanQuestion(QLParser.BooleanQuestionContext ctx)
{
IdentifierLiteral identifier = new IdentifierLiteral(ctx.Identifier().getText());
QBaseNode.addSourceCodePosition(identifier, ctx);
TextLiteral questionText = new TextLiteral(StringTools.removeSurroundingQuotes(ctx.Text().getText()));
QBaseNode.addSourceCodePosition(questionText, ctx);
FormQuestion question = new InputQuestion(identifier, questionText, QBaseQuestionType.BOOLEAN);
QBaseNode.addSourceCodePosition(question, ctx);
return question;
}
@Override
public QLNode visitNumberQuestion(QLParser.NumberQuestionContext ctx)
{
IdentifierLiteral identifier = new IdentifierLiteral(ctx.Identifier().getText());
QBaseNode.addSourceCodePosition(identifier, ctx);
TextLiteral questionText = new TextLiteral(StringTools.removeSurroundingQuotes(ctx.Text().getText()));
QBaseNode.addSourceCodePosition(questionText, ctx);
FormQuestion question = new InputQuestion(identifier, questionText, QBaseQuestionType.NUMBER);
QBaseNode.addSourceCodePosition(question, ctx);
return question;
}
@Override
public QLNode visitTextQuestion(QLParser.TextQuestionContext ctx)
{
IdentifierLiteral identifier = new IdentifierLiteral(ctx.Identifier().getText());
QBaseNode.addSourceCodePosition(identifier, ctx);
TextLiteral questionText = new TextLiteral(StringTools.removeSurroundingQuotes(ctx.Text().getText()));
QBaseNode.addSourceCodePosition(questionText, ctx);
FormQuestion question = new InputQuestion(identifier, questionText, QBaseQuestionType.TEXT);
QBaseNode.addSourceCodePosition(question, ctx);
return question;
}
@Override
public QLNode visitConditionalBlock(QLParser.ConditionalBlockContext ctx)
{
IfThenBlock ifThenBlock = (IfThenBlock) ctx.ifThenBlock().accept(this);
List<ElseIfThenBlock> elseIfThenBlocks = new ArrayList<ElseIfThenBlock>();
for (QLParser.ElseIfThenBlockContext elseIfThenBlockContext : ctx.elseIfThenBlock())
{
ElseIfThenBlock elseIfThenBlock = (ElseIfThenBlock)elseIfThenBlockContext.accept(this);
elseIfThenBlocks.add(elseIfThenBlock);
}
ElseThenBlock elseThenBlock = null;
if (ctx.elseThenBlock() != null)
{
elseThenBlock = (ElseThenBlock) ctx.elseThenBlock().accept(this);
}
ConditionalBlock conditionalBlock = new ConditionalBlock(ifThenBlock, elseIfThenBlocks, elseThenBlock);
QBaseNode.addSourceCodePosition(conditionalBlock, ctx);
return conditionalBlock;
}
@Override
public QLNode visitIfThenBlock(QLParser.IfThenBlockContext ctx)
{
Expression logicalExpression = (Expression) ctx.expression().accept(this);
List<FormElement> formElements = new ArrayList<FormElement>();
for (QLParser.FormElementContext contextualFormElement : ctx.formElement())
{
FormElement formElement = (FormElement) contextualFormElement.accept(this);
formElements.add(formElement);
}
IfThenBlock ifThenBlock = new IfThenBlock(logicalExpression, formElements);
QBaseNode.addSourceCodePosition(ifThenBlock, ctx);
return ifThenBlock;
}
@Override
public QLNode visitElseIfThenBlock(QLParser.ElseIfThenBlockContext ctx)
{
Expression expression = (Expression) ctx.expression().accept(this);
List<FormElement> formElements = new ArrayList<FormElement>();
for (QLParser.FormElementContext contextualFormElement : ctx.formElement())
{
FormElement formElement = (FormElement) contextualFormElement.accept(this);
formElements.add(formElement);
}
ElseIfThenBlock elseIfThenBlock = new ElseIfThenBlock(expression, formElements);
QBaseNode.addSourceCodePosition(elseIfThenBlock, ctx);
return elseIfThenBlock;
}
@Override
public QLNode visitElseThenBlock(QLParser.ElseThenBlockContext ctx)
{
List<FormElement> formElements = new ArrayList<FormElement>();
for (QLParser.FormElementContext contextualFormElement : ctx.formElement())
{
FormElement formElement = (FormElement) contextualFormElement.accept(this);
formElements.add(formElement);
}
ElseThenBlock elseThenBlock = new ElseThenBlock(formElements);
QBaseNode.addSourceCodePosition(elseThenBlock, ctx);
return elseThenBlock;
}
@Override
public QLNode visitOrExpression(QLParser.OrExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
OrExpression expression = new OrExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
@Override
public QLNode visitMultiplyExpression(QLParser.MultiplyExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
if (ctx.MultiplyOperator().getText().equals("*"))
{
MultiplyExpression expression = new MultiplyExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.MultiplyOperator().getText().equals("/"))
{
DivideExpression expression = new DivideExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
return null;
}
@Override
public QLNode visitAndExpression(QLParser.AndExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
AndExpression expression = new AndExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
@Override
public QLNode visitParenthesesExpression(QLParser.ParenthesesExpressionContext ctx)
{
return (Expression)ctx.expression().accept(this);
}
@Override
public QLNode visitComparisonExpression(QLParser.ComparisonExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
if (ctx.ComparisonOperator().getText().equals("<"))
{
SmallerThanExpression expression = new SmallerThanExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.ComparisonOperator().getText().equals("<="))
{
SmallerThanEqualExpression expression = new SmallerThanEqualExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.ComparisonOperator().getText().equals(">"))
{
GreaterThanExpression expression = new GreaterThanExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.ComparisonOperator().getText().equals(">="))
{
GreaterThanEqualExpression expression = new GreaterThanEqualExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
return null;
}
@Override
public QLNode visitAdditionExpression(QLParser.AdditionExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
if (ctx.op.getText().equals("+"))
{
AddExpression expression = new AddExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.op.getText().equals("-"))
{
SubtractExpression expression = new SubtractExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
return null;
}
@Override
public QLNode visitTextLiteral(QLParser.TextLiteralContext ctx)
{
TextLiteral literal = new TextLiteral(StringTools.removeSurroundingQuotes(ctx.Text().getText()));
QBaseNode.addSourceCodePosition(literal, ctx);
return literal;
}
@Override
public QLNode visitIdentifierLiteral(QLParser.IdentifierLiteralContext ctx)
{
IdentifierLiteral identifier = new IdentifierLiteral(ctx.Identifier().getText());
QBaseNode.addSourceCodePosition(identifier, ctx);
return identifier;
}
@Override
public QLNode visitEqualityExpression(QLParser.EqualityExpressionContext ctx)
{
Expression leftHandExpression = (Expression) ctx.expression(0).accept(this);
Expression rightHandExpression = (Expression) ctx.expression(1).accept(this);
if (ctx.EqualityOperator().getText().equals("=="))
{
EqualExpression expression = new EqualExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
if (ctx.EqualityOperator().getText().equals("!="))
{
UnEqualExpression expression = new UnEqualExpression(leftHandExpression, rightHandExpression);
QBaseNode.addSourceCodePosition(expression, ctx);
return expression;
}
return null;
}
@Override
public QLNode visitNumberLiteral(QLParser.NumberLiteralContext ctx)
{
NumberLiteral literal = new NumberLiteral(Integer.parseInt(ctx.Number().getText()));
QBaseNode.addSourceCodePosition(literal, ctx);
return literal;
}
@Override
public QLNode visitUnaryExpression(QLParser.UnaryExpressionContext ctx)
{
Expression expression = (Expression) ctx.expression().accept(this);
if (ctx.operator.getText().equals("!"))
{
NotExpression notExpression = new NotExpression(expression);
QBaseNode.addSourceCodePosition(notExpression, ctx);
return notExpression;
}
if (ctx.operator.getText().equals("-"))
{
MinusExpression minusExpression = new MinusExpression(expression);
QBaseNode.addSourceCodePosition(minusExpression, ctx);
return minusExpression;
}
if (ctx.operator.getText().equals("+"))
{
PlusExpression plusExpression = new PlusExpression(expression);
QBaseNode.addSourceCodePosition(plusExpression, ctx);
return plusExpression;
}
return null;
}
@Override
public QLNode visitBooleanLiteral(QLParser.BooleanLiteralContext ctx)
{
BooleanLiteral literal = new BooleanLiteral(ctx.Boolean().getText().equals("yes") ? true : false);
QBaseNode.addSourceCodePosition(literal, ctx);
return literal;
}
}