X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fjs%2FParser.java;h=9183c945a5128fc0a914ae18849b5934eefb85f7;hb=c9061d8a61194e28b998538995811c55b67390f3;hp=10159b7b4fd23214c7e8f9a901d4e0c2c4ee8992;hpb=52ffc2a48fc74d013ae7fa401d9d0d405543c38e;p=org.ibex.core.git diff --git a/src/org/xwt/js/Parser.java b/src/org/xwt/js/Parser.java index 10159b7..9183c94 100644 --- a/src/org/xwt/js/Parser.java +++ b/src/org/xwt/js/Parser.java @@ -111,13 +111,13 @@ class Parser extends Lexer implements ByteCodes { precedence[ASSIGN_MOD] = 1; precedence[HOOK] = 2; precedence[COMMA] = 3; - precedence[OR] = precedence[AND] = 4; + precedence[OR] = precedence[AND] = precedence[BANG] = 4; precedence[GT] = precedence[GE] = 5; precedence[BITOR] = 6; precedence[BITXOR] = 7; precedence[BITAND] = 8; precedence[EQ] = precedence[NE] = 9; - precedence[LT] = precedence[LE] = 10; + precedence[LT] = precedence[LE] = precedence[TYPEOF] = 10; precedence[SHEQ] = precedence[SHNE] = 11; precedence[LSH] = precedence[RSH] = precedence[URSH] = 12; precedence[ADD] = precedence[SUB] = 13; @@ -194,9 +194,14 @@ class Parser extends Lexer implements ByteCodes { } case INC: case DEC: { // prefix (not postfix) startExpr(b, precedence[tok]); - if (b.get(b.size() - 1) != GET) + int prev = b.size() - 1; + if (b.get(prev) == GET && b.getArg(prev) != null) + b.set(prev, LITERAL, b.getArg(prev)); + else if(b.get(prev) == GET) + b.pop(); + else throw pe("prefixed increment/decrement can only be performed on a valid assignment target"); - b.set(b.size() - 1, tok, new Boolean(true)); + b.add(parserLine, tok, Boolean.TRUE); break; } case BANG: case BITNOT: case TYPEOF: { @@ -236,38 +241,26 @@ class Parser extends Lexer implements ByteCodes { b.add(parserLine, NEWFUNCTION, b2); // function prelude; arguments array is already on the stack - b2.add(parserLine, TOPSCOPE); // push the scope onto the stack - b2.add(parserLine, SWAP); // swap 'this' and 'arguments' - - b2.add(parserLine, LITERAL, "arguments"); // declare arguments (equivalent to 'var arguments;') - b2.add(parserLine, DECLARE); - - b2.add(parserLine, LITERAL, "arguments"); // set this.arguments and leave the value on the stack + b2.add(parserLine, TOPSCOPE); b2.add(parserLine, SWAP); + b2.add(parserLine, DECLARE, "arguments"); // declare arguments (equivalent to 'var arguments;') + b2.add(parserLine, SWAP); // set this.arguments and leave the value on the stack b2.add(parserLine, PUT); - b2.add(parserLine, SWAP); - b2.add(parserLine, POP); while(peekToken() != RP) { // run through the list of argument names if (peekToken() == NAME) { consume(NAME); // a named argument + String varName = string; - b2.add(parserLine, LITERAL, string); // declare the name - b2.add(parserLine, DECLARE); - - b2.add(parserLine, LITERAL, new Integer(numArgs)); // retrieve it from the arguments array - b2.add(parserLine, GET_PRESERVE); + b2.add(parserLine, DUP); // dup the args array + b2.add(parserLine, GET, new Integer(numArgs)); // retrieve it from the arguments array + b2.add(parserLine, TOPSCOPE); b2.add(parserLine, SWAP); - b2.add(parserLine, POP); - - b2.add(parserLine, TOPSCOPE); // put it to the current scope - b2.add(parserLine, SWAP); - b2.add(parserLine, LITERAL, string); + b2.add(parserLine, DECLARE, varName); // declare the name b2.add(parserLine, SWAP); - b2.add(parserLine, PUT); - - b2.add(parserLine, POP); // clean the stack - b2.add(parserLine, POP); + b2.add(parserLine, PUT); + b2.add(parserLine, POP); // pop the value + b2.add(parserLine, POP); // pop the scope } if (peekToken() == RP) break; consume(COMMA); @@ -276,11 +269,17 @@ class Parser extends Lexer implements ByteCodes { consume(RP); b2.add(parserLine, POP); // pop off the arguments array + b2.add(parserLine, POP); // pop off TOPSCOPE + + if(peekToken() != LC) + throw pe("Functions must have a block surrounded by curly brackets"); + + parseBlock(b2, null); // the function body - parseStatement(b2, null); // the function body - - b2.add(parserLine, LITERAL, null); // in case we "fall out the bottom", return NULL - b2.add(parserLine, RETURN); + if(b2.get(b2.size()-1) != RETURN) { + b2.add(parserLine, LITERAL, null); // in case we "fall out the bottom", return NULL + b2.add(parserLine, RETURN); + } break; } @@ -336,9 +335,17 @@ class Parser extends Lexer implements ByteCodes { b.add(parserLine, POP); break; } + case LP: { + int n = parseArgs(b); + b.add(parserLine,CALLMETHOD,new Integer(n)); + break; + } default: { pushBackToken(); - b.add(parserLine, GET); + if(b.get(b.size()-1) == LITERAL && b.getArg(b.size()-1) != null) + b.set(b.size()-1,GET,b.getArg(b.size()-1)); + else + b.add(parserLine, GET); return; } } @@ -372,17 +379,8 @@ class Parser extends Lexer implements ByteCodes { switch (tok) { case LP: { // invocation (not grouping) - int i = 0; - while(peekToken() != RP) { - i++; - if (peekToken() != COMMA) { - startExpr(b, -1); - if (peekToken() == RP) break; - } - consume(COMMA); - } - consume(RP); - b.add(parserLine, CALL, new Integer(i)); + int n = parseArgs(b); + b.add(parserLine, CALL, new Integer(n)); break; } case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH: @@ -435,6 +433,21 @@ class Parser extends Lexer implements ByteCodes { continueExpr(b, minPrecedence); // try to continue the expression } + // parse a set of comma separated function arguments, assume LP has already been consumed + private int parseArgs(CompiledFunctionImpl b) throws IOException { + int i = 0; + while(peekToken() != RP) { + i++; + if (peekToken() != COMMA) { + startExpr(b, -1); + if (peekToken() == RP) break; + } + consume(COMMA); + } + consume(RP); + return i; + } + /** Parse a block of statements which must be surrounded by LC..RC. */ void parseBlock(CompiledFunctionImpl b) throws IOException { parseBlock(b, null); } void parseBlock(CompiledFunctionImpl b, String label) throws IOException { @@ -482,16 +495,15 @@ class Parser extends Lexer implements ByteCodes { b.add(parserLine, TOPSCOPE); // push the current scope while(true) { consume(NAME); - String name = string; - b.add(parserLine, LITERAL, name); // push the name to be declared - b.add(parserLine, DECLARE); // declare it + b.add(parserLine, DECLARE, string); // declare it if (peekToken() == ASSIGN) { // if there is an '=' after the variable name - b.add(parserLine, LITERAL, name); // put the var name back on the stack consume(ASSIGN); startExpr(b, -1); b.add(parserLine, PUT); // assign it b.add(parserLine, POP); // clean the stack - } + } else { + b.add(parserLine, POP); // pop the string pushed by declare + } if (peekToken() != COMMA) break; consume(COMMA); } @@ -585,37 +597,56 @@ class Parser extends Lexer implements ByteCodes { } case TRY: { - b.add(parserLine, TRY); - int size = b.size(); - parseStatement(b, null); // parse the expression to be TRYed - b.add(parserLine, POP); // pop the TryMarker - b.add(parserLine, JMP); // jump forward to the end of the catch block - int size2 = b.size(); - b.set(size - 1, new Integer(b.size() - size + 1)); // the TRY argument points at the start of the CATCH block + b.add(parserLine, TRY); // try bytecode causes a TryMarker to be pushed + int tryInsn = b.size() - 1; + // parse the expression to be TRYed + parseStatement(b, null); + // pop the try marker. this is pushed when the TRY bytecode is executed + b.add(parserLine, POP); + // jump forward to the end of the catch block, start of the finally block + b.add(parserLine, JMP); + int successJMPInsn = b.size() - 1; + if (peekToken() != CATCH && peekToken() != FINALLY) + throw pe("try without catch or finally"); + + int catchJMPDistance = -1; if (peekToken() == CATCH) { + 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); + b.add(parserLine, LITERAL,exceptionVar); b.add(parserLine, SWAP); b.add(parserLine, PUT); b.add(parserLine, POP); b.add(parserLine, POP); parseStatement(b, null); + // pop the try and catch markers + b.add(parserLine,POP); + b.add(parserLine,POP); } // jump here if no exception was thrown - b.set(size2 - 1, new Integer(b.size() - size2 + 1)); - - // FIXME: not implemented correctly + b.set(successJMPInsn, new Integer(b.size() - successJMPInsn)); + + int finallyJMPDistance = -1; if (peekToken() == FINALLY) { + b.add(parserLine, LITERAL, null); // null FinallyData + finallyJMPDistance = b.size() - tryInsn; consume(FINALLY); parseStatement(b, null); + b.add(parserLine,FINALLY_DONE); } + + // setup the TRY arguments + b.set(tryInsn, new int[] { catchJMPDistance, finallyJMPDistance }); + break; }