package edu.parser.QL.evaluator;
import edu.exceptions.EvaluationException;
import edu.gui.components.store.Store;
import edu.parser.QL.QLVisitorImpl;
import edu.parser.QL.nodes.AbstractNode;
import edu.parser.QL.nodes.Form;
import edu.parser.QL.nodes.expression.Expression;
import edu.parser.QL.nodes.expression.ExpressionVisitor;
import edu.parser.QL.nodes.question.Question;
import edu.parser.QL.nodes.statement.ElseClause;
import edu.parser.QL.nodes.statement.IfStatement;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Steven Kok on 23/02/2015.
*/
public class Evaluator extends QLVisitorImpl {
private final List<Question> evaluatedQuestions = new ArrayList<>();
private final ExpressionVisitor expressionEvaluator;
private final ExpressionVisitor computedQuestionsRetriever;
public Evaluator() {
expressionEvaluator = new EvaluatorExpressionValidator(evaluatedQuestions);
computedQuestionsRetriever = new ComputedQuestionsRetriever(evaluatedQuestions);
}
public List<Question> evaluate(Form form) {
this.evaluatedQuestions.clear();
visit(form);
return evaluatedQuestions;
}
@Override
public AbstractNode visit(Form form) {
visitStatements(form.getElements());
return form;
}
@Override
public AbstractNode visit(IfStatement ifStatement) {
if (isExpressionTrue(ifStatement)) {
visitStatements(ifStatement.getStatements());
} else {
if (ifStatement.getElseClause().isPresent())
visitStatements(ifStatement.getElseClause().get().getStatements());
}
return ifStatement;
}
private boolean isExpressionTrue(IfStatement ifStatement) {
return ((edu.parser.QL.nodes.type.Boolean) ifStatement.getExpression().accept(expressionEvaluator)).isTrue();
}
@Override
public AbstractNode visit(ElseClause elseClause) {
visitStatements(elseClause.getStatements());
return elseClause;
}
@Override
public AbstractNode visit(Question question) {
if (isComputedQuestion(question)) {
Store computedValue = getComputedValue(question.getExpression().get());
question.setValue(computedValue);
}
evaluatedQuestions.add(question);
return super.visit(question);
}
private boolean isComputedQuestion(Question question) {
return question.getExpression().isPresent();
}
private Store getComputedValue(Expression expression) {
AbstractNode abstractNode = expression.accept(computedQuestionsRetriever);
if (abstractNode instanceof Store) {
return (Store) abstractNode;
} else {
throw new EvaluationException("computedQuestionsRetriever returned invalid value: " + abstractNode);
}
}
}