2003/05/03 08:46:05
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:59:47 +0000 (06:59 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:59:47 +0000 (06:59 +0000)
darcs-hash:20040130065947-2ba56-159081d977bb6d0139d3c4153ebd90a7d1b4b86a.gz

src/org/xwt/js/JS.java
src/org/xwt/js/Parser.java

index 1da4c54..51929af 100644 (file)
@@ -3,16 +3,18 @@
 package org.xwt.js; 
 import org.xwt.util.*; 
  
-/** all objects other than Strings and Numbers which are exposed to JS code must implement this interface */ 
+/** The public API for the JS engine */
 public interface JS { 
  
     public Object get(Object key) throws JS.Exn; 
     public Object put(Object key, Object val) throws JS.Exn; 
     public Object[] enumerateProperties(); 
     public String coerceToString() throws JS.Exn; 
+    /*
     public Num coerceToNumber() throws JS.Exn; 
+    public boolean coerceToBoolean() throws JS.Exn; 
     public Object call(Object[] args) throws JS.Exn; 
+    */
     /** if JS calls a Java method, and the Java method throws an exception, it can only be caught by JS if it is a subclass of Exn. */ 
     public static class Exn extends RuntimeException { 
        private Object js = null; 
@@ -28,10 +30,10 @@ public interface JS {
     } 
  
     /** A mutable, boxed numeric value.  These are recycled -- never duplicate references -- use duplicate() instead. */ 
+       /*
     public static class Num implements Cloneable, JS { 
         
        private Num() { } 
-        
        public boolean isDouble = false; 
        public long longVal = -1; 
        public double doubleVal = -1; 
@@ -48,6 +50,6 @@ public interface JS {
        public String coerceToString() throws JS.Exn { return isDouble ? String.valueOf(doubleVal) : String.valueOf(longVal); } 
        public Num coerceToNumber() throws JS.Exn { return duplicate(); } 
        public Object call(Object[] args) throws JS.Exn { throw new JS.Exn("attempt to apply the () operator to a Number"); } 
-        
     } 
+       */
 } 
index 0535d50..82da503 100644 (file)
@@ -46,42 +46,8 @@ public class Parser extends Lexer {
     }
 
 
-    // Useful Types /////////////////////////////////////////////////////////
-
-    /** sorta like gcc trees */
-    public static class Expr {
-
-       int code = -1;
-
-       Expr left = null;
-       Expr right = null;
-       Expr next = null;   // if this expr is part of a list
-
-       String string = null;
-       Number number = null;
-
-       public String toString() { return toString(0); }
-       public String toString(int indent) {
-           String ret = "";
-           for(int i=0; i<indent; i++) ret += " ";
-           ret += codeToString[code];
-           if (code == NUMBER) ret += " " + number;
-           else if (string != null) ret += " \"" + string + "\"";
-           ret += "\n";
-           if (left != null) ret += left.toString(indent + 2);
-           if (right != null) ret += right.toString(indent + 2);
-           if (next != null) ret += next.toString(indent);
-           return ret;
-       }
+    // Parsing Logic /////////////////////////////////////////////////////////
 
-       public Expr(String s) { code = STRING; this.string = s; }  // an identifier or label
-       public Expr(Number n) { code = NUMBER; this.number = n; }  // an identifier or label
-       public Expr(int code) { this(code, null, null); }
-       public Expr(int code, String s) { this.code = code; string = s; }
-       public Expr(int code, Expr left) { this(code, left, null); }
-       public Expr(int code, Expr left, Expr right) { this.code = code; this.left = left; this.right = right; }
-    }
-    
     /** a block is either a single statement or a list of statements surrounded by curly braces; all expressions are also statements */
     public Expr parseBlock(boolean requireBraces) throws IOException {
        Expr ret = null;
@@ -124,7 +90,7 @@ public class Parser extends Lexer {
            default:
                smt = parseMaximalExpr();
                if (smt == null) {
-                   if (head == null) throw new Error("empty statement list");
+                   if (head == null) throw new Error("empty statement list; next token is " + codeToString[peekToken()]);
                    break OUTER;
                }
                break;
@@ -145,12 +111,13 @@ public class Parser extends Lexer {
     public Expr parseMaximalExpr() throws IOException { return parseMaximalExpr(null, -1); }
     public Expr parseMaximalExpr(Expr prefix, int minPrecedence) throws IOException {
        Expr save = null;
-       do {
+       while(true) {
            save = prefix;
            if (peekToken() == -1) break;
            prefix = parseSingleExpr(prefix, minPrecedence);
+           if (save == prefix) break;
            if (prefix == null) throw new Error("parseSingleExpr_() returned null");
-       } while (save != prefix);
+       }
        return prefix;
     }
 
@@ -175,10 +142,14 @@ public class Parser extends Lexer {
        case NUMBER: if (prefix != null) { pushBackToken(); return prefix; } else return new Expr(number);
        case NULL: case TRUE: case FALSE: case NOP: if (prefix != null) { pushBackToken(); return prefix; } else return new Expr(tok);
 
+        case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH:
+       case ASSIGN_RSH: case ASSIGN_URSH: case ASSIGN_ADD: case ASSIGN_SUB: case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD:
+           return new Expr(ASSIGN, prefix, new Expr(tok - 1, prefix, parseMaximalExpr(null, precedence[ASSIGN])));
+
+        case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH:
+       case RSH: case URSH: case ADD: case SUB: case MUL: case DIV: case MOD:
        case COMMA: case ASSIGN: case GT: case GE: case OR: case AND:
-        case BITOR: case BITXOR: case BITAND: case EQ: case NE: case LT:
-        case LE: case SHEQ: case SHNE: case LSH: case RSH: case URSH:
-        case ADD: case SUB: case MUL: case DIV: case MOD: case DOT:
+       case EQ: case NE: case LT: case LE: case DOT:
            return new Expr(tok, prefix, parseMaximalExpr(null, precedence[tok]));
 
        case BITNOT: case INSTANCEOF:
@@ -197,7 +168,7 @@ public class Parser extends Lexer {
        case LP:
            if (prefix == null) {  // grouping
                Expr r = parseMaximalExpr();
-               expect(RP);
+               expect(RP); getToken();
                return r;
 
            } else {  // invocation
@@ -215,7 +186,7 @@ public class Parser extends Lexer {
        case LB:
            if (prefix != null) {
                // subscripting
-               e1 = parseSingleExpr();
+               e1 = parseMaximalExpr();
                if (getToken() != RB) throw new Error("expected a right brace");
                return new Expr(LB, prefix, e1);
            } else {
@@ -223,7 +194,8 @@ public class Parser extends Lexer {
                tok = getToken();
                while(true) {
                    if (tok == RB) return new Expr(LB, prefix, head);
-                   if (head == null) head = tail = parseSingleExpr(); else tail = tail.next = parseSingleExpr();
+                   if (head == null) head = tail = parseMaximalExpr(null, precedence[COMMA]);
+                   else tail = tail.next = parseMaximalExpr(null, precedence[COMMA]);
                    tok = getToken();
                    if (tok != COMMA && tok != RP) throw new Error("expected right bracket or comma");
                }
@@ -235,32 +207,32 @@ public class Parser extends Lexer {
            while(true) {
                if (tok == RC) return new Expr(LC, head);
                if (tok != NAME) throw new Error("expecting name");
-               Expr name = parseSingleExpr();
+               expect(NAME); getToken();
+               Expr name = new Expr(NAME, string);
                if (tok != COLON) throw new Error("expecting colon");           
-               e1 = new Expr(COLON, name, parseSingleExpr());
+               e1 = new Expr(COLON, name, parseMaximalExpr(null, precedence[COMMA]));
                if (head == null) head = tail = e1; else tail = tail.next = e1;
                tok = getToken();
                if (tok != COMMA && tok != RP) throw new Error("expected right curly or comma");
            }
            
        case HOOK:
-           e2 = parseSingleExpr();
+           e2 = parseMaximalExpr();
            if (getToken() != COLON) throw new Error("expected colon to close ?: expression");
-           e3 = parseSingleExpr();
-           e2.next = e3;
-           return new Expr(HOOK, prefix, e2);
+           e3 = parseMaximalExpr();
+           return new Expr(HOOK, prefix, new Expr(ELSE, e2, e3));
            
        case SWITCH: {
            if (prefix != null) throw new Error("didn't expect non-null prefix");
            if (getToken() != LP) throw new Error("expected left paren");
-           Expr switchExpr = parseSingleExpr();
+           Expr switchExpr = parseMaximalExpr();
            if (getToken() != RP) throw new Error("expected left paren");
            if (getToken() != LC) throw new Error("expected left brace");
            Expr firstExpr = null;
            Expr lastExpr = null;
            while(true) {
                if (getToken() != CASE) throw new Error("expected CASE");
-               Expr caseExpr = parseSingleExpr();
+               Expr caseExpr = parseMaximalExpr();
                if (getToken() != COLON) throw new Error("expected COLON");
                Expr e = new Expr(CASE, caseExpr, parseBlock(false));
                if (lastExpr == null) firstExpr = e;
@@ -297,7 +269,7 @@ public class Parser extends Lexer {
                Expr e = null;
                if (tok == ASSIGN) {
                    getToken();
-                   initVal = parseSingleExpr();
+                   initVal = parseMaximalExpr(null, precedence[COMMA]);
                    tok = peekToken();
                    e = new Expr(ASSIGN, name, initVal);
                } else {
@@ -329,14 +301,13 @@ public class Parser extends Lexer {
        case IF: case WHILE: {
            if (prefix != null) throw new Error("didn't expect non-null prefix");
            if (getToken() != LP) throw new Error("expected left paren");
-           Expr parenExpr = parseMaximalExpr(null, -1);
+           Expr parenExpr = parseMaximalExpr();
            int t;
            if ((t = getToken()) != RP) throw new Error("expected right paren, but got " + codeToString[t]);
            Expr firstBlock = parseBlock(false);
            if (tok == IF && peekToken() == ELSE) {
                getToken();
-               firstBlock.next = parseBlock(false);
-               return new Expr(tok, parenExpr, firstBlock);
+               return new Expr(tok, parenExpr, new Expr(ELSE, firstBlock, parseBlock(false)));
            }
            return new Expr(tok, parenExpr, firstBlock);
        }
@@ -366,7 +337,7 @@ public class Parser extends Lexer {
            Expr firstBlock = parseBlock(false);
            if (getToken() != WHILE) throw new Error("expecting WHILE");
            if (getToken() != LP) throw new Error("expected left paren");
-           Expr whileExpr = parseSingleExpr();
+           Expr whileExpr = parseMaximalExpr();
            if (getToken() != RP) throw new Error("expected right paren");
            if (getToken() != SEMI) throw new Error("semicolon");
            return new Expr(DO, firstBlock, whileExpr);