- case RSH: case URSH: case ADD: case MUL: case DIV: case MOD:
- case GT: case GE: case EQ: case NE: case LT: case LE: {
- 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(tok);
- return parseSingleForthBlock(b, minPrecedence);
- }
-
- // includes short-circuit logic
- case OR: case AND: {
- if (prefix == null) throw new ParserException("the " + codeToString[tok] + " token cannot start an expression");
- ForthBlock b = new ForthBlock(curLine, sourceName);
- b.add(b.LITERAL, tok == AND ? new Boolean(false) : new Boolean(true));
- 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);
- }
-
- case WITH: throw new ParserException("XWT does not allow the WITH keyword");
- case VOID: case RESERVED: throw new ParserException("reserved word that you shouldn't be using");
-
- case NUMBER:
- if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(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);
-
- 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);
-
- case COMMA: pushBackToken(); return prefix;
-
- case Tokens.THIS:
- if (prefix != null) { pushBackToken(); return prefix; }
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.THIS, null), minPrecedence);
-
- case NAME: {
- if (prefix != null) { pushBackToken(); return prefix; }
- String name = string;
- ForthBlock b = new ForthBlock(curLine, sourceName);
- if (peekToken() == ASSIGN) {
- consume(ASSIGN);
- 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 parseSingleForthBlock(b, minPrecedence);
- } else {
- b.add(OpCodes.THIS);
- b.add(ForthBlock.LITERAL, name);
- b.add(ForthBlock.GET);
- return parseSingleForthBlock(parseMaximalForthBlock(b, minPrecedence), minPrecedence);
- }
- }
-
- case DOT: {
- consume(NAME);
- String target = string;
- ForthBlock b = new ForthBlock(curLine, sourceName);
- b.add(b.EXPR, prefix);
- if (peekToken() == ASSIGN) {
- consume(ASSIGN);
- ForthBlock val = parseMaximalForthBlock();
- b.add(b.LITERAL, target);
- b.add(b.EXPR, val);
- b.add(b.PUT);
- b.add(b.SWAP);
- b.add(b.POP);
- } else {
- b.add(b.LITERAL, target);
- b.add(b.GET);
- }
- return parseSingleForthBlock(b, minPrecedence);
- }
-
- case LB: {
- ForthBlock b = new ForthBlock(curLine, sourceName);
- if (prefix == null) {
- 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); }
- 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); }
- consume(COMMA);
- }
- } else {
- b.add(b.EXPR, prefix);
- b.add(b.EXPR, parseMaximalForthBlock());
- consume(RB);
- if (peekToken() == ASSIGN) {
- consume(ASSIGN);
- b.add(b.EXPR, parseMaximalForthBlock());
- b.add(b.PUT);
- b.add(b.SWAP);
- b.add(b.POP);
- } else {
- b.add(b.GET);
- }
- return parseSingleForthBlock(b, minPrecedence);
- }
- }
-
- case LC: {
- 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); }
- 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.PUT);
- b.add(b.POP);
- if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
- consume(COMMA);
- if (peekToken() == RC) { consume(RC); return parseSingleForthBlock(b, minPrecedence); }
- }
- }
-
- case HOOK: {
- 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.JMP, new Integer(2));
- consume(COLON);
- b.add(b.EXPR, parseMaximalForthBlock());
- return parseSingleForthBlock(b, minPrecedence);
- }
-
- case Tokens.FUNCTION: {
- if (prefix != null) { pushBackToken(); return prefix; }
- consume(LP);
- ForthBlock b = new ForthBlock(curLine, sourceName);
- int numArgs = 0;
- b.add(OpCodes.THIS);
- b.add(b.SWAP);
- b.add(b.LITERAL, "arguments");
- b.add(b.LITERAL, "arguments");
- b.add(b.DECLARE);
- b.add(b.SWAP);
- b.add(b.PUT);
- b.add(b.SWAP);
- b.add(b.POP);
- if (peekToken() == RP) consume(RP);
- else while(true) {
- if (peekToken() == COMMA) {
- consume(COMMA);
- } else {
- consume(NAME);
-
- // declare the name
- b.add(b.LITERAL, string);
- b.add(b.DECLARE);
-
- // retrieve it from the arguments array
- b.add(b.LITERAL, new Integer(numArgs));
- b.add(b.GET_PRESERVE);
- b.add(b.SWAP);
- b.add(b.POP);
-
- // put it to the current scope
- b.add(OpCodes.THIS);
- b.add(b.SWAP);
- b.add(b.LITERAL, string);
- b.add(b.SWAP);
- b.add(b.PUT);
-
- // clean the stack
- b.add(b.POP);
- b.add(b.POP);
-
- if (peekToken() == RP) { consume(RP); break; }
- consume(COMMA);
- }
- numArgs++;
- }
- // pop off the arguments array
- b.add(b.POP);
- parseStatement(true, b);
- return parseSingleForthBlock(new ForthBlock(curLine, sourceName, OpCodes.FUNCTION, b), minPrecedence);
- }
-
- case WHILE: {
- if (prefix != null) { pushBackToken(); return prefix; }
- consume(LP);
- ForthBlock r = new ForthBlock(curLine, sourceName);
- ForthBlock loop = new ForthBlock(curLine, sourceName);
- r.add(loop.LOOP, loop);
- r.add(r.LITERAL, null);
-
- loop.add(loop.EXPR, parseMaximalForthBlock());
- loop.add(loop.JT, new Integer(2));
- loop.add(Lexer.BREAK);
- consume(RP);
- parseStatement(false, loop);
-
- // if we fall out of the end, definately continue
- loop.add(CONTINUE);
- return parseSingleForthBlock(r, minPrecedence);
- }
-
- case SWITCH: {
- if (prefix != null) { pushBackToken(); return prefix; }
- consume(LP);
- ForthBlock r = new ForthBlock(curLine, sourceName);
- ForthBlock loop = new ForthBlock(curLine, sourceName);
- r.add(loop.LOOP, loop);
- r.add(r.LITERAL, null);
- loop.add(loop.EXPR, parseMaximalForthBlock());
- consume(RP);
- consume(LC);
- while(true) {
- ForthBlock caseForthBlock;
- tok = getToken();
- if (tok == CASE) {
- loop.add(loop.DUP);
- loop.add(loop.EXPR, parseMaximalForthBlock());
- loop.add(EQ);
- loop.add(loop.JF, new Integer(2));
- } else if (tok != DEFAULT) throw new ParserException("expected CASE or DEFAULT");
- consume(COLON);
- ForthBlock b = new ForthBlock(curLine, sourceName);
- while(peekToken() != CASE && peekToken() != DEFAULT && peekToken() != RC) {
- if ((e1 = parseStatement(false)) == null) break;
- b.add(b.EXPR, e1);
- }
- loop.add(loop.EXPR, b);
- if (peekToken() == RC) {
- consume(RC);
- r.add(BREAK);
- return parseSingleForthBlock(r, minPrecedence);
- }
- }
- }
-
- case DO: {
- if (prefix != null) { pushBackToken(); return prefix; }
- ForthBlock r = new ForthBlock(curLine, sourceName);
- ForthBlock loop = new ForthBlock(curLine, sourceName);
- r.add(loop.LOOP, loop);
- r.add(r.LITERAL, null);
-
- parseStatement(false, loop);
- consume(WHILE);
- consume(LP);
- loop.add(loop.EXPR, parseMaximalForthBlock());
- loop.add(loop.JT, new Integer(2));
- loop.add(Lexer.BREAK);
- loop.add(Lexer.CONTINUE);
- consume(RP);
- consume(SEMI);
- return parseSingleForthBlock(r, minPrecedence);
- }
-
- case TRY: {
- // FIXME: don't just ignore this!
- // We deliberately allow you to omit braces in catch{}/finally{} if they are single statements...
- if (prefix != null) { pushBackToken(); return prefix; }
- ForthBlock tryBlock = parseStatement(true);
-
- tok = peekToken();
- if (tok == CATCH) {
- getToken();
- if (getToken() != LP) throw new ParserException("expected (");
- if (getToken() != NAME) throw new ParserException("expected name");
- if (getToken() != RP) throw new ParserException("expected )");
- tok = peekToken();
- }
- if (tok == FINALLY) getToken();
-
- return parseSingleForthBlock(tryBlock, minPrecedence);
- }
-
- case FOR: {
- if (prefix != null) { pushBackToken(); return prefix; }
- if (getToken() != LP) throw new ParserException("expected left paren");
-
- tok = getToken();
- if (tok == VAR) tok = getToken();
- String varName = string;
- boolean forIn = peekToken() == IN;
- pushBackToken(tok, varName);
-
- ForthBlock b = new ForthBlock(curLine, sourceName);
- if (forIn) {
- consume(NAME);
- consume(IN);
- b.add(b.EXPR, parseMaximalForthBlock());
- b.add(b.PUSHKEYS);
- b.add(b.LITERAL, "length");
- b.add(b.GET);
- consume(RP);
- ForthBlock b2 = new ForthBlock(curLine, sourceName);
- b.add(b.SCOPE, b2);
- b2.add(b.LITERAL, new Integer(1));
- b2.add(SUB);
- b2.add(b.DUP);
- b2.add(b.LITERAL, new Integer(0));
- b2.add(LT);
- b2.add(b.JT, new Integer(7));
- b2.add(b.GET_PRESERVE);
- b2.add(b.LITERAL, varName);
- b2.add(b.LITERAL, varName);
- b2.add(b.DECLARE);
- b2.add(b.PUT);
- b2.add(b.EXPR, parseStatement(false));
- b2.add(b.LITERAL, null);
- return parseSingleForthBlock(b, minPrecedence);
-
- } else {
- ForthBlock b2 = new ForthBlock(curLine, sourceName);
- b.add(b.SCOPE, b2);
-
- e1 = parseMaximalForthBlock();
- if (e1 == null) e1 = new ForthBlock(curLine, sourceName, b.LITERAL, null);
-
- b2.add(b.EXPR, e1);
- b2.add(b.POP);
- consume(SEMI);
- e2 = parseMaximalForthBlock();
- consume(SEMI);
- e3 = parseMaximalForthBlock();
- consume(RP);
-
- if (e2 == null) e2 = new ForthBlock(curLine, sourceName, b.LITERAL, null);
- if (e3 == null) e3 = new ForthBlock(curLine, sourceName, b.LITERAL, null);
-
- ForthBlock b3 = new ForthBlock(curLine, sourceName);
- b2.add(b.LOOP, b3);
- b2.add(b.LITERAL, null);
- b3.add(b.JT, new Integer(3));
- b3.add(b.EXPR, e3);
- b3.add(b.POP);
- b3.add(b.EXPR, e2);
- b3.add(b.JT, new Integer(2));
- b3.add(BREAK);
- parseStatement(false, b3);
- return parseSingleForthBlock(b, minPrecedence);
- }
- }
-
- default:
- pushBackToken();
- return prefix;
- }