From: megacz Date: Fri, 30 Jan 2004 07:00:41 +0000 (+0000) Subject: 2003/06/04 03:31:42 X-Git-Tag: RC3~954 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=3b4175d23bee1a58fb66f70aa46df94cf9c166de 2003/06/04 03:31:42 darcs-hash:20040130070041-2ba56-7a1debddfa938ff87233d50b05d8dcc585499319.gz --- diff --git a/src/org/xwt/js/Parser.java b/src/org/xwt/js/Parser.java index c99ff71..9af090f 100644 --- a/src/org/xwt/js/Parser.java +++ b/src/org/xwt/js/Parser.java @@ -59,18 +59,8 @@ public class Parser extends Lexer { // Parsing Logic ///////////////////////////////////////////////////////// public void consume(int code) throws IOException { - int got = getToken(); - if (got != code) throw new ParserException("expected " + codeToString[code] + ", got " + (got == -1 ? "EOL" : codeToString[got])); - } - public void consume(int code, int code2) throws IOException { - int got = getToken(); - if (got != code && got != code2) - throw new ParserException("expected " + codeToString[code] + " or " + codeToString[code2] + - ", got " + (got == -1 ? "EOL" : codeToString[got])); - } - public void expect(int code) throws IOException { - int got = peekToken(); - if (got != code) throw new ParserException("expected " + codeToString[code] + ", got " + (got == -1 ? "EOL" : codeToString[got])); + if (getToken() != code) + throw new ParserException("expected " + codeToString[op] + ", got " + (op == -1 ? "EOL" : codeToString[op])); } /** parses the largest possible expression */ @@ -344,15 +334,14 @@ public class Parser extends Lexer { } } - // end // - case LC: { if (prefix != null) { pushBackToken(); return prefix; } ByteCode b = new ByteCode(curLine); b.add(b.OBJECT, null); if (peekToken() == RC) { consume(RC); return b; } while(true) { - consume(NAME, STRING); + if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING"); + getToken(); b.add(b.LITERAL, string); consume(COLON); b.add(b.EXPR, parseMaximalExpr()); @@ -428,73 +417,80 @@ public class Parser extends Lexer { return new ByteCode(curLine, b.FUNCTION, b); } - // Needs break // + case WHILE: { + if (prefix != null) { pushBackToken(); return prefix; } + consume(LP); + ByteCode r = new ByteCode(curLine); + ByteCode loop = new ByteCode(curLine); + r.add(loop.LOOP, loop); + r.add(r.LITERAL, null); + + loop.add(loop.EXPR, parseMaximalExpr()); + loop.add(loop.JT, new Integer(2)); + loop.add(Lexer.BREAK, NO_ARG); + consume(RP); + parseBlock(false, loop); + + // if we fall out of the end, definately continue + loop.add(CONTINUE, NO_ARG); + return r; + } case SWITCH: { if (prefix != null) { pushBackToken(); return prefix; } consume(LP); - Expr switchExpr = parseMaximalExpr(); + ByteCode r = new ByteCode(curLine); + ByteCode loop = new ByteCode(curLine); + r.add(loop.LOOP, loop); + r.add(r.LITERAL, null); + loop.add(loop.EXPR, parseMaximalExpr()); consume(RP); consume(LC); - ExprList toplevel = new ExprList(curLine, LC); while(true) { - tok = getToken(); Expr caseExpr; - if (tok == DEFAULT) caseExpr = null; - else if (tok == CASE) caseExpr = parseMaximalExpr(); - else throw new ParserException("expected CASE or DEFAULT"); + tok = getToken(); + if (tok == CASE) { + loop.add(loop.DUP, NO_ARG); + loop.add(loop.EXPR, parseMaximalExpr()); + loop.add(EQ, NO_ARG); + loop.add(loop.JF, new Integer(2)); + } else if (tok != DEFAULT) throw new ParserException("expected CASE or DEFAULT"); consume(COLON); - // FIXME: we shouldn't be creating a scope here - ExprList list = new ExprList(curLine, LC); + ByteCode b = new ByteCode(curLine); while(peekToken() != CASE && peekToken() != DEFAULT && peekToken() != RC) { if ((e1 = parseBlock(false)) == null) break; - list.add(e1); + b.add(b.EXPR, e1); + } + loop.add(loop.EXPR, b); + if (peekToken() == RC) { + consume(RC); + r.add(BREAK, NO_ARG); + return r; } - toplevel.add(new Expr(curLine, tok, caseExpr, list)); - if (peekToken() == RC) { consume(RC); return new Expr(curLine, SWITCH, switchExpr, toplevel); } } } - case TRY: { - // We deliberately allow you to omit braces in catch{}/finally{} if they are single statements... + case DO: { if (prefix != null) { pushBackToken(); return prefix; } - Expr tryBlock = parseBlock(true); - - tok = peekToken(); - ExprList list = new ExprList(curLine, TRY); - if (tok == CATCH) { - getToken(); - if (getToken() != LP) throw new ParserException("expected ("); - if (getToken() != NAME) throw new ParserException("expected name"); - Expr name = new Expr(curLine, NAME, string); - if (getToken() != RP) throw new ParserException("expected )"); - list.add(new Expr(curLine, CATCH, name, parseBlock(false))); - tok = peekToken(); - } - if (tok == FINALLY) { - getToken(); - list.add(new Expr(curLine, FINALLY, parseBlock(false))); - } - - if (list.size() == 0) throw new ParserException("try without catch or finally"); - return new Expr(curLine, TRY, tryBlock, list); - } + ByteCode r = new ByteCode(curLine); + ByteCode loop = new ByteCode(curLine); + r.add(loop.LOOP, loop); + r.add(r.LITERAL, null); - case WHILE: { - if (prefix != null) { pushBackToken(); return prefix; } + parseBlock(false, loop); + consume(WHILE); consume(LP); - Expr parenExpr = parseMaximalExpr(); - int t; - if ((t = getToken()) != RP) - throw new ParserException("expected right paren, but got " + codeToString[t]); - Expr firstBlock = parseBlock(false); - ExprList list = new ExprList(curLine, WHILE); - list.add(parenExpr); - list.add(firstBlock); - list.add(new Expr(curLine, NULL)); - return list; + loop.add(loop.EXPR, parseMaximalExpr()); + loop.add(loop.JT, new Integer(2)); + loop.add(Lexer.BREAK, NO_ARG); + loop.add(Lexer.CONTINUE, NO_ARG); + consume(RP); + consume(SEMI); + return r; } + // Needs break // + case FOR: if (prefix != null) { pushBackToken(); return prefix; } if (getToken() != LP) throw new ParserException("expected left paren"); @@ -508,11 +504,11 @@ public class Parser extends Lexer { } else { Expr initExpr = e1; if (initExpr == null) initExpr = new Expr(curLine, NULL); - expect(SEMI); getToken(); + consume(SEMI); Expr whileExpr = parseMaximalExpr(); - expect(SEMI); getToken(); + consume(SEMI); Expr incExpr = parseMaximalExpr(); - expect(RP); getToken(); + consume(RP); Expr body = parseBlock(false); Expr loop = new Expr(curLine, WHILE, whileExpr, body); ExprList list = new ExprList(curLine, LC); @@ -525,20 +521,31 @@ public class Parser extends Lexer { return list; } - case DO: { + case TRY: { + // We deliberately allow you to omit braces in catch{}/finally{} if they are single statements... if (prefix != null) { pushBackToken(); return prefix; } - ExprList list = new ExprList(curLine, DO); - Expr body = parseBlock(false); - consume(WHILE); - consume(LP); - list.add(parseMaximalExpr()); - list.add(body); - list.add(new Expr(curLine, NULL)); - consume(RP); - consume(SEMI); - return list; - } + Expr tryBlock = parseBlock(true); + tok = peekToken(); + ExprList list = new ExprList(curLine, TRY); + if (tok == CATCH) { + getToken(); + if (getToken() != LP) throw new ParserException("expected ("); + if (getToken() != NAME) throw new ParserException("expected name"); + Expr name = new Expr(curLine, NAME, string); + if (getToken() != RP) throw new ParserException("expected )"); + list.add(new Expr(curLine, CATCH, name, parseBlock(false))); + tok = peekToken(); + } + if (tok == FINALLY) { + getToken(); + list.add(new Expr(curLine, FINALLY, parseBlock(false))); + } + + if (list.size() == 0) throw new ParserException("try without catch or finally"); + return new Expr(curLine, TRY, tryBlock, list); + } + default: pushBackToken(); return prefix; @@ -588,6 +595,8 @@ public class Parser extends Lexer { public static final byte EXPR = -20; // -- transitional public static final byte SWAP = -23; // -- transitional public static final byte SCOPE = -30; // -- transitional + public static final byte LOOP = -40; // -- transitional + public static final byte DUP = -50; // -- transitional int[] op = new int[10]; Object[] arg = new Object[10]; @@ -630,7 +639,36 @@ public class Parser extends Lexer { case JMP: i += toNumber(arg[i]).intValue() - 1; break; case POP: t.pop(); break; case SWAP: t.swap(); break; + case DUP: t.push(t.peek()); break; + case Lexer.BREAK: { + // FIXME: make sure this can only appear in proper places + return Boolean.FALSE; + } + case Lexer.CONTINUE: { + // FIXME: make sure this can only appear in proper places + return Boolean.TRUE; + } + case LOOP: { + ByteCode loop = (ByteCode)arg[i]; + Parser.Thread t2 = new Parser.Thread(); + t2.push(Boolean.TRUE); + while (true) { + Boolean result; + try { + result = (Boolean)loop.eval(new JS.Scope(s), t2); + } catch (ContinueException c) { + result = Boolean.TRUE; + } catch (BreakException b) { + result = Boolean.FALSE; + } + if (result == Boolean.FALSE) break; + t2 = new Parser.Thread(); + t2.push(Boolean.FALSE); + } + break; + } + case PUT: { Object val = arg[i] == NO_ARG ? t.pop() : arg[i]; Object key = t.pop(); @@ -834,9 +872,13 @@ public class Parser extends Lexer { class Thread { public Object[] os = new Object[256]; - int size = 0; - public void push(Object o) { os[size++] = o; } - public Object pop() { return os[--size]; } + private int size = 0; + public void push(Object o) { + os[size++] = o; + } + public Object pop() { + return os[--size]; + } public Object peek() { return os[size - 1]; } public void swap() { Object temp = os[size - 1]; os[size - 1] = os[size - 2]; os[size - 2] = temp; } public int size() { return size; }