2003/06/09 06:38:36
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:58 +0000 (07:00 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:00:58 +0000 (07:00 +0000)
darcs-hash:20040130070058-2ba56-d6fca2757abec5586a8c422d91e8d7241777d070.gz

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

index 2da760d..54b8169 100644 (file)
@@ -109,7 +109,8 @@ public class ByteCodeBlock implements ByteCodes, Tokens {
                 Object key = t.pop();
                 JS target = (JS)t.peek();
                 if (target == null)
-                   throw new JS.Exn("tried to put a value to the " + key + " property on the null value");
+                   throw new JS.Exn(sourceName + ":" + line + ": tried to put a value to the " + key +
+                                    " property on the null value");
                 target.put(key, val);
                 t.push(val);
                 break;
@@ -136,7 +137,7 @@ public class ByteCodeBlock implements ByteCodes, Tokens {
                 arguments.setSize(numArgs);
                 for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(t.pop(), j);
                 JS.Function f = (JS.Function)t.pop();
-                if (f == null) throw new JS.Exn("attempted to call null");
+                if (f == null) throw new JS.Exn(sourceName + ":" + line + ": attempted to call null");
                 t.push(f.call(arguments));
                 break;
             }
@@ -214,10 +215,10 @@ public class ByteCodeBlock implements ByteCodes, Tokens {
 
     public Object doGet(final Object o, final Object v) {
         if (o == null)
-            throw new JS.Exn("tried to get property \"" + v + "\" from the null value");
+            throw new JS.Exn(sourceName + ":" + line + ": tried to get property \"" + v + "\" from the null value");
         if (o instanceof String) {
             if (v.equals("length")) return new Integer(((String)o).length());
-            else if (v.equals("substring")) return new JS.Function() {
+            else if (v.equals("substring")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         if (args.length() == 1) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue());
                         else if (args.length() == 2) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue(),
@@ -225,24 +226,24 @@ public class ByteCodeBlock implements ByteCodes, Tokens {
                         else throw new Error("String.substring() can only take one or two arguments");
                     }
                 };
-            else if (v.equals("toLowerCase")) return new JS.Function() {
+            else if (v.equals("toLowerCase")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         return ((String)o).toLowerCase();
                     } };
-            else if (v.equals("toUpperCase")) return new JS.Function() {
+            else if (v.equals("toUpperCase")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         return ((String)o).toString().toUpperCase();
                     } };
-            else if (v.equals("charAt")) return new JS.Function() {
+            else if (v.equals("charAt")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         return ((String)o).charAt(JS.toNumber(args.elementAt(0)).intValue()) + "";
                     } };
-            else if (v.equals("lastIndexOf")) return new JS.Function() {
+            else if (v.equals("lastIndexOf")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         if (args.length() != 1) return null;
                         return new Integer(((String)o).lastIndexOf(args.elementAt(0).toString()));
                     } };
-            else if (v.equals("indexOf")) return new JS.Function() {
+            else if (v.equals("indexOf")) return new JS.Function(-1, "java", null, null) {
                     public Object _call(JS.Array args) {
                         if (args.length() != 1) return null;
                         return new Integer(((String)o).indexOf(args.elementAt(0).toString()));
index b0d54e5..d3da1f1 100644 (file)
@@ -104,7 +104,7 @@ public abstract class JS {
            try {
                return vec.elementAt(i);
            } catch (ArrayIndexOutOfBoundsException e) {
-               throw new JS.Exn(e.getMessage());
+               return null;
            }
        }
        public void put(Object key, Object val) {
@@ -137,24 +137,28 @@ public abstract class JS {
        int line;
        String sourceName;
        Scope parentScope;
-       public Function() { this(-1, "unknown", null, null); }
        public Function(int line, String sourceName, ByteCodeBlock bytecodes, Scope parentScope) {
            this.sourceName = sourceName;
            this.line = line;
            this.bytecodes = bytecodes;
            this.parentScope = parentScope;
        }
+       public Function cloneWithNewParentScope(Scope s) {
+           if (this.getClass() != Function.class)
+               throw new Error("org.xwt.js.JS.Function.cloneWithNewParentScope() is not valid for subclasses");
+           return new Function(line, sourceName, bytecodes, s);
+       }
        public String getSourceName() throws JS.Exn { return sourceName; }
        public int getLine() throws JS.Exn { return line; }
        public Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException {
            if (bytecodes == null) throw new Error("tried to call() a JS.Function with bytecodes == null");
            Vec stack = new Vec();
            stack.push(args);
-           return bytecodes.eval(new FunctionScope(sourceName, parentScope), stack);
+           return bytecodes.eval(args == null ? parentScope : new FunctionScope(sourceName, parentScope), stack);
        }
        public final Object call(JS.Array args) throws JS.Exn {
            Function saved = (Function)currentFunction.get(Thread.currentThread());
-           currentFunction.put(Thread.currentThread(), this);
+           if (!getSourceName().equals("java")) currentFunction.put(Thread.currentThread(), this);
            try {
                return _call(args);
            } catch (ByteCodeBlock.ReturnException e) {  // ignore
@@ -169,29 +173,19 @@ public abstract class JS {
        }
     }
 
-    public static class Script extends Function {
-       Vector e = null;
-       private Script(Vector e) { this.e = e; }
-       public String getSourceName() throws JS.Exn { return ((ByteCodeBlock)e.elementAt(0)).getSourceName(); }
-       public Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException {
-           Scope rootScope = (Scope)args.elementAt(0);
-           for(int i=0; i<e.size(); i++) ((ByteCodeBlock)e.elementAt(i)).eval(rootScope, new Vec());
-           return null;
-       }
-       public static Script parse(Reader r, String sourceName, int line) throws IOException {
-           Parser p = new Parser(r, sourceName, line);
-           try {
-               Vector exprs = new Vector();
-               while(true) {
-                   ByteCodeBlock ret = p.parseStatement();
-                   if (ret == null) break;
-                   exprs.addElement(ret);
-               }
-               return new Script(exprs);
-           } catch (Exception e) {
-               if (Log.on) Log.log(Parser.class, e);
-               return null;
+    public static Function parse(Reader r, String sourceName, int line) throws IOException {
+       ByteCodeBlock b = new ByteCodeBlock(line, sourceName);
+       Parser p = new Parser(r, sourceName, line);
+       try {
+           while(true) {
+               int size = b.size();
+               p.parseStatement(false, b);
+               if (size == b.size()) break;
            }
+           return new Function(line, sourceName, b, null);
+       } catch (Exception e) {
+           if (Log.on) Log.log(Parser.class, e);
+           return null;
        }
     }
 
index f7039f4..4752c64 100644 (file)
@@ -25,7 +25,7 @@ class Lexer implements Tokens {
 
     /** for debugging */
     public static void main(String[] s) throws Exception {
-       Lexer l = new Lexer(new InputStreamReader(System.in));
+       Lexer l = new Lexer(new InputStreamReader(System.in), "stdin", 0);
        int tok = 0;
        while((tok = l.getToken()) != -1) System.out.println(codeToString[tok]);
     }
@@ -46,10 +46,14 @@ class Lexer implements Tokens {
     protected int col = 0;
 
     /** the name of the source code file being lexed */
-    protected String sourceName = "unknown";
+    protected String sourceName;
 
     private SmartReader in;
-    public Lexer(Reader r) throws IOException { in = new SmartReader(r); }
+    public Lexer(Reader r, String sourceName, int line) throws IOException {
+       this.sourceName = sourceName;
+       this.line = line;
+       in = new SmartReader(r);
+    }
 
 
     // Predicates ///////////////////////////////////////////////////////////////////////
index addf0f0..f594eee 100644 (file)
@@ -10,11 +10,7 @@ class Parser extends Lexer implements ByteCodes {
 
     // Constructors //////////////////////////////////////////////////////
 
-    public Parser(Reader r, String sourceName, int line) throws IOException {
-       super(r);
-       this.sourceName = sourceName;
-       this.line = line;
-    }
+    public Parser(Reader r, String sourceName, int line) throws IOException { super(r, sourceName, line); }
 
     /** for debugging */
     public static void main(String[] s) throws Exception {
@@ -81,9 +77,6 @@ class Parser extends Lexer implements ByteCodes {
        int tok = getToken();
        int curLine = line;
        if (tok == -1) return;
-       if (minPrecedence > 0 && precedence[tok] != 0)
-           if (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok]))
-               { pushBackToken(); return; }
 
        ByteCodeBlock b = appendTo;
 
@@ -111,7 +104,8 @@ class Parser extends Lexer implements ByteCodes {
        }
        case SUB: {
            consume(NUMBER);
-           continueExpr(b.add(ByteCodeBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence);
+           b.add(ByteCodeBlock.LITERAL, new Double(number.doubleValue() * -1));
+           continueExpr(b, minPrecedence);
            return;
        }
        case LP: {
@@ -536,7 +530,8 @@ class Parser extends Lexer implements ByteCodes {
            consume(LP);
 
            tok = getToken();
-           if (tok == VAR) tok = getToken();
+           boolean hadVar = false;
+           if (tok == VAR) { hadVar = true; tok = getToken(); }
            String varName = string;
            boolean forIn = peekToken() == IN;
            pushBackToken(tok, varName);
@@ -566,14 +561,13 @@ class Parser extends Lexer implements ByteCodes {
                break;
                
            } else {
+               if (hadVar) pushBackToken(VAR, null);
                ByteCodeBlock b2 = newbb(curLine);
                b.add(SCOPE, b2);
                b.add(POP);
 
                int size = b2.size();
-               startExpr(b2);
-               if (b2.size() - size > 0) b2.add(POP);
-               consume(SEMI);
+               parseStatement(false, b2);
                ByteCodeBlock e2 = startExpr();
                consume(SEMI);
                if (e2 == null) e2 = newbb(curLine).add(b.LITERAL, null);
@@ -593,7 +587,7 @@ class Parser extends Lexer implements ByteCodes {
                b3.add(JT, new Integer(2));
                b3.add(BREAK);
                parseStatement(false, b3);
-               b3.add(BREAK);
+               b3.add(CONTINUE);
                break;
            }
        }