l_pop:
while (!ops.isEmpty()) {
final Op xop = ops.remove(0);
switch (xop.getValue()) {
case FUNC:
new FunctionValue(expr, xop.getData(), argc, xop.getLine());
//fall thru
case LPAREN:
break l_pop; //done
case COMMA:
++argc;
break;
default:
new Operator(expr, xop.getValue(), xop.getLine());
}
}
if (endcc == EOPAREN && ops.isEmpty())
break; //done
continue; //next token
} else if (op.getValue() == LPAREN)
throw error("unexpected '('", op);
//push an operator
while (!ops.isEmpty()) {
final Op xop = ops.get(0);
final Operator.Type xtype = xop.getValue();
if (xtype.getPrecedence() > op.getValue().getPrecedence())
break;
//move ops[0] to expression since the precedence is GE
ops.remove(0);
new Operator(expr, xop.getValue(), xop.getLine());
}
ops.add(0, op);
opExpected = false;
} else {
if (opExpected)
throw error("an operator expected, not "+token, token);
if (token instanceof Id) {
final String nm = ((Id)token).getValue();
Token t = next(ctx);
if (!(t instanceof Op) || ((Op)t).getValue() != LPAREN) {
putback(t);
new FunctionValue(expr, nm, token.getLine()); //no parenthesis
} else { //function invocation
t = next(ctx);
if (t instanceof Op && ((Op)t).getValue() == RPAREN) {
//handle no arg invocation special, since it is not easy
//to tell the difference between f(a) vs. f()
new FunctionValue(expr, nm, 0, token.getLine()); //empty parenthesis
if (endcc == EOPAREN && ops.isEmpty())
break; //done
} else {
putback(t);
ops.add(0, new Op(FUNC, nm, token.getLine())); //pass name as op's data