From c7958573764aab1b512024456f975bb41f81a7b7 Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:00:50 +0000 Subject: [PATCH] 2003/06/07 09:37:13 darcs-hash:20040130070050-2ba56-dfd97756c2e45f666d178172d84ed297672b8fd5.gz --- src/org/xwt/js/Parser.java | 429 ++++++++++++++++++++------------------------ 1 file changed, 191 insertions(+), 238 deletions(-) diff --git a/src/org/xwt/js/Parser.java b/src/org/xwt/js/Parser.java index 5a170ba..cc55164 100644 --- a/src/org/xwt/js/Parser.java +++ b/src/org/xwt/js/Parser.java @@ -32,60 +32,7 @@ public class Parser extends Lexer implements OpCodes { static byte[] precedence = new byte[MAX_TOKEN + 1]; static boolean[] isRightAssociative = new boolean[MAX_TOKEN + 1]; - static boolean[] mustStartExpression = new boolean[MAX_TOKEN + 1]; - static boolean[] cannotStartExpression = new boolean[MAX_TOKEN + 1]; static { - - mustStartExpression[VAR] = true; - mustStartExpression[IF] = true; - mustStartExpression[BANG] = true; - mustStartExpression[BITNOT] = true; - mustStartExpression[INSTANCEOF] = true; - mustStartExpression[TYPEOF] = true; - mustStartExpression[NUMBER] = true; - mustStartExpression[STRING] = true; - mustStartExpression[NULL] = true; - mustStartExpression[TRUE] = true; - mustStartExpression[FALSE] = true; - mustStartExpression[Tokens.FUNCTION] = true; - mustStartExpression[NAME] = true; - mustStartExpression[LC] = true; - mustStartExpression[THIS] = true; - - cannotStartExpression[OR] = true; - cannotStartExpression[AND] = true; - cannotStartExpression[BITOR] = true; - cannotStartExpression[BITXOR] = true; - cannotStartExpression[BITAND] = true; - cannotStartExpression[SHEQ] = true; - cannotStartExpression[SHNE] = true; - cannotStartExpression[LSH] = true; - cannotStartExpression[RSH] = true; - cannotStartExpression[URSH] = true; - cannotStartExpression[ADD] = true; - cannotStartExpression[MUL] = true; - cannotStartExpression[DIV] = true; - cannotStartExpression[MOD] = true; - cannotStartExpression[GT] = true; - cannotStartExpression[GE] = true; - cannotStartExpression[EQ] = true; - cannotStartExpression[NE] = true; - cannotStartExpression[LT] = true; - cannotStartExpression[LE] = true; - cannotStartExpression[DOT] = true; - cannotStartExpression[HOOK] = true; - cannotStartExpression[ASSIGN_BITOR] = true; - cannotStartExpression[ASSIGN_BITXOR] = true; - cannotStartExpression[ASSIGN_BITAND] = true; - cannotStartExpression[ASSIGN_LSH] = true; - cannotStartExpression[ASSIGN_RSH] = true; - cannotStartExpression[ASSIGN_URSH] = true; - cannotStartExpression[ASSIGN_ADD] = true; - cannotStartExpression[ASSIGN_SUB] = true; - cannotStartExpression[ASSIGN_MUL] = true; - cannotStartExpression[ASSIGN_DIV] = true; - cannotStartExpression[ASSIGN_MOD] = true; - isRightAssociative[ASSIGN] = true; precedence[ASSIGN] = 1; @@ -118,120 +65,85 @@ public class Parser extends Lexer implements OpCodes { throw new ParserException("expected " + codeToString[code] + ", got " + (op == -1 ? "EOL" : codeToString[op])); } - /** parses the largest possible expression */ - public ForthBlock parseExpr() throws IOException { return parseExpr(null, -1); } - - /** return the largest expression beginning with prefix containing no operators of precedence below minPrecedence */ - public ForthBlock parseExpr(ForthBlock prefix, int minPrecedence) throws IOException { - return parseExpr(prefix, minPrecedence, new ForthBlock(line, sourceName)); - } - /** append the largest expression beginning with prefix containing no operators of precedence below minPrecedence */ - public ForthBlock parseExpr(ForthBlock prefix, int minPrecedence, ForthBlock appendTo) throws IOException { + public ForthBlock startExpr() throws IOException { return startExpr(-1); } + public ForthBlock startExpr(int minPrecedence) throws IOException { return startExpr(minPrecedence, new ForthBlock(line, sourceName)); } + public ForthBlock startExpr(int minPrecedence, ForthBlock appendTo) throws IOException { int tok = getToken(); int curLine = line; - if (tok == -1) return prefix; + if (tok == -1) return null; if (minPrecedence > 0 && precedence[tok] != 0) if (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok])) - { pushBackToken(); return prefix; } - - if (prefix != null && mustStartExpression[tok]) { pushBackToken(); return prefix; } - if (prefix == null && cannotStartExpression[tok]) { pushBackToken(); return prefix; } + { pushBackToken(); return null; } ForthBlock b = appendTo; switch (tok) { - - case NUMBER: return parseExpr(b.add(ForthBlock.LITERAL, number), minPrecedence); - case STRING: return parseExpr(b.add(ForthBlock.LITERAL, string), minPrecedence); - case THIS: return parseExpr(b.add(THIS, null), minPrecedence); - case NULL: return parseExpr(b.add(ForthBlock.LITERAL, null), minPrecedence); - case TRUE: case FALSE: return parseExpr(b.add(ForthBlock.LITERAL, new Boolean(tok == TRUE)), minPrecedence); - - 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: { - b.add(b.EXPR, prefix); - prefix.set(prefix.size() - 1, b.GET_PRESERVE, new Boolean(true)); - prefix.add(prefix.EXPR, parseExpr(null, precedence[tok - 1])); - prefix.add(tok - 1); - prefix.add(b.PUT); - prefix.add(b.SWAP); - prefix.add(b.POP); - return parseExpr(b, minPrecedence); - } - - case INC: case DEC: - if (prefix == null) { - // prefix - ForthBlock subexp = parseExpr(null, precedence[tok]); - subexp.set(subexp.size() - 1, tok, new Boolean(true)); - b.add(b.EXPR, subexp); - return parseExpr(b, minPrecedence); - } else { - // postfix - prefix.set(prefix.size() - 1, tok, new Boolean(false)); - b.add(b.EXPR, prefix); - return parseExpr(b, minPrecedence); - } - - case LP: - if (prefix == null) { // grouping - b.add(EXPR, parseExpr()); - consume(RP); - return parseExpr(b, minPrecedence); - - } else { // invocation - int i = 0; - b.add(b.EXPR, prefix); - while(peekToken() != RP) { - b.add(b.EXPR, parseExpr()); - i++; - if (peekToken() == RP) break; - consume(COMMA); - } - consume(RP); - b.add(b.CALL, new Integer(i)); - return parseExpr(b, minPrecedence); + case NUMBER: return continueExpr(b.add(ForthBlock.LITERAL, number), minPrecedence); + case STRING: return continueExpr(b.add(ForthBlock.LITERAL, string), minPrecedence); + case THIS: return continueExpr(b.add(THIS, null), minPrecedence); + case NULL: return continueExpr(b.add(ForthBlock.LITERAL, null), minPrecedence); + case TRUE: case FALSE: return continueExpr(b.add(ForthBlock.LITERAL, new Boolean(tok == TRUE)), minPrecedence); + case LB: { + b.add(b.ARRAY, new Integer(0)); + int i = 0; + while(true) { + ForthBlock e = startExpr(); + if (e == null && peekToken() == RB) { consume(RB); return continueExpr(b, minPrecedence); } + b.add(b.LITERAL, new Integer(i++)); + if (e == null) b.add(b.LITERAL, null); + else b.add(b.EXPR, e); + b.add(b.PUT); + b.add(b.POP); + if (peekToken() == RB) { consume(RB); return continueExpr(b, minPrecedence); } + consume(COMMA); } - + } + case SUB: { + consume(NUMBER); + return continueExpr(b.add(ForthBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence); + } + case LP: { + b.add(EXPR, startExpr()); + consume(RP); + return continueExpr(b, minPrecedence); + } + case INC: case DEC: { + // prefix + ForthBlock subexp = startExpr(precedence[tok]); + subexp.set(subexp.size() - 1, tok, new Boolean(true)); + b.add(b.EXPR, subexp); + return continueExpr(b, minPrecedence); + } case BANG: case BITNOT: case INSTANCEOF: case TYPEOF: { - b.add(b.EXPR, parseExpr(null, precedence[tok])); + b.add(b.EXPR, startExpr(precedence[tok])); b.add(tok); - return parseExpr(b, minPrecedence); + return continueExpr(b, minPrecedence); } - - case SUB: - if (prefix == null) { - consume(NUMBER); - return parseExpr(b.add(ForthBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence); + case LC: { + b.add(b.OBJECT, null); + if (peekToken() == RC) { consume(RC); return continueExpr(b, minPrecedence); } + while(true) { + if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING"); + getToken(); + b.add(b.LITERAL, string); + consume(COLON); + b.add(b.EXPR, startExpr()); + b.add(b.PUT); + b.add(b.POP); + if (peekToken() == RC) { consume(RC); return continueExpr(b, minPrecedence); } + consume(COMMA); + if (peekToken() == RC) { consume(RC); return continueExpr(b, minPrecedence); } } - // fall through - case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH: - case RSH: case URSH: case ADD: case MUL: case DIV: case MOD: - case GT: case GE: case EQ: case NE: case LT: case LE: { - b.add(b.EXPR, prefix); - b.add(b.EXPR, parseExpr(null, precedence[tok])); - b.add(tok); - return parseExpr(b, minPrecedence); } - - case OR: case AND: { - b.add(b.LITERAL, tok == AND ? new Boolean(false) : new Boolean(true)); - b.add(b.EXPR, prefix); - b.add(tok == AND ? b.JF : b.JT, new Integer(3)); - b.add(b.POP); - b.add(b.EXPR, parseExpr(null, precedence[tok])); - return parseExpr(b, minPrecedence); - } - case NAME: { String name = string; if (peekToken() == ASSIGN) { consume(ASSIGN); b.add(THIS); b.add(ForthBlock.LITERAL, name); - b.add(ForthBlock.EXPR, parseExpr(null, minPrecedence)); + b.add(ForthBlock.EXPR, startExpr(minPrecedence)); b.add(ForthBlock.PUT); b.add(ForthBlock.SWAP); b.add(ForthBlock.POP); @@ -240,87 +152,8 @@ public class Parser extends Lexer implements OpCodes { b.add(ForthBlock.LITERAL, name); b.add(ForthBlock.GET); } - return parseExpr(b, minPrecedence); - } - - case DOT: { - consume(NAME); - String target = string; - b.add(b.EXPR, prefix); - if (peekToken() == ASSIGN) { - consume(ASSIGN); - ForthBlock val = parseExpr(); - b.add(b.LITERAL, target); - b.add(b.EXPR, val); - b.add(b.PUT); - b.add(b.SWAP); - b.add(b.POP); - } else { - b.add(b.LITERAL, target); - b.add(b.GET); - } - return parseExpr(b, minPrecedence); - } - - case LB: { - if (prefix == null) { - b.add(b.ARRAY, new Integer(0)); - int i = 0; - while(true) { - ForthBlock e = parseExpr(); - if (e == null && peekToken() == RB) { consume(RB); return parseExpr(b, minPrecedence); } - b.add(b.LITERAL, new Integer(i++)); - if (e == null) b.add(b.LITERAL, null); - else b.add(b.EXPR, e); - b.add(b.PUT); - b.add(b.POP); - if (peekToken() == RB) { consume(RB); return parseExpr(b, minPrecedence); } - consume(COMMA); - } - } else { - b.add(b.EXPR, prefix); - b.add(b.EXPR, parseExpr()); - consume(RB); - if (peekToken() == ASSIGN) { - consume(ASSIGN); - b.add(b.EXPR, parseExpr()); - b.add(b.PUT); - b.add(b.SWAP); - b.add(b.POP); - } else { - b.add(b.GET); - } - return parseExpr(b, minPrecedence); - } - } - - case LC: { - b.add(b.OBJECT, null); - if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); } - while(true) { - if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING"); - getToken(); - b.add(b.LITERAL, string); - consume(COLON); - b.add(b.EXPR, parseExpr()); - b.add(b.PUT); - b.add(b.POP); - if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); } - consume(COMMA); - if (peekToken() == RC) { consume(RC); return parseExpr(b, minPrecedence); } - } + return continueExpr(b, minPrecedence); } - - case HOOK: { - b.add(b.EXPR, prefix); - b.add(b.JF, new Integer(3)); - b.add(b.EXPR, parseExpr()); - b.add(b.JMP, new Integer(2)); - consume(COLON); - b.add(b.EXPR, parseExpr()); - return parseExpr(b, minPrecedence); - } - case Tokens.FUNCTION: { consume(LP); int numArgs = 0; @@ -373,8 +206,128 @@ public class Parser extends Lexer implements OpCodes { parseStatement(true, b2); b2.add(b.LITERAL, null); b2.add(RETURN); - return parseExpr(b.add(OpCodes.FUNCTION, b2), minPrecedence); + return continueExpr(b.add(OpCodes.FUNCTION, b2), minPrecedence); + } + default: pushBackToken(); return null; + } + } + + + /** return the largest expression beginning with prefix containing no operators of precedence below minPrecedence */ + public ForthBlock continueExpr(ForthBlock prefix, int minPrecedence) throws IOException { + return continueExpr(prefix, minPrecedence, new ForthBlock(line, sourceName)); + } + public ForthBlock continueExpr(ForthBlock prefix, int minPrecedence, ForthBlock appendTo) throws IOException { + int tok = getToken(); + int curLine = line; + if (tok == -1) return prefix; + if (minPrecedence > 0 && precedence[tok] != 0) + if (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok])) + { pushBackToken(); return prefix; } + + if (prefix == null) throw new Error("got null prefix"); + + ForthBlock b = appendTo; + + switch (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: { + b.add(b.EXPR, prefix); + prefix.set(prefix.size() - 1, b.GET_PRESERVE, new Boolean(true)); + prefix.add(prefix.EXPR, startExpr(precedence[tok - 1])); + prefix.add(tok - 1); + prefix.add(b.PUT); + prefix.add(b.SWAP); + prefix.add(b.POP); + return continueExpr(b, minPrecedence); + } + + case INC: case DEC: { + // postfix + prefix.set(prefix.size() - 1, tok, new Boolean(false)); + b.add(b.EXPR, prefix); + return continueExpr(b, minPrecedence); + } + + case LP: { + // invocation + int i = 0; + b.add(b.EXPR, prefix); + while(peekToken() != RP) { + b.add(b.EXPR, startExpr()); + i++; + if (peekToken() == RP) break; + consume(COMMA); + } + consume(RP); + b.add(b.CALL, new Integer(i)); + return continueExpr(b, minPrecedence); + } + + case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH: + case RSH: case URSH: case ADD: case MUL: case DIV: case MOD: + case GT: case GE: case EQ: case NE: case LT: case LE: case SUB: { + b.add(b.EXPR, prefix); + b.add(b.EXPR, startExpr(precedence[tok])); + b.add(tok); + return continueExpr(b, minPrecedence); } + + case OR: case AND: { + b.add(b.LITERAL, tok == AND ? new Boolean(false) : new Boolean(true)); + b.add(b.EXPR, prefix); + b.add(tok == AND ? b.JF : b.JT, new Integer(3)); + b.add(b.POP); + b.add(b.EXPR, startExpr(precedence[tok])); + return continueExpr(b, minPrecedence); + } + + case DOT: { + consume(NAME); + String target = string; + b.add(b.EXPR, prefix); + if (peekToken() == ASSIGN) { + consume(ASSIGN); + ForthBlock val = startExpr(); + b.add(b.LITERAL, target); + b.add(b.EXPR, val); + b.add(b.PUT); + b.add(b.SWAP); + b.add(b.POP); + } else { + b.add(b.LITERAL, target); + b.add(b.GET); + } + return continueExpr(b, minPrecedence); + } + + case LB: { + b.add(b.EXPR, prefix); + b.add(b.EXPR, startExpr()); + consume(RB); + if (peekToken() == ASSIGN) { + consume(ASSIGN); + b.add(b.EXPR, startExpr()); + b.add(b.PUT); + b.add(b.SWAP); + b.add(b.POP); + } else { + b.add(b.GET); + } + return continueExpr(b, minPrecedence); + } + + case HOOK: { + b.add(b.EXPR, prefix); + b.add(b.JF, new Integer(3)); + b.add(b.EXPR, startExpr()); + b.add(b.JMP, new Integer(2)); + consume(COLON); + b.add(b.EXPR, startExpr()); + return continueExpr(b, minPrecedence); + } + default: pushBackToken(); return prefix; } @@ -405,7 +358,7 @@ public class Parser extends Lexer implements OpCodes { case THROW: case RETURN: case ASSERT: { getToken(); if (tok == RETURN && peekToken() == SEMI) b.add(b.LITERAL, null); - else b.add(b.EXPR, parseExpr()); + else b.add(b.EXPR, startExpr()); consume(SEMI); b.add(tok); break; @@ -435,7 +388,7 @@ public class Parser extends Lexer implements OpCodes { if (peekToken() == ASSIGN) { // if there is an '=' after the variable name b.add(b.LITERAL, name); // put the var name back on the stack consume(ASSIGN); - b.add(b.EXPR, parseExpr()); + b.add(b.EXPR, startExpr()); b.add(b.PUT); b.add(b.POP); } @@ -450,7 +403,7 @@ public class Parser extends Lexer implements OpCodes { case IF: { consume(IF); consume(LP); - b.add(b.EXPR, parseExpr()); + b.add(b.EXPR, startExpr()); consume(RP); b.add(b.JF, new Integer(4)); b.add(b.EXPR, parseStatement()); @@ -474,7 +427,7 @@ public class Parser extends Lexer implements OpCodes { b.add(loop.LOOP, loop); loop.add(loop.POP); - loop.add(loop.EXPR, parseExpr()); + loop.add(loop.EXPR, startExpr()); loop.add(loop.JT, new Integer(2)); loop.add(Lexer.BREAK); consume(RP); @@ -490,7 +443,7 @@ public class Parser extends Lexer implements OpCodes { consume(LP); ForthBlock loop = new ForthBlock(curLine, sourceName); b.add(loop.LOOP, loop); - loop.add(loop.EXPR, parseExpr()); + loop.add(loop.EXPR, startExpr()); consume(RP); consume(LC); while(true) { @@ -498,7 +451,7 @@ public class Parser extends Lexer implements OpCodes { tok = getToken(); if (tok == CASE) { loop.add(loop.DUP); - loop.add(loop.EXPR, parseExpr()); + loop.add(loop.EXPR, startExpr()); loop.add(EQ); loop.add(loop.JF, new Integer(2)); } else if (tok != DEFAULT) throw new ParserException("expected CASE or DEFAULT"); @@ -528,7 +481,7 @@ public class Parser extends Lexer implements OpCodes { parseStatement(false, loop); consume(WHILE); consume(LP); - loop.add(loop.EXPR, parseExpr()); + loop.add(loop.EXPR, startExpr()); loop.add(loop.JT, new Integer(2)); loop.add(Lexer.BREAK); loop.add(Lexer.CONTINUE); @@ -571,7 +524,7 @@ public class Parser extends Lexer implements OpCodes { if (forIn) { consume(NAME); consume(IN); - b.add(b.EXPR, parseExpr()); + b.add(b.EXPR, startExpr()); b.add(b.PUSHKEYS); b.add(b.LITERAL, "length"); b.add(b.GET); @@ -598,15 +551,15 @@ public class Parser extends Lexer implements OpCodes { b.add(b.SCOPE, b2); b.add(b.POP); - ForthBlock e1 = parseExpr(); + ForthBlock e1 = startExpr(); if (e1 == null) e1 = new ForthBlock(curLine, sourceName, b.LITERAL, null); b2.add(b.EXPR, e1); b2.add(b.POP); consume(SEMI); - ForthBlock e2 = parseExpr(); + ForthBlock e2 = startExpr(); consume(SEMI); - ForthBlock e3 = parseExpr(); + ForthBlock e3 = startExpr(); consume(RP); if (e2 == null) e2 = new ForthBlock(curLine, sourceName, b.LITERAL, null); @@ -644,7 +597,7 @@ public class Parser extends Lexer implements OpCodes { if (tok == RC && braced) { consume(RC); return; } // fall through default: { - ForthBlock ret = parseExpr(); + ForthBlock ret = startExpr(); if (ret == null) return; b.add(b.EXPR, ret); b.add(b.POP); -- 1.7.10.4