package edu.parser.QL.evaluator; import edu.parser.QL.nodes.expression.*; import edu.parser.QL.nodes.question.Question; import edu.parser.QL.nodes.type.Boolean; import edu.parser.QL.nodes.type.Number; import java.util.List; import java.util.Optional; /** * Created by Steven Kok on 12/03/2015. */ public class EvaluatorExpressionValidator implements ExpressionVisitor<Expression> { private final List<Question> evaluatedQuestions; public EvaluatorExpressionValidator(List<Question> evaluatedQuestions) { this.evaluatedQuestions = evaluatedQuestions; } @Override public Expression visit(Addition addition) { Number left = (Number) addition.getLeft().accept(this); Number right = (Number) addition.getRight().accept(this); return new Number(left.getNumber() + right.getNumber()); } @Override public Expression visit(And and) { Boolean left = (Boolean) and.getLeft().accept(this); Boolean right = (Boolean) and.getRight().accept(this); return new Boolean(left.isTrue() && right.isTrue()); } @Override public Expression visit(Equal equal) { Number left = (Number) equal.getLeft().accept(this); Number right = (Number) equal.getRight().accept(this); return new Boolean(left.getNumber() == right.getNumber()); } @Override public Expression visit(GreaterOrEqual greaterOrEqual) { Number left = (Number) greaterOrEqual.getLeft().accept(this); Number right = (Number) greaterOrEqual.getRight().accept(this); return new Boolean(left.getNumber() >= right.getNumber()); } @Override public Expression visit(GreaterThan greaterThan) { Number left = (Number) greaterThan.getLeft().accept(this); Number right = (Number) greaterThan.getRight().accept(this); return new Boolean(left.getNumber() > right.getNumber()); } @Override public Expression visit(LessOrEqual lessOrEqual) { Number left = (Number) lessOrEqual.getLeft().accept(this); Number right = (Number) lessOrEqual.getRight().accept(this); return new Boolean(left.getNumber() <= right.getNumber()); } @Override public Expression visit(LessThan lessThan) { Number left = (Number) lessThan.getLeft().accept(this); Number right = (Number) lessThan.getRight().accept(this); return new Boolean(left.getNumber() < right.getNumber()); } @Override public Expression visit(Multiplication multiplication) { Number left = (Number) multiplication.getLeft().accept(this); Number right = (Number) multiplication.getRight().accept(this); return new Number(left.getNumber() * right.getNumber()); } @Override public Expression visit(Not not) { Boolean result = (Boolean) not.getOperand().accept(this); return new Boolean(!result.isTrue()); } @Override public Expression visit(Or or) { Boolean left = (Boolean) or.getLeft().accept(this); Boolean right = (Boolean) or.getRight().accept(this); return new Boolean(left.isTrue() || right.isTrue()); } @Override public Expression visit(Division division) { Number left = (Number) division.getLeft().accept(this); Number right = (Number) division.getRight().accept(this); if (left.getNumber() == 0 || right.getNumber() == 0) { throw new ArithmeticException("Cannot divide by 0 for:" + division); } return new Number(left.getNumber() / right.getNumber()); } @Override public Expression visit(Boolean aBoolean) { return aBoolean; } @Override public Expression visit(Number number) { return number; } @Override public Expression visit(Expression expression) { return (Expression) expression.accept(this); } @Override public Expression visit(NotEqual notEqual) { Number left = (Number) notEqual.getLeft().accept(this); Number right = (Number) notEqual.getRight().accept(this); return new Boolean(left.getNumber() != right.getNumber()); } @Override public Expression visit(QLIdentifier qlIdentifier) { Optional<Question> foundQuestion = getQuestion(qlIdentifier); if (foundQuestion.isPresent()) { return new Boolean(isQuestionEnabled(foundQuestion.get())); } else { return new Boolean(false); // if question does not exist, expression cannot be true. } } private boolean isQuestionEnabled(Question foundQuestion) { return foundQuestion.isEnabled(); } private Optional<Question> getQuestion(QLIdentifier QLIdentifier) { return evaluatedQuestions .stream() .filter(q -> q.getQLIdentifier().equals(QLIdentifier)) .findFirst(); } }