}
/** parses the largest possible expression */
- public ForthBlock parseMaximalForthBlock() throws IOException { return parseMaximalForthBlock(null, -1); }
- public ForthBlock parseMaximalForthBlock(ForthBlock prefix, int minPrecedence) throws IOException {
- while(true) {
- if (peekToken() == -1) break;
- ForthBlock save = prefix;
- prefix = parseSingleForthBlock(prefix, minPrecedence);
- if (save == prefix) break;
- if (prefix == null) throw new ParserException("parseSingleForthBlock() returned null");
- }
- return prefix;
- }
-
- public ForthBlock parseSingleForthBlock(ForthBlock prefix, int minPrecedence) throws IOException {
+ public ForthBlock parseExpr() throws IOException { return parseExpr(null, -1); }
+ public ForthBlock parseExpr(ForthBlock prefix, int minPrecedence) throws IOException {
ForthBlock e1 = null, e2 = null, e3 = null, head = null, tail = null, ret = null;
int tok = peekToken();
if (peekToken() == ASSIGN) {
b.add(b.LITERAL, name);
consume(ASSIGN);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
b.add(b.PUT);
b.add(b.POP);
}
if (peekToken() != COMMA) break;
consume(COMMA);
}
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case IN: pushBackToken(); return prefix;
if (prefix != null) { pushBackToken(); return prefix; }
ForthBlock b = new ForthBlock(curLine, sourceName);
consume(LP);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
consume(RP);
b.add(b.JF, new Integer(3));
b.add(b.EXPR, parseStatement(false));
b.add(b.JMP, new Integer(2));
- if (peekToken() != ELSE) return parseSingleForthBlock(b.add(b.LITERAL, null), minPrecedence);
+ if (peekToken() != ELSE) return parseExpr(b.add(b.LITERAL, null), minPrecedence);
consume(ELSE);
b.add(b.EXPR, parseStatement(false));
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
// FIXME: ugly hack!!
{
ForthBlock b = (ForthBlock)prefix;
b.set(b.size() - 1, b.GET_PRESERVE, new Boolean(true));
- b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
+ b.add(b.EXPR, parseExpr(null, precedence[tok]));
b.add(tok);
b.add(b.PUT);
b.add(b.SWAP);
b.add(b.POP);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case INC: case DEC:
if (prefix == null) {
// prefix
- ForthBlock b = (ForthBlock)parseMaximalForthBlock(null, precedence[tok]);
+ ForthBlock b = (ForthBlock)parseExpr(null, precedence[tok]);
b.set(b.size() - 1, tok, new Boolean(true));
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
} else {
// postfix
ForthBlock b = (ForthBlock)prefix;
b.set(b.size() - 1, tok, new Boolean(false));
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case LP:
if (prefix == null) { // grouping
- ForthBlock b = new ForthBlock(curLine, sourceName, ForthBlock.EXPR, parseMaximalForthBlock());
+ ForthBlock b = new ForthBlock(curLine, sourceName, ForthBlock.EXPR, parseExpr());
consume(RP);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
} else { // invocation
ForthBlock b = new ForthBlock(curLine, sourceName);
int i = 0;
b.add(b.EXPR, prefix);
while(peekToken() != RP) {
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
i++;
if (peekToken() == RP) break;
consume(COMMA);
}
consume(RP);
b.add(b.CALL, new Integer(i));
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case BANG: case BITNOT: case INSTANCEOF: case TYPEOF: {
if (prefix != null) { pushBackToken(); return prefix; }
ForthBlock b = new ForthBlock(curLine, sourceName);
- b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
+ b.add(b.EXPR, parseExpr(null, precedence[tok]));
b.add(tok);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case SUB:
if (prefix == null && peekToken() == NUMBER) {
getToken();
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence);
} // else fall through
case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH:
case RSH: case URSH: case ADD: case MUL: case DIV: case MOD:
if (prefix == null) throw new ParserException("the " + codeToString[tok] + " token cannot start an expression");
ForthBlock b = new ForthBlock(curLine, sourceName);
b.add(b.EXPR, prefix);
- b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
+ b.add(b.EXPR, parseExpr(null, precedence[tok]));
b.add(tok);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
// includes short-circuit logic
b.add(b.EXPR, prefix);
b.add(tok == AND ? b.JF : b.JT, new Integer(3));
b.add(b.POP);
- b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
- return parseSingleForthBlock(b, minPrecedence);
+ b.add(b.EXPR, parseExpr(null, precedence[tok]));
+ return parseExpr(b, minPrecedence);
}
case WITH: throw new ParserException("XWT does not allow the WITH keyword");
case NUMBER:
if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, number), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, number), minPrecedence);
case STRING:
if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, string), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, string), minPrecedence);
case NULL: case TRUE: case FALSE: case NOP:
if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, (tok == NULL || tok == NOP) ? null : new Boolean(tok == TRUE)), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, (tok == NULL || tok == NOP) ? null : new Boolean(tok == TRUE)), minPrecedence);
case COMMA: pushBackToken(); return prefix;
case Tokens.THIS:
if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.THIS, null), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, OpCodes.THIS, null), minPrecedence);
case NAME: {
if (prefix != null) { pushBackToken(); return prefix; }
consume(ASSIGN);
b.add(OpCodes.THIS);
b.add(ForthBlock.LITERAL, name);
- b.add(ForthBlock.EXPR, parseMaximalForthBlock(null, minPrecedence));
+ b.add(ForthBlock.EXPR, parseExpr(null, minPrecedence));
b.add(ForthBlock.PUT);
b.add(ForthBlock.SWAP);
b.add(ForthBlock.POP);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
} else {
b.add(OpCodes.THIS);
b.add(ForthBlock.LITERAL, name);
b.add(ForthBlock.GET);
- return parseSingleForthBlock(parseMaximalForthBlock(b, minPrecedence), minPrecedence);
+ return parseExpr(parseExpr(b, minPrecedence), minPrecedence);
}
}
b.add(b.EXPR, prefix);
if (peekToken() == ASSIGN) {
consume(ASSIGN);
- ForthBlock val = parseMaximalForthBlock();
+ ForthBlock val = parseExpr();
b.add(b.LITERAL, target);
b.add(b.EXPR, val);
b.add(b.PUT);
b.add(b.LITERAL, target);
b.add(b.GET);
}
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
case LB: {
b.add(b.ARRAY, new Integer(0));
int i = 0;
while(true) {
- ForthBlock e = parseMaximalForthBlock();
- if (e == null && peekToken() == RB) { consume(RB); return parseSingleForthBlock(b, minPrecedence); }
+ ForthBlock e = parseExpr();
+ if (e == null && peekToken() == RB) { consume(RB); return parseExpr(b, minPrecedence); }
b.add(b.LITERAL, new Integer(i++));
if (e == null) b.add(b.LITERAL, null);
else b.add(b.EXPR, e);
b.add(b.PUT);
b.add(b.POP);
- if (peekToken() == RB) { consume(RB); return parseSingleForthBlock(b, minPrecedence); }
+ if (peekToken() == RB) { consume(RB); return parseExpr(b, minPrecedence); }
consume(COMMA);
}
} else {
b.add(b.EXPR, prefix);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
consume(RB);
if (peekToken() == ASSIGN) {
consume(ASSIGN);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
b.add(b.PUT);
b.add(b.SWAP);
b.add(b.POP);
} else {
b.add(b.GET);
}
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
}
if (prefix != null) { pushBackToken(); return prefix; }
ForthBlock b = new ForthBlock(curLine, sourceName);
b.add(b.OBJECT, null);
- if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
+ if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); }
while(true) {
if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING");
getToken();
b.add(b.LITERAL, string);
consume(COLON);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
b.add(b.PUT);
b.add(b.POP);
- if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
+ if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); }
consume(COMMA);
- if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
+ if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); }
}
}
ForthBlock b = new ForthBlock(curLine, sourceName);
b.add(b.EXPR, prefix);
b.add(b.JF, new Integer(3));
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
b.add(b.JMP, new Integer(2));
consume(COLON);
- b.add(b.EXPR, parseMaximalForthBlock());
- return parseSingleForthBlock(b, minPrecedence);
+ b.add(b.EXPR, parseExpr());
+ return parseExpr(b, minPrecedence);
}
case Tokens.FUNCTION: {
// pop off the arguments array
b.add(b.POP);
parseStatement(true, b);
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.FUNCTION, b), minPrecedence);
+ return parseExpr(new ForthBlock(curLine, sourceName, OpCodes.FUNCTION, b), minPrecedence);
}
case WHILE: {
r.add(loop.LOOP, loop);
r.add(r.LITERAL, null);
- loop.add(loop.EXPR, parseMaximalForthBlock());
+ loop.add(loop.EXPR, parseExpr());
loop.add(loop.JT, new Integer(2));
loop.add(Lexer.BREAK);
consume(RP);
// if we fall out of the end, definately continue
loop.add(CONTINUE);
- return parseSingleForthBlock(r, minPrecedence);
+ return parseExpr(r, minPrecedence);
}
case SWITCH: {
ForthBlock loop = new ForthBlock(curLine, sourceName);
r.add(loop.LOOP, loop);
r.add(r.LITERAL, null);
- loop.add(loop.EXPR, parseMaximalForthBlock());
+ loop.add(loop.EXPR, parseExpr());
consume(RP);
consume(LC);
while(true) {
tok = getToken();
if (tok == CASE) {
loop.add(loop.DUP);
- loop.add(loop.EXPR, parseMaximalForthBlock());
+ loop.add(loop.EXPR, parseExpr());
loop.add(EQ);
loop.add(loop.JF, new Integer(2));
} else if (tok != DEFAULT) throw new ParserException("expected CASE or DEFAULT");
if (peekToken() == RC) {
consume(RC);
r.add(BREAK);
- return parseSingleForthBlock(r, minPrecedence);
+ return parseExpr(r, minPrecedence);
}
}
}
parseStatement(false, loop);
consume(WHILE);
consume(LP);
- loop.add(loop.EXPR, parseMaximalForthBlock());
+ loop.add(loop.EXPR, parseExpr());
loop.add(loop.JT, new Integer(2));
loop.add(Lexer.BREAK);
loop.add(Lexer.CONTINUE);
consume(RP);
consume(SEMI);
- return parseSingleForthBlock(r, minPrecedence);
+ return parseExpr(r, minPrecedence);
}
case TRY: {
}
if (tok == FINALLY) getToken();
- return parseSingleForthBlock(tryBlock, minPrecedence);
+ return parseExpr(tryBlock, minPrecedence);
}
case FOR: {
if (forIn) {
consume(NAME);
consume(IN);
- b.add(b.EXPR, parseMaximalForthBlock());
+ b.add(b.EXPR, parseExpr());
b.add(b.PUSHKEYS);
b.add(b.LITERAL, "length");
b.add(b.GET);
b2.add(b.PUT);
b2.add(b.EXPR, parseStatement(false));
b2.add(b.LITERAL, null);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
} else {
ForthBlock b2 = new ForthBlock(curLine, sourceName);
b.add(b.SCOPE, b2);
- e1 = parseMaximalForthBlock();
+ e1 = parseExpr();
if (e1 == null) e1 = new ForthBlock(curLine, sourceName, b.LITERAL, null);
b2.add(b.EXPR, e1);
b2.add(b.POP);
consume(SEMI);
- e2 = parseMaximalForthBlock();
+ e2 = parseExpr();
consume(SEMI);
- e3 = parseMaximalForthBlock();
+ e3 = parseExpr();
consume(RP);
if (e2 == null) e2 = new ForthBlock(curLine, sourceName, b.LITERAL, null);
b3.add(b.JT, new Integer(2));
b3.add(BREAK);
parseStatement(false, b3);
- return parseSingleForthBlock(b, minPrecedence);
+ return parseExpr(b, minPrecedence);
}
}
getToken();
ForthBlock r = new ForthBlock(curLine, sourceName);
if (tok == RETURN && peekToken() == SEMI) r.add(b.LITERAL, null);
- else r.add(b.EXPR, parseMaximalForthBlock());
+ else r.add(b.EXPR, parseExpr());
consume(SEMI);
r.add(tok);
smt = r;
case -1:
default:
- smt = parseMaximalForthBlock();
+ smt = parseExpr();
if (smt == null) return block.size() == 0 ? null : ret;
if (peekToken() == SEMI) getToken();
break;