import org.xwt.util.*;
import java.io.*;
-/**
- * A block of JavaScript bytecode.
- *
- * The JavaScript ByteCode runs on a very simple stack machine.
- */
+/** A block of JavaScript bytecode run on a very simple stack machine. */
class ByteCodeBlock implements ByteCodes, Tokens {
- int line;
- String sourceName;
- int[] op = new int[10];
- Object[] arg = new Object[10];
- int size = 0;
+ // FIXME: this should be line-by-line
+ private int line;
+ private String sourceName;
+
+ /** the instructions */
+ private int[] op = new int[10];
+
+ /** the arguments to the instructions */
+ private Object[] arg = new Object[10];
+
+ /** the number of instruction/argument pairs */
+ private int size = 0;
public ByteCodeBlock(int line, String sourceName) { this.line = line; this.sourceName = sourceName; }
- public ByteCodeBlock(int line, String sourceName, int op_, Object arg_) { this(line, sourceName); add(op_, arg_); }
+ public String getSourceName() { return sourceName; }
public int size() { return size; }
public void set(int pos, int op_, Object arg_) { op[pos] = op_; arg[pos] = arg_; }
+ public void set(int pos, Object arg_) { arg[pos] = arg_; }
public void paste(ByteCodeBlock other) { for(int i=0; i<other.size; i++) add(other.op[i], other.arg[i]); }
public ByteCodeBlock add(int op_) { return add(op_, null); }
public ByteCodeBlock add(int op_, Object arg_) {
case RETURN: throw new ReturnException(t.pop());
case THROW: throw new JS.Exn(t.pop());
case TRY: break;
- case INSTANCEOF: break;
case TYPEOF: break;
- case BITNOT: t.push(new Long(~JS.toLong(t.pop()))); break;
- case BANG: t.push(new Boolean(!JS.toBoolean(t.pop()))); break;
case BREAK: return Boolean.FALSE;
case CONTINUE: return Boolean.TRUE;
+ case BITNOT: t.push(new Long(~JS.toLong(t.pop()))); break;
+ case BANG: t.push(new Boolean(!JS.toBoolean(t.pop()))); break;
case PUSHKEYS: {
Object o = t.peek();
/**
* Constants for the various JavaScript ByteCode operations.
*
- * Each instruction is an opcode and an optional literal literal; the
- * arithmetic Tokens are also valid. They are: BITOR, BITXOR, BITAND,
- * ADD, INC, DEC, SUB, MUL, DIV, MOD, LSH, RSH, URSH, LT, LE, GT, GE,
- * EQ, NE
+ * Each instruction is an opcode and an optional literal literal;
+ * some Tokens are also valid; see Tokens.java
*/
interface ByteCodes {
/** push the literal onto the stack */
- public static final byte LITERAL = -2;
+ public static final byte LITERAL = -2;
/** push a new array onto the stack with length equal to the literal */
public static final byte ARRAY = -3;
public static final byte GET = -8;
/** push stack[-1].get(stack[top]) */
- public static final byte GET_PRESERVE = -80;
+ public static final byte GET_PRESERVE = -9;
/** pop two elements off the stack; stack[-2].put(stack[-1], stack[top]); push stack[top] */
- public static final byte PUT = -9;
+ public static final byte PUT = -10;
/** literal is a relative address; pop stacktop and jump if the value is true */
- public static final byte JT = -13;
+ public static final byte JT = -11;
/** literal is a relative address; pop stacktop and jump if the value is false */
- public static final byte JF = -21;
+ public static final byte JF = -12;
/** literal is a relative address; jump to it */
- public static final byte JMP = -22;
+ public static final byte JMP = -13;
/** discard the top stack element */
static public final byte POP = -14;
public static final byte CALL = -15;
/** pop an element; push a JS.Array containing the keys of the popped element */
- public static final byte PUSHKEYS = -19;
+ public static final byte PUSHKEYS = -16;
/** swap the top two elements on the stack */
- public static final byte SWAP = -23;
+ public static final byte SWAP = -17;
/** execute the ForthBlock pointed to by the literal in a fresh scope with parentScope==THIS */
- public static final byte SCOPE = -30;
+ public static final byte SCOPE = -18;
/** push a copy of the top stack element */
- public static final byte DUP = -50;
+ public static final byte DUP = -19;
/** declare a label */
- public static final byte LABEL = -60;
+ public static final byte LABEL = -20;
/** execute the ForthBlock pointed to by the literal until BREAK encountered; push TRUE onto the stack for the first iteration
* and FALSE for all subsequent iterations */
- public static final byte LOOP = -40;
+ public static final byte LOOP = -21;
}
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)).sourceName; }
+ 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);
package org.xwt.js;
import java.io.*;
+/** Lexes a stream of characters into a stream of Tokens */
class Lexer implements Tokens {
+ /** for debugging */
public static void main(String[] s) throws Exception {
Lexer l = new Lexer(new InputStreamReader(System.in));
int tok = 0;
- while((tok = l.getToken()) != -1)
- System.out.println(codeToString[tok]);
+ while((tok = l.getToken()) != -1) System.out.println(codeToString[tok]);
}
- public int op;
- public Number number = null;
- public String string = null;
+ /** the token that was just parsed */
+ protected int op;
- public int line = 0;
- public int col = 0;
+ /** if the token just parsed was a NUMBER, this is the numeric value */
+ protected Number number = null;
- private SmartReader in;
- public String sourceName = "unknown";
+ /** if the token just parsed was a NAME or STRING, this is the string value */
+ protected String string = null;
+
+ /** the line number of the current token */
+ protected int line = 0;
+
+ /** the column number of the current token */
+ protected int col = 0;
+ /** the name of the source code file being lexed */
+ protected String sourceName = "unknown";
+
+ private SmartReader in;
public Lexer(Reader r) throws IOException { in = new SmartReader(r); }
// Predicates ///////////////////////////////////////////////////////////////////////
- protected static boolean isJSIdentifier(String s) {
- int length = s.length();
- if (length == 0 || !Character.isJavaIdentifierStart(s.charAt(0))) return false;
- for (int i=1; i<length; i++) {
- char c = s.charAt(i);
- if (!Character.isJavaIdentifierPart(c) && c == '\\' && !((i + 5) < length) &&
- (s.charAt(i + 1) == 'u') && 0 <= xDigitToInt(s.charAt(i + 2)) && 0 <= xDigitToInt(s.charAt(i + 3)) &&
- 0 <= xDigitToInt(s.charAt(i + 4)) && 0 <= xDigitToInt(s.charAt(i + 5)))
- return false;
- }
- return true;
- }
-
private static boolean isAlpha(int c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); }
private static boolean isDigit(int c) { return (c >= '0' && c <= '9'); }
- private static boolean isLineBreak(int c) { return (c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029); }
private static int xDigitToInt(int c) {
if ('0' <= c && c <= '9') return c - '0';
- if ('a' <= c && c <= 'f') return c - ('a' - 10);
- if ('A' <= c && c <= 'F') return c - ('A' - 10);
- return -1;
- }
- public static boolean isWhiteSpace(int c) {
- if (c == '\u0020' || c == '\u0009' || c == '\u000C' || c == '\u000B' || c == '\u00A0') return true;
- return Character.getType((char)c) == Character.SPACE_SEPARATOR;
+ else if ('a' <= c && c <= 'f') return c - ('a' - 10);
+ else if ('A' <= c && c <= 'F') return c - ('A' - 10);
+ else return -1;
}
in.unread();
String str = in.getString();
int result = getKeyword(str);
- if (result == RESERVED) throw new IOException("the reserved word \"" + str + "\" is not permitted in XWT scripts");
+ if (result == RESERVED) throw new LexerException("The reserved word \"" + str + "\" is not permitted in XWT scripts");
if (result != -1) return result;
- this.string = str;
+ this.string = str.intern();
return NAME;
}
if (c == 'e' || c == 'E') {
c = in.read();
if (c == '+' || c == '-') c = in.read();
- if (!isDigit(c)) throw new IOException("msg.missing.exponent");
+ if (!isDigit(c)) throw new LexerException("float listeral did not have an exponent value");
do { c = in.read(); } while (isDigit(c));
}
}
String numString = in.getString();
if (base == 10 && !isInteger) {
try { dval = (Double.valueOf(numString)).doubleValue(); }
- catch (NumberFormatException ex) { throw new IOException("msg.caught.nfe"); }
+ catch (NumberFormatException ex) { throw new LexerException("invalid numeric literal: \"" + numString + "\""); }
} else {
if (isInteger) {
longval = Long.parseLong(numString, base);
c = in.read();
in.startString(); // start after the first "
while(c != quoteChar) {
- if (c == '\n' || c == -1) throw new IOException("msg.unterminated.string.lit");
+ if (c == '\n' || c == -1) throw new LexerException("unterminated string literal");
if (c == '\\') {
if (stringBuf == null) {
in.unread(); // Don't include the backslash
for(int i=0; i<4; i++) {
int ci = in.read();
if (!((ci >= '0' && ci <= '9') || (ci >= 'a' && ci <= 'f') || (ci >= 'A' && ci <= 'F')))
- throw new IOException("illegal character '" + ((char)c) + "' in \\u unicode escape sequence");
+ throw new LexerException("illegal character '" + ((char)c) + "' in \\u unicode escape sequence");
v = (v << 8) | Integer.parseInt(ci + "", 16);
}
c = (char)v;
if (stringBuf != null) stringBuf.append((char) c);
c = in.read();
}
- if (stringBuf != null) this.string = stringBuf.toString();
+ if (stringBuf != null) this.string = stringBuf.toString().intern();
else {
in.unread(); // miss the trailing "
- this.string = in.getString();
+ this.string = in.getString().intern();
in.read();
}
return STRING;
public int _getToken() throws IOException {
int c;
- do { if ((c = in.read()) == '\n') break; } while (isWhiteSpace(c) || c == '\n');
+ do { c = in.read(); } while (c == '\u0020' || c == '\u0009' || c == '\u000C' || c == '\u000B' || c == '\n' );
if (c == -1) return -1;
if (c == '\\' || Character.isJavaIdentifierStart((char)c)) return getIdentifier(c);
if (isDigit(c) || (c == '.' && isDigit(in.peek()))) return getNumber(c);
if (c == '"' || c == '\'') return getString(c);
switch (c) {
- case '\n': return EOL;
case ';': return SEMI;
case '[': return LB;
case ']': return RB;
case '+': return in.match('=') ? ASSIGN_ADD : in.match('+') ? INC : ADD;
case '-': return in.match('=') ? ASSIGN_SUB: in.match('-') ? DEC : SUB;
case '*': return in.match('=') ? ASSIGN_MUL : MUL;
- case '<': return !in.match('<') ?
- (in.match('=') ? LE : LT) :
- in.match('=') ? ASSIGN_LSH : LSH;
- case '>': return !in.match('>') ?
- (in.match('=') ? GE : GT) :
- in.match('>') ?
- (in.match('=') ? ASSIGN_URSH : URSH) :
- (in.match('=') ? ASSIGN_RSH : RSH);
+ case '<': return !in.match('<') ? (in.match('=') ? LE : LT) : in.match('=') ? ASSIGN_LSH : LSH;
+ case '>': return !in.match('>') ? (in.match('=') ? GE : GT) :
+ in.match('>') ? (in.match('=') ? ASSIGN_URSH : URSH) : (in.match('=') ? ASSIGN_RSH : RSH);
case '/':
if (in.match('=')) return ASSIGN_DIV;
if (in.match('/')) { while ((c = in.read()) != -1 && c != '\n'); in.unread(); return getToken(); }
while ((c = in.read()) != -1 && !(c == '*' && in.match('/'))) {
if (c == '\n' || c != '/' || !in.match('*')) continue;
if (in.match('/')) return getToken();
- throw new IOException("msg.nested.comment");
+ throw new LexerException("nested comments are not permitted");
}
- if (c == -1) throw new IOException("msg.unterminated.comment");
+ if (c == -1) throw new LexerException("unterminated comment");
return getToken(); // `goto retry'
- default: throw new IOException("illegal character: " + ((char)c));
+ default: throw new LexerException("illegal character: \'" + ((char)c) + "\'");
}
}
+
+ // SmartReader ////////////////////////////////////////////////////////////////
+
+ /** a Reader that tracks line numbers and can push back tokens */
private class SmartReader {
PushbackReader reader = null;
int lastread = -1;
lastread = reader.read();
if (accumulator != null) accumulator.append((char)lastread);
if (lastread != '\n' && lastread != '\r') col++;
+ if (lastread == '\n') { line++; col = 0; }
return lastread;
}
}
- // PushBack Stuff ////////////////////////////////////////////////////////////
+ // Token PushBack code ////////////////////////////////////////////////////////////
- int pushBackDepth = 0;
- int[] pushBackInts = new int[10];
- Object[] pushBackObjects = new Object[10];
+ private int pushBackDepth = 0;
+ private int[] pushBackInts = new int[10];
+ private Object[] pushBackObjects = new Object[10];
+ /** push back a token */
public void pushBackToken(int op, Object obj) {
if (pushBackDepth >= pushBackInts.length - 1) {
int[] newInts = new int[pushBackInts.length * 2];
pushBackDepth++;
}
+ /** push back the most recently read token */
public void pushBackToken() { pushBackToken(op, number != null ? (Object)number : (Object)string); }
+ /** read a token but leave it in the stream */
public int peekToken() throws IOException {
int ret = getToken();
pushBackToken();
return ret;
}
+ /** read a token */
public int getToken() throws IOException {
number = null;
string = null;
- if (pushBackDepth > 0) {
- pushBackDepth--;
- op = pushBackInts[pushBackDepth];
- if (pushBackObjects[pushBackDepth] != null) {
- number = pushBackObjects[pushBackDepth] instanceof Number ? (Number)pushBackObjects[pushBackDepth] : null;
- string = pushBackObjects[pushBackDepth] instanceof String ? (String)pushBackObjects[pushBackDepth] : null;
- }
- } else {
- do {
- op = _getToken();
- if (op == EOL) { line++; col = 0; }
- } while (op == EOL);
+ if (pushBackDepth == 0) return _getToken();
+ pushBackDepth--;
+ op = pushBackInts[pushBackDepth];
+ if (pushBackObjects[pushBackDepth] != null) {
+ number = pushBackObjects[pushBackDepth] instanceof Number ? (Number)pushBackObjects[pushBackDepth] : null;
+ string = pushBackObjects[pushBackDepth] instanceof String ? (String)pushBackObjects[pushBackDepth] : null;
}
return op;
}
+ class LexerException extends IOException {
+ public LexerException(String s) { super(sourceName + ":" + line + "," + col + " " + s); }
+ }
}
precedence[LSH] = precedence[RSH] = precedence[URSH] = 12;
precedence[ADD] = precedence[SUB] = 13;
precedence[MUL] = precedence[DIV] = precedence[MOD] = 14;
- precedence[BITNOT] = precedence[INSTANCEOF] = 15;
+ precedence[BITNOT] = 15;
precedence[INC] = precedence[DEC] = 16;
precedence[LP] = 17;
precedence[LB] = 18;
// Parsing Logic /////////////////////////////////////////////////////////
+ private ByteCodeBlock newbb(int line) { return new ByteCodeBlock(line, sourceName); }
+
/** gets a token and throws an exception if it is not <tt>code</tt> */
public void consume(int code) throws IOException {
if (getToken() != code)
continueExpr(b, minPrecedence);
return;
}
- case BANG: case BITNOT: case INSTANCEOF: case TYPEOF: {
+ case BANG: case BITNOT: case TYPEOF: {
startExpr(precedence[tok], b);
b.add(tok);
continueExpr(b, minPrecedence);
case FUNCTION: {
consume(LP);
int numArgs = 0;
- ByteCodeBlock b2 = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock b2 = newbb(curLine);
b2.add(TOPSCOPE);
b2.add(SWAP);
b2.add(LITERAL, "arguments");
b.add(tok == AND ? b.JF : b.JT, new Integer(0));
int size = b.size();
startExpr(precedence[tok], b);
- b.arg[size - 1] = new Integer(b.size() - size + 2);
+ b.set(size - 1, new Integer(b.size() - size + 2));
b.add(JMP, new Integer(2));
b.add(LITERAL, tok == AND ? new Boolean(false) : new Boolean(true));
continueExpr(b, minPrecedence);
b.add(JF, new Integer(0));
int size = b.size();
startExpr(b);
- b.arg[size - 1] = new Integer(b.size() - size + 2);
+ b.set(size - 1, new Integer(b.size() - size + 2));
b.add(JMP, new Integer(0));
consume(COLON);
size = b.size();
startExpr(b);
- b.arg[size - 1] = new Integer(b.size() - size + 1);
+ b.set(size - 1, new Integer(b.size() - size + 1));
continueExpr(b, minPrecedence);
return;
}
if (peekToken() == ELSE) {
consume(ELSE);
- b.arg[size - 1] = new Integer(2 + b.size() - size);
+ b.set(size - 1, new Integer(2 + b.size() - size));
b.add(JMP, new Integer(0));
size = b.size();
parseStatement(false, b);
}
- b.arg[size - 1] = new Integer(1 + b.size() - size);
+ b.set(size - 1, new Integer(1 + b.size() - size));
break;
}
case WHILE: {
consume(WHILE);
consume(LP);
- ByteCodeBlock loop = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock loop = newbb(curLine);
b.add(LOOP, loop);
loop.add(POP);
case SWITCH: {
consume(SWITCH);
consume(LP);
- ByteCodeBlock loop = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock loop = newbb(curLine);
b.add(LOOP, loop);
startExpr(loop);
consume(RP);
parseStatement(false, loop);
if (size2 == loop.size()) break;
}
- loop.arg[size - 1] = new Integer(1 + loop.size() - size);
+ loop.set(size - 1, new Integer(1 + loop.size() - size));
} else if (peekToken() == DEFAULT) {
consume(DEFAULT);
consume(COLON);
case DO: {
consume(DO);
- ByteCodeBlock loop = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock loop = newbb(curLine);
b.add(LOOP, loop);
parseStatement(false, loop);
b.add(LITERAL, "length");
b.add(GET);
consume(RP);
- ByteCodeBlock b2 = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock b2 = newbb(curLine);
b.add(SCOPE, b2);
b2.add(LITERAL, new Integer(1));
b2.add(SUB);
break;
} else {
- ByteCodeBlock b2 = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock b2 = newbb(curLine);
b.add(SCOPE, b2);
b.add(POP);
consume(SEMI);
ByteCodeBlock e2 = startExpr();
consume(SEMI);
- if (e2 == null) e2 = new ByteCodeBlock(curLine, sourceName, b.LITERAL, null);
+ if (e2 == null) e2 = newbb(curLine).add(b.LITERAL, null);
- ByteCodeBlock b3 = new ByteCodeBlock(curLine, sourceName);
+ ByteCodeBlock b3 = newbb(curLine);
b2.add(LOOP, b3);
b2.add(LITERAL, null);
startExpr(b3);
consume(RP);
if (b3.size() - size > 0) b3.add(POP);
- b3.arg[size - 1] = new Integer(b3.size() - size + 1);
+ b3.set(size - 1, new Integer(b3.size() - size + 1));
b3.paste(e2);
b3.add(JT, new Integer(2));
-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
package org.xwt.js;
+/** this class contains a <tt>public static final int</tt> for each valid token */
interface Tokens {
+
// Token Constants //////////////////////////////////////////////////////////
- public final static int
- EOL = 1, // end of line
- RETURN = 2, // return
- GOTO = 3, // goto
- BITOR = 4, // |
- ASSIGN_BITOR = 5, // |=
- BITXOR = 6, // ^
- ASSIGN_BITXOR= 7, // ^=
- BITAND = 8, // &
- ASSIGN_BITAND= 9, // &=
- EQ = 10, // ==
- NE = 11, // !=
- LT = 12, // <
- LE = 13, // <=
- GT = 14, // >
- GE = 15, // >=
- LSH = 16, // <<
- ASSIGN_LSH = 17, // <<=
- RSH = 18, // >>
- ASSIGN_RSH = 19, // >>=
- URSH = 20, // >>>
- ASSIGN_URSH = 21, // >>>=
- ADD = 22, // +
- ASSIGN_ADD = 23, // +=
- SUB = 24, // -
- ASSIGN_SUB = 25, // -=
- MUL = 26, // *
- ASSIGN_MUL = 27, // *=
- DIV = 28, // /
- ASSIGN_DIV = 29, // /=
- MOD = 30, // %
- ASSIGN_MOD = 31, // %=
- BITNOT = 32, // ~
- ASSIGN_BITNOT= 33, // ~=
- DELPROP = 34, // delete
- TYPEOF = 35, // typeof
- NAME = 36, // *** identifiers ***
- NUMBER = 37, // *** numeric literals ***
- STRING = 38, // *** string literals ***
- NULL = 39, // null
- THIS = 40, // this
- FALSE = 41, // false
- TRUE = 42, // true
- SHEQ = 43, // ===
- SHNE = 44, // !==
- THROW = 45, // throw
- IN = 46, // in
- INSTANCEOF = 47, // instanceof
- TRY = 48, // try
- SEMI = 49, // ;
- LB = 50, // [
- RB = 51, // ]
- LC = 52, // {
- RC = 53, // }
- LP = 54, // (
- RP = 55, // )
- COMMA = 56, // ,
- ASSIGN = 57, // =
- HOOK = 58, // ?
- COLON = 59, // :
- OR = 60, // ||
- AND = 61, // &&
- INC = 62, // ++
- DEC = 63, // --
- DOT = 64, // .
- FUNCTION = 65, // function
- IF = 66, // if keyword
- ELSE = 67, // else keyword
- SWITCH = 68, // switch keyword
- CASE = 69, // case keyword
- DEFAULT = 70, // default keyword
- WHILE = 71, // while keyword
- DO = 72, // do keyword
- FOR = 73, // for keyword
- BREAK = 74, // break keyword
- CONTINUE = 75, // continue keyword
- VAR = 76, // var keyword
- WITH = 77, // with keyword
- CATCH = 78, // catch keyword
- FINALLY = 79, // finally keyword
- RESERVED = 80, // reserved keywords
- BANG = 84, // !
- ASSERT = 85; // assert keyword
+ public static final int EOL = -1; // end of line
+
+ // arithmetic operations; also valid as bytecodes
+ public static final int BITOR = 0; // |
+ public static final int ASSIGN_BITOR = 1; // |=
+ public static final int BITXOR = 2; // ^
+ public static final int ASSIGN_BITXOR = 3; // ^=
+ public static final int BITAND = 4; // &
+ public static final int ASSIGN_BITAND = 5; // &=
+ public static final int LSH = 6; // <<
+ public static final int ASSIGN_LSH = 7; // <<=
+ public static final int RSH = 8; // >>
+ public static final int ASSIGN_RSH = 9; // >>=
+ public static final int URSH = 10; // >>>
+ public static final int ASSIGN_URSH = 11; // >>>=
+ public static final int ADD = 12; // +
+ public static final int ASSIGN_ADD = 13; // +=
+ public static final int SUB = 14; // -
+ public static final int ASSIGN_SUB = 15; // -=
+ public static final int MUL = 16; // *
+ public static final int ASSIGN_MUL = 17; // *=
+ public static final int DIV = 18; // /
+ public static final int ASSIGN_DIV = 19; // /=
+ public static final int MOD = 20; // %
+ public static final int ASSIGN_MOD = 21; // %=
+ public static final int BITNOT = 22; // ~
+ public static final int ASSIGN_BITNOT = 23; // ~=
+
+ // logical operations; also valid as bytecodes
+ public static final int OR = 24; // ||
+ public static final int AND = 25; // &&
+ public static final int BANG = 26; // !
+
+ // equality operations; also valid as bytecodes
+ public static final int EQ = 27; // ==
+ public static final int NE = 28; // !=
+ public static final int LT = 29; // <
+ public static final int LE = 30; // <=
+ public static final int GT = 31; // >
+ public static final int GE = 32; // >=
+ public static final int SHEQ = 33; // ===
+ public static final int SHNE = 34; // !==
- public static final int MAX_TOKEN = ASSERT;
+ // other permissible bytecode tokens
+ public static final int RETURN = 35; // return
+ public static final int TYPEOF = 36; // typeof
+ public static final int BREAK = 37; // break keyword
+ public static final int CONTINUE = 38; // continue keyword
+ public static final int TRY = 39; // try
+ public static final int THROW = 40; // throw
+ public static final int ASSERT = 41; // assert keyword
+ public static final int NAME = 42; // *** identifiers ***
+ public static final int NUMBER = 43; // *** numeric literals ***
+ public static final int STRING = 44; // *** string literals ***
+ public static final int NULL = 45; // null
+ public static final int THIS = 46; // this
+ public static final int FALSE = 47; // false
+ public static final int TRUE = 48; // true
+ public static final int IN = 49; // in
+
+ public static final int SEMI = 50; // ;
+ public static final int LB = 51; // [
+ public static final int RB = 52; // ]
+ public static final int LC = 53; // {
+ public static final int RC = 54; // }
+ public static final int LP = 55; // (
+ public static final int RP = 56; // )
+ public static final int COMMA = 57; // ,
+ public static final int ASSIGN = 58; // =
+ public static final int HOOK = 59; // ?
+ public static final int COLON = 60; // :
+ public static final int INC = 61; // ++
+ public static final int DEC = 62; // --
+ public static final int DOT = 63; // .
+ public static final int FUNCTION = 64; // function
+ public static final int IF = 65; // if keyword
+ public static final int ELSE = 66; // else keyword
+ public static final int SWITCH = 67; // switch keyword
+ public static final int CASE = 68; // case keyword
+ public static final int DEFAULT = 69; // default keyword
+ public static final int WHILE = 70; // while keyword
+ public static final int DO = 71; // do keyword
+ public static final int FOR = 74; // for keyword
+ public static final int VAR = 75; // var keyword
+ public static final int WITH = 76; // with keyword
+ public static final int CATCH = 77; // catch keyword
+ public static final int FINALLY = 78; // finally keyword
+ public static final int RESERVED = 79; // reserved keyword
+
+ public static final int MAX_TOKEN = RESERVED;
+
public final static String[] codeToString = new String[] {
- "0", "EOL", "RETURN", "GOTO", "BITOR", "ASSIGN_BITOR",
- "BITXOR", "ASSIGN_BITXOR", "BITAND", "ASSIGN_BITAND", "EQ",
- "NE", "LT", "LE", "GT", "GE", "LSH", "ASSIGN_LSH", "RSH",
- "ASSIGN_RSH", "URSH", "ASSIGN_URSH", "ADD", "ASSIGN_ADD",
- "SUB", "ASSIGN_SUB", "MUL", "ASSIGN_MUL", "DIV", "ASSIGN_DIV",
- "MOD", "ASSIGN_MOD", "BITNOT", "ASSIGN_BITNOT=", "DELPROP",
- "TYPEOF", "NAME", "NUMBER", "STRING", "NULL", "THIS", "FALSE",
- "TRUE", "SHEQ", "SHNE", "THROW", "IN", "INSTANCEOF", "TRY",
- "SEMI", "LB", "RB", "LC", "RC", "LP", "RP", "COMMA", "ASSIGN",
- "HOOK", "COLON", "OR", "AND", "INC", "DEC", "DOT", "FUNCTION",
- "IF", "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO",
- "FOR", "BREAK", "CONTINUE", "VAR", "WITH", "CATCH", "FINALLY",
- "RESERVED", "BANG", "ASSERT" };
+ "BITOR", "ASSIGN_BITOR", "BITXOR", "ASSIGN_BITXOR", "BITAND",
+ "ASSIGN_BITAND", "LSH", "ASSIGN_LSH", "RSH", "ASSIGN_RSH",
+ "URSH", "ASSIGN_URSH", "ADD", "ASSIGN_ADD", "SUB",
+ "ASSIGN_SUB", "MUL", "ASSIGN_MUL", "DIV", "ASSIGN_DIV", "MOD",
+ "ASSIGN_MOD", "BITNOT", "ASSIGN_BITNOT", "OR", "AND", "BANG",
+ "EQ", "NE", "LT", "LE", "GT", "GE", "SHEQ", "SHNE", "RETURN",
+ "TYPEOF", "BREAK", "CONTINUE", "TRY", "THROW", "ASSERT", "NAME",
+ "NUMBER", "STRING", "NULL", "THIS", "FALSE", "TRUE", "IN",
+ "SEMI", "LB", "RB", "LC", "RC", "LP", "RP", "COMMA", "ASSIGN",
+ "HOOK", "COLON", "INC", "DEC", "DOT", "FUNCTION", "IF",
+ "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR",
+ "VAR", "WITH", "CATCH", "FINALLY", "RESERVED"
+ };
}
+
+