package querying.parsing.query;
/**
* Evaluate given term (if it is valuable, i.e, it has no variables)
*
*/
public class TermEvaluator {
QASTarithmeticTerm aterm;
/**
* Constructor
*
* @param aterm
* term to be stored in class field
*/
public TermEvaluator(QASTarithmeticTerm aterm) {
this.aterm = aterm;
}
/**
* @return true if term stored in aterm field is valuable
*/
public boolean isEvaluable() {
return isEvaluable(aterm);
}
/**
* Find value of the term stored in aterm field.
*
* @return value of term
* @throws ParseException
* if aterm contains variables or division by zero occurs
*/
public long evaluate() {
return evaluate((QASTadditiveArithmeticTerm) aterm.jjtGetChild(0));
}
/**
* Find value of the term
*
* @param aterm
* additive arithmetic term
* @return value of term
* @throws ParseException
* if term contains variables or division by zero occurs
*/
private long evaluate(QASTadditiveArithmeticTerm aterm)
{
long result = 0;
for (int i = 0; i < aterm.jjtGetNumChildren(); i++) {
if (aterm.image.charAt(i) == '+') {
result += evaluate((QASTmultiplicativeArithmeticTerm) aterm
.jjtGetChild(i));
} else {
result -= evaluate((QASTmultiplicativeArithmeticTerm) aterm
.jjtGetChild(i));
}
}
return result;
}
/**
* Find value of the term
*
* @param mterm
* multiplicative arithmetic term
* @return value of term
* @throws ParseException
* if term contains variables or division by zero occurs
*/
private long evaluate(QASTmultiplicativeArithmeticTerm mterm) {
long value = evaluate((QASTatomicArithmeticTerm) mterm.jjtGetChild(0));
for (int i = 1; i < mterm.jjtGetNumChildren(); i++) {
QASTatomicArithmeticTerm child = (QASTatomicArithmeticTerm) mterm
.jjtGetChild(i);
switch (mterm.image.charAt(i - 1)) {
case '*':
value *= evaluate((QASTatomicArithmeticTerm) mterm
.jjtGetChild(i));
break;
case '/':
long div = evaluate(child);
if (div == 0)
throw new IllegalArgumentException("Division By Zero");
value /= div;
break;
case '%':
long remdiv = evaluate(child);
if (remdiv == 0)
throw new IllegalArgumentException("Division By Zero");
value %= remdiv;
break;
}
}
return value;
}
/**
* Find value of the term
*
* @param atterm
* atomic arithmetic term
* @return value of term
* @throws ParseException
* if term contains variables or division by zero occurs
*/
private long evaluate(QASTatomicArithmeticTerm atterm) {
if (!atterm.image.matches("(-?[1-9][0-9]*)|0")
&& !atterm.image.startsWith("(")) {
throw new IllegalArgumentException("term "+atterm.toString()
+ " contains variables and not evaluable");
} else if (atterm.image.startsWith("(")) {
TermEvaluator te = new TermEvaluator(
(QASTarithmeticTerm) atterm.jjtGetChild(0));
return te.evaluate();
} else
return Integer.parseInt(atterm.image);
}
/**
* Check if given term is valuable
*
* @param n
* term represented in AST node
* @return true if term is valuable (has no variables)
*/
private boolean isEvaluable(SimpleNode n) {
if (n.id == QueryParserTreeConstants.JJTATOMICARITHMETICTERM) {
if (n.jjtGetNumChildren() > 0
&& ((SimpleNode) n.jjtGetChild(0)).id == QueryParserTreeConstants.JJTVAR) {
return false;
}
}
boolean result = true;
for (int i = 0; i < n.jjtGetNumChildren(); i++) {
if (!isEvaluable((SimpleNode) n.jjtGetChild(i))) {
result = false;
}
}
return result;
}
}