2004/01/13 10:27:47
[org.ibex.core.git] / src / org / xwt / js / Parser.java
index 66084e0..bffeeb4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
 package org.xwt.js;
 
 import org.xwt.util.*;
@@ -73,7 +73,7 @@ class Parser extends Lexer implements ByteCodes {
 
     /** for debugging */
     public static void main(String[] s) throws Exception {
-        JSFunction block = JSFunction.fromReader("stdin", 0, new InputStreamReader(System.in));
+        JS block = JS.fromReader("stdin", 0, new InputStreamReader(System.in));
         if (block == null) return;
         System.out.println(block);
     }
@@ -319,9 +319,9 @@ class Parser extends Lexer implements ByteCodes {
         if (g != null)
             switch(tok) {
                 case BITOR: return new Grammar.Alternative(g, parseGrammar(null));
-                case ADD:   return new Grammar.Repetition(g, 1, Integer.MAX_VALUE);
-                case MUL:   return new Grammar.Repetition(g, 0, Integer.MAX_VALUE);
-                case HOOK:  return new Grammar.Repetition(g, 0, 1);
+                case ADD:   return parseGrammar(new Grammar.Repetition(g, 1, Integer.MAX_VALUE));
+                case MUL:   return parseGrammar(new Grammar.Repetition(g, 0, Integer.MAX_VALUE));
+                case HOOK:  return parseGrammar(new Grammar.Repetition(g, 0, 1));
             }
         Grammar g0 = null;
         switch(tok) {
@@ -342,7 +342,7 @@ class Parser extends Lexer implements ByteCodes {
             default:     pushBackToken(); return g;
         }
         if (g == null) return parseGrammar(g0);
-        return new Grammar.Juxtaposition(g, g0);
+        return parseGrammar(new Grammar.Juxtaposition(g, g0));
     }
 
     /**
@@ -370,9 +370,9 @@ class Parser extends Lexer implements ByteCodes {
             Grammar g = parseGrammar(null);
             if (peekToken() == LC) {
                 g.action = new JSFunction(sourceName, parserLine, null);
-                parseBlock(g.action);
-                g.action.add(parserLine, LITERAL, null);         // in case we "fall out the bottom", return NULL              
-                g.action.add(parserLine, RETURN);
+                parseBlock((JSFunction)g.action);
+                ((JSFunction)g.action).add(parserLine, LITERAL, null);         // in case we "fall out the bottom", return NULL              
+                ((JSFunction)g.action).add(parserLine, RETURN);
             }
             b.add(parserLine, MAKE_GRAMMAR, g);
             b.add(parserLine, PUT);
@@ -726,26 +726,88 @@ class Parser extends Lexer implements ByteCodes {
             
             int catchJMPDistance = -1;
             if (peekToken() == CATCH) {
+                Vec catchEnds = new Vec();
+                boolean catchAll = false;
+                
                 catchJMPDistance = b.size - tryInsn;
-                String exceptionVar;
-                getToken();
-                consume(LP);
-                consume(NAME);
-                exceptionVar = string;
-                consume(RP);
-                b.add(parserLine, TOPSCOPE);                        // the exception is on top of the stack; put it to the chosen name
-                b.add(parserLine, SWAP);
-                b.add(parserLine, LITERAL,exceptionVar);
-                b.add(parserLine, SWAP);
-                b.add(parserLine, PUT);
-                b.add(parserLine, POP);
-                b.add(parserLine, POP);
-                parseStatement(b, null);
+                
+                while(peekToken() == CATCH && !catchAll) {
+                    String exceptionVar;
+                    getToken();
+                    consume(LP);
+                    consume(NAME);
+                    exceptionVar = string;
+                    int[] writebacks = new int[] { -1, -1, -1 };
+                    if (peekToken() != RP) {
+                        // extended XWT catch block: catch(e faultCode "foo.bar.baz")
+                        consume(NAME);
+                        String propName = string;
+                        b.add(parserLine, DUP);
+                        b.add(parserLine, LITERAL, string);
+                        b.add(parserLine, GET);
+                        b.add(parserLine, DUP);
+                        b.add(parserLine, LITERAL, null);
+                        b.add(parserLine, EQ);
+                        b.add(parserLine, JT);
+                        writebacks[0] = b.size - 1;
+                        if (peekToken() == STRING) {
+                            consume(STRING);
+                            b.add(parserLine, DUP);
+                            b.add(parserLine, LITERAL, string);
+                            b.add(parserLine, LT);
+                            b.add(parserLine, JT);
+                            writebacks[1] = b.size - 1;
+                            b.add(parserLine, DUP);
+                            b.add(parserLine, LITERAL, string + "/");   // (slash is ASCII after dot)
+                            b.add(parserLine, GE);
+                            b.add(parserLine, JT);
+                            writebacks[2] = b.size - 1;
+                        } else {
+                            consume(NUMBER);
+                            b.add(parserLine, DUP);
+                            b.add(parserLine, LITERAL, number);
+                            b.add(parserLine, EQ);
+                            b.add(parserLine, JF);
+                            writebacks[1] = b.size - 1;
+                        }
+                        b.add(parserLine, POP);  // pop the element thats on the stack from the compare
+                    } else {
+                        catchAll = true;
+                    }
+                    consume(RP);
+                    // the exception is on top of the stack; put it to the chosen name
+                    b.add(parserLine, NEWSCOPE);
+                    b.add(parserLine, TOPSCOPE);
+                    b.add(parserLine, SWAP);
+                    b.add(parserLine, LITERAL,exceptionVar);
+                    b.add(parserLine, DECLARE);
+                    b.add(parserLine, SWAP);
+                    b.add(parserLine, PUT);
+                    b.add(parserLine, POP);
+                    b.add(parserLine, POP);
+                    parseBlock(b, null);
+                    b.add(parserLine, OLDSCOPE);
+                    
+                    b.add(parserLine, JMP);
+                    catchEnds.addElement(new Integer(b.size-1));
+                    
+                    for(int i=0; i<3; i++) if (writebacks[i] != -1) b.set(writebacks[i], JS.N(b.size-writebacks[i]));
+                    b.add(parserLine, POP); // pop the element thats on the stack from the compare
+                }
+                
+                if(!catchAll)
+                    b.add(parserLine, THROW);
+                
+                for(int i=0;i<catchEnds.size();i++) {
+                    int n = ((Integer)catchEnds.elementAt(i)).intValue();
+                    b.set(n, JS.N(b.size-n));
+                }
+                
                 // pop the try and catch markers
                 b.add(parserLine,POP);
                 b.add(parserLine,POP);
             }
-            
+                        
             // jump here if no exception was thrown
             b.set(successJMPInsn, JS.N(b.size - successJMPInsn));