EvaluatorBuilder.java
package org.microspace.evaluator;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.microspace.evaluator.EvaluatorParser.ExpressionContext;
import org.microspace.evaluator.EvaluatorParser.Expression_atomContext;
import org.microspace.evaluator.EvaluatorParser.Expression_listContext;
import org.microspace.evaluator.EvaluatorParser.Expression_plus_minusContext;
import org.microspace.evaluator.EvaluatorParser.Expression_times_slashContext;
import org.microspace.evaluator.EvaluatorParser.Number_literalContext;
import org.microspace.evaluator.EvaluatorParser.Plus_minusContext;
import org.microspace.evaluator.EvaluatorParser.Times_slashContext;
/**
* Build an Evaluator.
*
* @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
* @version 2017-10-16
*/
public class EvaluatorBuilder implements EvaluatorListener {
Stack <Expression> expressionStack = new Stack<>();
final Evaluator evaluator;
public EvaluatorBuilder (String expression) {
EvaluatorLexer lexer = new EvaluatorLexer(CharStreams.fromString(expression));
CommonTokenStream tokens = new CommonTokenStream(lexer);
EvaluatorParser parser = new EvaluatorParser(tokens);
parser.setErrorHandler(new BailErrorStrategy());
ParseTree tree;
try {
tree = parser.expression();
} catch (ParseCancellationException ex) {
throw new IllegalArgumentException ("Syntax Error", ex);
}
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(this, tree);
evaluator = new Evaluator (expressionStack.peek());
}
public Evaluator getEvaluator() {
return evaluator;
}
@Override
public void visitTerminal(TerminalNode node) {
// TODO Auto-generated method stub
}
@Override
public void visitErrorNode(ErrorNode node) {
// TODO Auto-generated method stub
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void enterNumber_literal(Number_literalContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitNumber_literal(Number_literalContext ctx) {
expressionStack.push (new ExpressionLiteral(new BigDecimal(ctx.getText())));
}
@Override
public void enterExpression_atom(Expression_atomContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitExpression_atom(Expression_atomContext ctx) {
if (ctx.VARIABLE() != null) {
expressionStack.push (new ExpressionVariable(ctx.getText()));
}
}
@Override
public void enterExpression_list(Expression_listContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitExpression_list(Expression_listContext ctx) {
expressionStack.peek ().setNeedsBracket(true);
}
@Override
public void enterExpression(ExpressionContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitExpression(ExpressionContext ctx) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.microspace.evaluator.EvaluatorListener#enterTimes_slash(org.microspace.evaluator.EvaluatorParser.Times_slashContext)
*/
@Override
public void enterTimes_slash(Times_slashContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitTimes_slash(Times_slashContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void enterPlus_minus(Plus_minusContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitPlus_minus(Plus_minusContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void enterExpression_plus_minus(Expression_plus_minusContext ctx) {
// TODO Auto-generated method stub
}
@Override
public void exitExpression_plus_minus(Expression_plus_minusContext ctx) {
Stack <Expression> reverseStack = new Stack<>();
List<ExpressionAtom.Operator> plusMinusOperatorLR = new LinkedList<> ();
for (int i=0; i< ctx.plus_minus().size(); i++) {
reverseStack.push(expressionStack.pop());
if (ctx.plus_minus().get(i).PLUS() != null) {
plusMinusOperatorLR.add(ExpressionAtom.Operator.PLUS);
} else if (ctx.plus_minus().get(i).MINUS() != null){
plusMinusOperatorLR.add(ExpressionAtom.Operator.MINUS);
}
}
while (reverseStack.size() > 0) {
Expression exp1 = expressionStack.pop();
Expression exp2 = reverseStack.pop();
Expression expAtom = new ExpressionAtom(exp1, plusMinusOperatorLR.remove(0), exp2);
expressionStack.push (expAtom);
}
}
/* (non-Javadoc)
* @see org.microspace.evaluator.EvaluatorListener#enterExpression_times_slash(org.microspace.evaluator.EvaluatorParser.Expression_times_slashContext)
*/
@Override
public void enterExpression_times_slash(Expression_times_slashContext ctx) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.microspace.evaluator.EvaluatorListener#exitExpression_times_slash(org.microspace.evaluator.EvaluatorParser.Expression_times_slashContext)
*/
@Override
public void exitExpression_times_slash(Expression_times_slashContext ctx) {
// TODO Auto-generated method stub
Stack <Expression> reverseStack = new Stack<>();
List<ExpressionAtom.Operator> timesSlashOperatorLR = new LinkedList<> ();
for (int i=0; i< ctx.times_slash().size(); i++) {
reverseStack.push(expressionStack.pop());
if (ctx.times_slash().get(i).TIMES() != null) {
timesSlashOperatorLR.add(ExpressionAtom.Operator.TIMES);
} else if (ctx.times_slash().get(i).SLASH() != null){
timesSlashOperatorLR.add(ExpressionAtom.Operator.SLASH);
}
}
while (reverseStack.size() > 0) {
Expression exp1 = expressionStack.pop();
Expression exp2 = reverseStack.pop();
Expression expAtom = new ExpressionAtom(exp1, timesSlashOperatorLR.remove(0), exp2);
expressionStack.push (expAtom);
}
}
}