import java.io.*;
/** parses a stream of lexed tokens into ForthBlock's */
-public class Parser extends Lexer {
+public class Parser extends Lexer implements OpCodes {
// Constructors //////////////////////////////////////////////////////
case VAR: {
if (prefix != null) { pushBackToken(); return prefix; }
ForthBlock b = new ForthBlock(curLine, sourceName);
- b.add(b.THIS);
+ b.add(OpCodes.THIS);
while(true) {
consume(NAME);
String name = string;
if (peekToken() != COMMA) break;
consume(COMMA);
}
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case IN: pushBackToken(); return prefix;
b.add(b.JF, new Integer(3));
b.add(b.EXPR, parseStatement(false));
b.add(b.JMP, new Integer(2));
- if (peekToken() != ELSE) return b.add(b.LITERAL, null);
+ if (peekToken() != ELSE) return parseSingleForthBlock(b.add(b.LITERAL, null), minPrecedence);
consume(ELSE);
b.add(b.EXPR, parseStatement(false));
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
// FIXME: ugly hack!!
b.add(b.PUT);
b.add(b.SWAP);
b.add(b.POP);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case INC: case DEC:
// prefix
ForthBlock b = (ForthBlock)parseMaximalForthBlock(null, precedence[tok]);
b.set(b.size() - 1, tok, new Boolean(true));
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
} else {
// postfix
ForthBlock b = (ForthBlock)prefix;
b.set(b.size() - 1, tok, new Boolean(false));
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case LP:
if (prefix == null) { // grouping
ForthBlock b = new ForthBlock(curLine, sourceName, ForthBlock.EXPR, parseMaximalForthBlock());
consume(RP);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
} else { // invocation
ForthBlock b = new ForthBlock(curLine, sourceName);
}
consume(RP);
b.add(b.CALL, new Integer(i));
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case BANG: case BITNOT: case INSTANCEOF: case TYPEOF: {
ForthBlock b = new ForthBlock(curLine, sourceName);
b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
b.add(tok);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case SUB:
if (prefix == null && peekToken() == NUMBER) {
getToken();
- return new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, new Double(number.doubleValue() * -1));
+ return parseSingleForthBlock(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:
b.add(b.EXPR, prefix);
b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
b.add(tok);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
// includes short-circuit logic
b.add(tok == AND ? b.JF : b.JT, new Integer(3));
b.add(b.POP);
b.add(b.EXPR, parseMaximalForthBlock(null, precedence[tok]));
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case WITH: throw new ParserException("XWT does not allow the WITH keyword");
case NUMBER:
if (prefix != null) { pushBackToken(); return prefix; }
- return new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, number);
+ return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, number), minPrecedence);
case STRING:
if (prefix != null) { pushBackToken(); return prefix; }
- return new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, string);
+ return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, string), minPrecedence);
case NULL: case TRUE: case FALSE: case NOP:
if (prefix != null) { pushBackToken(); return prefix; }
- return new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, (tok == NULL || tok == NOP) ? null : new Boolean(tok == TRUE));
+ return parseSingleForthBlock(new ForthBlock(curLine, sourceName, ForthBlock.LITERAL, (tok == NULL || tok == NOP) ? null : new Boolean(tok == TRUE)), minPrecedence);
case COMMA: pushBackToken(); return prefix;
- case THIS:
+ case Tokens.THIS:
if (prefix != null) { pushBackToken(); return prefix; }
- return new ForthBlock(curLine, sourceName, ForthBlock.THIS, null);
+ return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.THIS, null), minPrecedence);
case NAME: {
if (prefix != null) { pushBackToken(); return prefix; }
ForthBlock b = new ForthBlock(curLine, sourceName);
if (peekToken() == ASSIGN) {
consume(ASSIGN);
- b.add(ForthBlock.THIS);
+ b.add(OpCodes.THIS);
b.add(ForthBlock.LITERAL, name);
b.add(ForthBlock.EXPR, parseMaximalForthBlock(null, minPrecedence));
b.add(ForthBlock.PUT);
b.add(ForthBlock.SWAP);
b.add(ForthBlock.POP);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
} else {
- b.add(ForthBlock.THIS);
+ b.add(OpCodes.THIS);
b.add(ForthBlock.LITERAL, name);
b.add(ForthBlock.GET);
- return parseMaximalForthBlock(b, minPrecedence);
+ return parseSingleForthBlock(parseMaximalForthBlock(b, minPrecedence), minPrecedence);
}
}
b.add(b.LITERAL, target);
b.add(b.GET);
}
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
case LB: {
int i = 0;
while(true) {
ForthBlock e = parseMaximalForthBlock();
- if (e == null && peekToken() == RB) { consume(RB); return b; }
+ if (e == null && peekToken() == RB) { consume(RB); return parseSingleForthBlock(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 b; }
+ if (peekToken() == RB) { consume(RB); return parseSingleForthBlock(b, minPrecedence); }
consume(COMMA);
}
} else {
} else {
b.add(b.GET);
}
- return b;
+ return parseSingleForthBlock(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 b; }
+ if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
while(true) {
if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING");
getToken();
b.add(b.EXPR, parseMaximalForthBlock());
b.add(b.PUT);
b.add(b.POP);
- if (peekToken() == RC) { consume(RC); return b; }
+ if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
consume(COMMA);
- if (peekToken() == RC) { consume(RC); return b; }
+ if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
}
}
b.add(b.JMP, new Integer(2));
consume(COLON);
b.add(b.EXPR, parseMaximalForthBlock());
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
- case FUNCTION: {
+ case Tokens.FUNCTION: {
if (prefix != null) { pushBackToken(); return prefix; }
consume(LP);
ForthBlock b = new ForthBlock(curLine, sourceName);
int numArgs = 0;
- b.add(b.THIS);
+ b.add(OpCodes.THIS);
b.add(b.SWAP);
b.add(b.LITERAL, "arguments");
b.add(b.LITERAL, "arguments");
b.add(b.POP);
// put it to the current scope
- b.add(b.THIS);
+ b.add(OpCodes.THIS);
b.add(b.SWAP);
b.add(b.LITERAL, string);
b.add(b.SWAP);
// pop off the arguments array
b.add(b.POP);
parseStatement(true, b);
- return new ForthBlock(curLine, sourceName, b.FUNCTION, b);
+ return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.FUNCTION, b), minPrecedence);
}
case WHILE: {
// if we fall out of the end, definately continue
loop.add(CONTINUE);
- return r;
+ return parseSingleForthBlock(r, minPrecedence);
}
case SWITCH: {
if (peekToken() == RC) {
consume(RC);
r.add(BREAK);
- return r;
+ return parseSingleForthBlock(r, minPrecedence);
}
}
}
loop.add(Lexer.CONTINUE);
consume(RP);
consume(SEMI);
- return r;
+ return parseSingleForthBlock(r, minPrecedence);
}
case TRY: {
}
if (tok == FINALLY) getToken();
- return tryBlock;
+ return parseSingleForthBlock(tryBlock, minPrecedence);
}
case FOR: {
b2.add(b.PUT);
b2.add(b.EXPR, parseStatement(false));
b2.add(b.LITERAL, null);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
} else {
ForthBlock b2 = new ForthBlock(curLine, sourceName);
b3.add(b.JT, new Integer(2));
b3.add(BREAK);
parseStatement(false, b3);
- return b;
+ return parseSingleForthBlock(b, minPrecedence);
}
}