changes made after tupshins reconstruction
[org.ibex.core.git] / src / org / xwt / js / Parser.java
index ee04b7e..1914cc7 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);
     }
@@ -97,7 +97,10 @@ class Parser extends Lexer implements ByteCodes {
             isRightAssociative[ASSIGN_SUB] =
             isRightAssociative[ASSIGN_MUL] =
             isRightAssociative[ASSIGN_DIV] =
-            isRightAssociative[ASSIGN_MOD] = true;
+            isRightAssociative[ASSIGN_MOD] =
+            isRightAssociative[ADD_TRAP] =
+            isRightAssociative[DEL_TRAP] =
+            true;
 
         precedence[COMMA] = 1;
         // 2 is intentionally left unassigned. we use minPrecedence==2 for comma separated lists
@@ -112,6 +115,8 @@ class Parser extends Lexer implements ByteCodes {
             precedence[ASSIGN_SUB] =
             precedence[ASSIGN_MUL] =
             precedence[ASSIGN_DIV] =
+            precedence[ADD_TRAP] =
+            precedence[DEL_TRAP] =
             precedence[ASSIGN_MOD] = 3;
         precedence[HOOK] = 4;
         precedence[OR] = 5;
@@ -370,9 +375,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);
@@ -380,25 +385,22 @@ class Parser extends Lexer implements ByteCodes {
         }
 
         case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH: case ASSIGN_RSH: case ASSIGN_URSH:
-        case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: {
-            if (tok != ASSIGN_ADD && tok != ASSIGN_SUB) b.add(parserLine, GET_PRESERVE);
+        case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: case ADD_TRAP: case DEL_TRAP: {
+            if (tok != ADD_TRAP && tok != DEL_TRAP) b.add(parserLine, GET_PRESERVE);
             
             startExpr(b,  precedence[tok]);
             
             int size = b.size;
-            if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) {
-                b.add(parserLine, tok);
-                b.add(parserLine, GET);
+            
+            if (tok != ADD_TRAP && tok != DEL_TRAP) {
+                // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc) 
+                b.add(parserLine, tok - 1, tok-1==ADD ? JS.N(2) : null);
+                b.add(parserLine, PUT);
                 b.add(parserLine, SWAP);
+                b.add(parserLine, POP);
+            } else {
+                b.add(parserLine, tok);
             }
-            
-            // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc) 
-            b.add(parserLine, tok - 1, tok-1==ADD ? JS.N(2) : null);
-            b.add(parserLine, PUT);
-            b.add(parserLine, SWAP);
-            b.add(parserLine, POP);
-            
-            if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) b.set(size, tok, JS.N(b.size - size));
             break;
         }
         case INC: case DEC: { // postfix
@@ -726,26 +728,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));