2003/06/04 03:31:42
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:41 +0000 (07:00 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:41 +0000 (07:00 +0000)
darcs-hash:20040130070041-2ba56-7a1debddfa938ff87233d50b05d8dcc585499319.gz

src/org/xwt/js/Parser.java

index c99ff71..9af090f 100644 (file)
@@ -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; }