diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java index 0d7874c5e84..dcc57415a01 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java @@ -127,7 +127,7 @@ public class Parser { } Object pn = nf.createScript(tempBlock, ts.getSourceName(), baseLineno, ts - .getLineno(), sourceToString(0)); + .getLineno(), null); ((Node) pn).setIsSyntheticBlock(true); return pn; } @@ -178,7 +178,6 @@ public class Parser { Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) { // Extension to ECMA: if 'function ' does not follow // by '(', assume starts memberExpr - sourceAddString(ts.NAME, name); Object memberExprHead = nf.createName(name); name = null; memberExprNode = memberExprTail(ts, false, memberExprHead); @@ -200,16 +199,6 @@ public class Parser { mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); } - if (memberExprNode != null) { - // transform 'function' to = function - // even in the decompilated source - sourceAdd((char) ts.ASSIGN); - sourceAdd((char) ts.NOP); - } - - // save a reference to the function in the enclosing source. - sourceAdd((char) ts.FUNCTION); - sourceAdd((char) functionNumber); ++functionNumber; // Save current source top to restore it on exit not to include @@ -218,53 +207,32 @@ public class Parser { int savedFunctionNumber = functionNumber; Object args; Object body; - String source; try { functionNumber = 0; - - // FUNCTION as the first token in a Source means it's a function - // definition, and not a reference. - sourceAdd((char) ts.FUNCTION); - if (name != null) { - sourceAddString(ts.NAME, name); - } - sourceAdd((char) ts.LP); args = nf.createLeaf(ts.LP); if (!ts.matchToken(ts.GWT)) { - boolean first = true; do { - if (!first) - sourceAdd((char) ts.COMMA); - first = false; mustMatchToken(ts, ts.NAME, "msg.no.parm"); String s = ts.getString(); nf.addChildToBack(args, nf.createName(s)); - sourceAddString(ts.NAME, s); } while (ts.matchToken(ts.COMMA)); mustMatchToken(ts, ts.GWT, "msg.no.paren.after.parms"); } - sourceAdd((char) ts.GWT); mustMatchToken(ts, ts.LC, "msg.no.brace.body"); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); body = parseFunctionBody(ts); mustMatchToken(ts, ts.RC, "msg.no.brace.after.body"); - sourceAdd((char) ts.RC); // skip the last EOL so nested functions work... - - // name might be null; - source = sourceToString(savedSourceTop); } finally { sourceTop = savedSourceTop; functionNumber = savedFunctionNumber; } Object pn = nf.createFunction(name, args, body, ts.getSourceName(), - baseLineno, ts.getLineno(), source, isExpr || memberExprNode != null); + baseLineno, ts.getLineno(), null, isExpr || memberExprNode != null); if (memberExprNode != null) { pn = nf.createBinary(ts.ASSIGN, ts.NOP, memberExprNode, pn); } @@ -272,12 +240,6 @@ public class Parser { // Add EOL but only if function is not part of expression, in which // case it gets SEMI + EOL from Statement. if (!isExpr) { - if (memberExprNode != null) { - // Add ';' to make 'function x.f(){}' and 'x.f = function(){}' - // to print the same strings when decompiling - sourceAdd((char) ts.SEMI); - } - sourceAdd((char) ts.EOL); wellTerminated(ts, ts.FUNCTION); } @@ -299,10 +261,8 @@ public class Parser { JavaScriptException { Object pn; mustMatchToken(ts, ts.LP, "msg.no.paren.cond"); - sourceAdd((char) ts.LP); pn = expr(ts, false); mustMatchToken(ts, ts.GWT, "msg.no.paren.after.cond"); - sourceAdd((char) ts.GWT); // there's a check here in jsparse.c that corrects = to == @@ -390,22 +350,13 @@ public class Parser { case TokenStream.IF: { skipsemi = true; - sourceAdd((char) ts.IF); int lineno = ts.getLineno(); Object cond = condition(ts); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); Object ifTrue = statement(ts); Object ifFalse = null; if (ts.matchToken(ts.ELSE)) { - sourceAdd((char) ts.RC); - sourceAdd((char) ts.ELSE); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); ifFalse = statement(ts); } - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); pn = nf.createIf(cond, ifTrue, ifFalse, lineno); break; } @@ -413,35 +364,24 @@ public class Parser { case TokenStream.SWITCH: { skipsemi = true; - sourceAdd((char) ts.SWITCH); pn = nf.createSwitch(ts.getLineno()); Object cur_case = null; // to kill warning Object case_statements; mustMatchToken(ts, ts.LP, "msg.no.paren.switch"); - sourceAdd((char) ts.LP); nf.addChildToBack(pn, expr(ts, false)); mustMatchToken(ts, ts.GWT, "msg.no.paren.after.switch"); - sourceAdd((char) ts.GWT); mustMatchToken(ts, ts.LC, "msg.no.brace.switch"); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); while ((tt = ts.getToken()) != ts.RC && tt != ts.EOF) { switch (tt) { case TokenStream.CASE: - sourceAdd((char) ts.CASE); cur_case = nf.createUnary(ts.CASE, expr(ts, false)); - sourceAdd((char) ts.COLON); - sourceAdd((char) ts.EOL); break; case TokenStream.DEFAULT: cur_case = nf.createLeaf(ts.DEFAULT); - sourceAdd((char) ts.DEFAULT); - sourceAdd((char) ts.COLON); - sourceAdd((char) ts.EOL); // XXX check that there isn't more than one default break; @@ -463,22 +403,15 @@ public class Parser { nf.addChildToBack(pn, cur_case); } - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); break; } case TokenStream.WHILE: { skipsemi = true; - sourceAdd((char) ts.WHILE); int lineno = ts.getLineno(); Object cond = condition(ts); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); Object body = statement(ts); - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); pn = nf.createWhile(cond, body, lineno); break; @@ -486,17 +419,11 @@ public class Parser { } case TokenStream.DO: { - sourceAdd((char) ts.DO); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); - int lineno = ts.getLineno(); Object body = statement(ts); - sourceAdd((char) ts.RC); mustMatchToken(ts, ts.WHILE, "msg.no.while.do"); - sourceAdd((char) ts.WHILE); Object cond = condition(ts); pn = nf.createDoWhile(body, cond, lineno); @@ -506,7 +433,6 @@ public class Parser { case TokenStream.FOR: { skipsemi = true; - sourceAdd((char) ts.FOR); int lineno = ts.getLineno(); Object init; // Node init is also foo in 'foo in Object' @@ -515,7 +441,6 @@ public class Parser { Object body; mustMatchToken(ts, ts.LP, "msg.no.paren.for"); - sourceAdd((char) ts.LP); tt = ts.peekToken(); if (tt == ts.SEMI) { init = nf.createLeaf(ts.VOID); @@ -532,12 +457,10 @@ public class Parser { tt = ts.peekToken(); if (tt == ts.RELOP && ts.getOp() == ts.IN) { ts.matchToken(ts.RELOP); - sourceAdd((char) ts.IN); // 'cond' is the object over which we're iterating cond = expr(ts, false); } else { // ordinary for loop mustMatchToken(ts, ts.SEMI, "msg.no.semi.for"); - sourceAdd((char) ts.SEMI); if (ts.peekToken() == ts.SEMI) { // no loop condition cond = nf.createLeaf(ts.VOID); @@ -546,7 +469,6 @@ public class Parser { } mustMatchToken(ts, ts.SEMI, "msg.no.semi.for.cond"); - sourceAdd((char) ts.SEMI); if (ts.peekToken() == ts.GWT) { incr = nf.createLeaf(ts.VOID); } else { @@ -555,12 +477,7 @@ public class Parser { } mustMatchToken(ts, ts.GWT, "msg.no.paren.for.ctrl"); - sourceAdd((char) ts.GWT); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); body = statement(ts); - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); if (incr == null) { // cond could be null if 'in obj' got eaten by the init node. @@ -579,12 +496,7 @@ public class Parser { Object finallyblock = null; skipsemi = true; - sourceAdd((char) ts.TRY); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); tryblock = statement(ts); - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); catchblocks = nf.createLeaf(TokenStream.BLOCK); @@ -595,47 +507,32 @@ public class Parser { if (sawDefaultCatch) { reportError(ts, "msg.catch.unreachable"); } - sourceAdd((char) ts.CATCH); mustMatchToken(ts, ts.LP, "msg.no.paren.catch"); - sourceAdd((char) ts.LP); mustMatchToken(ts, ts.NAME, "msg.bad.catchcond"); String varName = ts.getString(); - sourceAddString(ts.NAME, varName); Object catchCond = null; if (ts.matchToken(ts.IF)) { - sourceAdd((char) ts.IF); catchCond = expr(ts, false); } else { sawDefaultCatch = true; } mustMatchToken(ts, ts.GWT, "msg.bad.catchcond"); - sourceAdd((char) ts.GWT); mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock"); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); nf.addChildToBack(catchblocks, nf.createCatch(varName, catchCond, statements(ts), ts.getLineno())); mustMatchToken(ts, ts.RC, "msg.no.brace.after.body"); - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); } } else if (peek != ts.FINALLY) { mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally"); } if (ts.matchToken(ts.FINALLY)) { - sourceAdd((char) ts.FINALLY); - - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); finallyblock = statement(ts); - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); } pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock, @@ -645,7 +542,6 @@ public class Parser { } case TokenStream.THROW: { int lineno = ts.getLineno(); - sourceAdd((char) ts.THROW); pn = nf.createThrow(expr(ts, false), lineno); if (lineno == ts.getLineno()) wellTerminated(ts, ts.ERROR); @@ -654,34 +550,21 @@ public class Parser { case TokenStream.BREAK: { int lineno = ts.getLineno(); - sourceAdd((char) ts.BREAK); - // matchLabel only matches if there is one String label = matchLabel(ts); - if (label != null) { - sourceAddString(ts.NAME, label); - } pn = nf.createBreak(label, lineno); break; } case TokenStream.CONTINUE: { int lineno = ts.getLineno(); - sourceAdd((char) ts.CONTINUE); - // matchLabel only matches if there is one String label = matchLabel(ts); - if (label != null) { - sourceAddString(ts.NAME, label); - } pn = nf.createContinue(label, lineno); break; } case TokenStream.DEBUGGER: { int lineno = ts.getLineno(); - - sourceAdd((char) ts.DEBUGGER); - pn = nf.createDebugger(lineno); break; } @@ -694,21 +577,11 @@ public class Parser { skipsemi = true; - sourceAdd((char) ts.WITH); int lineno = ts.getLineno(); mustMatchToken(ts, ts.LP, "msg.no.paren.with"); - sourceAdd((char) ts.LP); Object obj = expr(ts, false); mustMatchToken(ts, ts.GWT, "msg.no.paren.after.with"); - sourceAdd((char) ts.GWT); - sourceAdd((char) ts.LC); - sourceAdd((char) ts.EOL); - Object body = statement(ts); - - sourceAdd((char) ts.RC); - sourceAdd((char) ts.EOL); - pn = nf.createWith(obj, body, lineno); break; } @@ -722,9 +595,6 @@ public class Parser { case TokenStream.RETURN: { Object retExpr = null; int lineno = 0; - - sourceAdd((char) ts.RETURN); - // bail if we're not in a (toplevel) function if ((!insideFunction) && ((ts.flags & ts.TSF_FUNCTION) == 0)) { reportError(ts, "msg.bad.return"); @@ -796,8 +666,6 @@ public class Parser { // depend on decompiling lookahead to guess that that // last name was a label. - sourceAdd((char) ts.COLON); - sourceAdd((char) ts.EOL); return pn; } @@ -826,10 +694,6 @@ public class Parser { } } ts.matchToken(ts.SEMI); - if (!skipsemi) { - sourceAdd((char) ts.SEMI); - sourceAdd((char) ts.EOL); - } return pn; } @@ -837,21 +701,12 @@ public class Parser { private Object variables(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException { Object pn = nf.createVariables(ts.getLineno()); - boolean first = true; - - sourceAdd((char) ts.VAR); for (;;) { Object name; Object init; mustMatchToken(ts, ts.NAME, "msg.bad.var"); String s = ts.getString(); - - if (!first) - sourceAdd((char) ts.COMMA); - first = false; - - sourceAddString(ts.NAME, s); name = nf.createName(s); // omitted check for argument hiding @@ -860,9 +715,6 @@ public class Parser { if (ts.getOp() != ts.NOP) reportError(ts, "msg.bad.var.init"); - sourceAdd((char) ts.ASSIGN); - sourceAdd((char) ts.NOP); - init = assignExpr(ts, inForInit); nf.addChildToBack(name, init); } @@ -877,7 +729,6 @@ public class Parser { JavaScriptException { Object pn = assignExpr(ts, inForInit); while (ts.matchToken(ts.COMMA)) { - sourceAdd((char) ts.COMMA); pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, inForInit)); } return pn; @@ -889,8 +740,6 @@ public class Parser { if (ts.matchToken(ts.ASSIGN)) { // omitted: "invalid assignment left-hand side" check. - sourceAdd((char) ts.ASSIGN); - sourceAdd((char) ts.getOp()); pn = nf .createBinary(ts.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit)); } @@ -906,10 +755,8 @@ public class Parser { Object pn = orExpr(ts, inForInit); if (ts.matchToken(ts.HOOK)) { - sourceAdd((char) ts.HOOK); ifTrue = assignExpr(ts, false); mustMatchToken(ts, ts.COLON, "msg.no.colon.cond"); - sourceAdd((char) ts.COLON); ifFalse = assignExpr(ts, inForInit); return nf.createTernary(pn, ifTrue, ifFalse); } @@ -921,7 +768,6 @@ public class Parser { JavaScriptException { Object pn = andExpr(ts, inForInit); if (ts.matchToken(ts.OR)) { - sourceAdd((char) ts.OR); pn = nf.createBinary(ts.OR, pn, orExpr(ts, inForInit)); } @@ -932,7 +778,6 @@ public class Parser { JavaScriptException { Object pn = bitOrExpr(ts, inForInit); if (ts.matchToken(ts.AND)) { - sourceAdd((char) ts.AND); pn = nf.createBinary(ts.AND, pn, andExpr(ts, inForInit)); } @@ -943,7 +788,6 @@ public class Parser { throws IOException, JavaScriptException { Object pn = bitXorExpr(ts, inForInit); while (ts.matchToken(ts.BITOR)) { - sourceAdd((char) ts.BITOR); pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, inForInit)); } return pn; @@ -953,7 +797,6 @@ public class Parser { throws IOException, JavaScriptException { Object pn = bitAndExpr(ts, inForInit); while (ts.matchToken(ts.BITXOR)) { - sourceAdd((char) ts.BITXOR); pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, inForInit)); } return pn; @@ -963,7 +806,6 @@ public class Parser { throws IOException, JavaScriptException { Object pn = eqExpr(ts, inForInit); while (ts.matchToken(ts.BITAND)) { - sourceAdd((char) ts.BITAND); pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, inForInit)); } return pn; @@ -973,8 +815,6 @@ public class Parser { JavaScriptException { Object pn = relExpr(ts, inForInit); while (ts.matchToken(ts.EQOP)) { - sourceAdd((char) ts.EQOP); - sourceAdd((char) ts.getOp()); pn = nf.createBinary(ts.EQOP, ts.getOp(), pn, relExpr(ts, inForInit)); } return pn; @@ -989,8 +829,7 @@ public class Parser { ts.ungetToken(ts.RELOP); break; } - sourceAdd((char) ts.RELOP); - sourceAdd((char) op); + pn = nf.createBinary(ts.RELOP, op, pn, shiftExpr(ts)); } return pn; @@ -1000,8 +839,6 @@ public class Parser { JavaScriptException { Object pn = addExpr(ts); while (ts.matchToken(ts.SHOP)) { - sourceAdd((char) ts.SHOP); - sourceAdd((char) ts.getOp()); pn = nf.createBinary(ts.SHOP, ts.getOp(), pn, addExpr(ts)); } return pn; @@ -1013,7 +850,6 @@ public class Parser { Object pn = mulExpr(ts); while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) { - sourceAdd((char) tt); // flushNewLines pn = nf.createBinary(tt, pn, mulExpr(ts)); } @@ -1030,7 +866,6 @@ public class Parser { while ((tt = ts.peekToken()) == ts.MUL || tt == ts.DIV || tt == ts.MOD) { tt = ts.getToken(); - sourceAdd((char) tt); pn = nf.createBinary(tt, pn, unaryExpr(ts)); } @@ -1047,23 +882,17 @@ public class Parser { switch (tt) { case TokenStream.UNARYOP: - sourceAdd((char) ts.UNARYOP); - sourceAdd((char) ts.getOp()); return nf.createUnary(ts.UNARYOP, ts.getOp(), unaryExpr(ts)); case TokenStream.ADD: case TokenStream.SUB: - sourceAdd((char) ts.UNARYOP); - sourceAdd((char) tt); return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts)); case TokenStream.INC: case TokenStream.DEC: - sourceAdd((char) tt); return nf.createUnary(tt, ts.PRE, memberExpr(ts, true)); case TokenStream.DELPROP: - sourceAdd((char) ts.DELPROP); return nf.createUnary(ts.DELPROP, unaryExpr(ts)); case TokenStream.ERROR: @@ -1087,7 +916,6 @@ public class Parser { if (((peeked = ts.peekToken()) == ts.INC || peeked == ts.DEC) && ts.getLineno() == lineno) { int pf = ts.getToken(); - sourceAdd((char) pf); return nf.createUnary(pf, ts.POST, pn); } return pn; @@ -1103,17 +931,12 @@ public class Parser { matched = ts.matchToken(ts.GWT); ts.flags &= ~ts.TSF_REGEXP; if (!matched) { - boolean first = true; do { - if (!first) - sourceAdd((char) ts.COMMA); - first = false; nf.addChildToBack(listNode, assignExpr(ts, false)); } while (ts.matchToken(ts.COMMA)); mustMatchToken(ts, ts.GWT, "msg.no.paren.arg"); } - sourceAdd((char) ts.GWT); return listNode; } @@ -1130,14 +953,12 @@ public class Parser { if (tt == ts.NEW) { /* Eat the NEW token. */ ts.getToken(); - sourceAdd((char) ts.NEW); /* Make a NEW node to append to. */ pn = nf.createLeaf(ts.NEW); nf.addChildToBack(pn, memberExpr(ts, false)); if (ts.matchToken(ts.LP)) { - sourceAdd((char) ts.LP); /* Add the arguments to pn, if any are supplied. */ pn = argumentList(ts, pn); } @@ -1170,10 +991,8 @@ public class Parser { int tt; while ((tt = ts.getToken()) > ts.EOF) { if (tt == ts.DOT) { - sourceAdd((char) ts.DOT); mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot"); String s = ts.getString(); - sourceAddString(ts.NAME, s); pn = nf.createBinary(ts.DOT, pn, nf.createName(ts.getString())); /* * pn = nf.createBinary(ts.DOT, pn, memberExpr(ts)) is the version in @@ -1182,17 +1001,13 @@ public class Parser { */ lastExprEndLine = ts.getLineno(); } else if (tt == ts.LB) { - sourceAdd((char) ts.LB); pn = nf.createBinary(ts.LB, pn, expr(ts, false)); mustMatchToken(ts, ts.RB, "msg.no.bracket.index"); - sourceAdd((char) ts.RB); lastExprEndLine = ts.getLineno(); } else if (allowCallSyntax && tt == ts.LP) { /* make a call node */ - pn = nf.createUnary(ts.CALL, pn); - sourceAdd((char) ts.LP); /* Add the arguments to pn, if any are supplied. */ pn = argumentList(ts, pn); @@ -1222,7 +1037,6 @@ public class Parser { return function(ts, true); case TokenStream.LB: { - sourceAdd((char) ts.LB); pn = nf.createLeaf(ts.ARRAYLIT); ts.flags |= ts.TSF_REGEXP; @@ -1230,17 +1044,11 @@ public class Parser { ts.flags &= ~ts.TSF_REGEXP; if (!matched) { - boolean first = true; do { ts.flags |= ts.TSF_REGEXP; tt = ts.peekToken(); ts.flags &= ~ts.TSF_REGEXP; - if (!first) - sourceAdd((char) ts.COMMA); - else - first = false; - if (tt == ts.RB) { // to fix [,,,].length behavior... break; } @@ -1254,42 +1062,31 @@ public class Parser { } while (ts.matchToken(ts.COMMA)); mustMatchToken(ts, ts.RB, "msg.no.bracket.arg"); } - sourceAdd((char) ts.RB); + return nf.createArrayLiteral(pn); } case TokenStream.LC: { pn = nf.createLeaf(ts.OBJLIT); - sourceAdd((char) ts.LC); if (!ts.matchToken(ts.RC)) { - boolean first = true; commaloop : do { Object property; - if (!first) - sourceAdd((char) ts.COMMA); - else - first = false; - tt = ts.getToken(); switch (tt) { // map NAMEs to STRINGs in object literal context. case TokenStream.NAME: case TokenStream.STRING: - String s = ts.getString(); - sourceAddString(ts.NAME, s); property = nf.createString(ts.getString()); break; case TokenStream.NUMBER_INT: int n = (int) ts.getNumber(); - sourceAddNumber(n); property = nf.createNumber(n); break; case TokenStream.NUMBER: double d = ts.getNumber(); - sourceAddNumber(d); property = nf.createNumber(d); break; case TokenStream.RC: @@ -1304,7 +1101,6 @@ public class Parser { // OBJLIT is used as ':' in object literal for // decompilation to solve spacing ambiguity. - sourceAdd((char) ts.OBJLIT); nf.addChildToBack(pn, property); nf.addChildToBack(pn, assignExpr(ts, false)); @@ -1312,7 +1108,6 @@ public class Parser { mustMatchToken(ts, ts.RC, "msg.no.brace.prop"); } - sourceAdd((char) ts.RC); return nf.createObjectLiteral(pn); } @@ -1324,43 +1119,34 @@ public class Parser { * the structure of the parse tree? also TOK_LP is already overloaded (I * think) in the C IR as 'function call.' */ - sourceAdd((char) ts.LP); pn = expr(ts, false); - sourceAdd((char) ts.GWT); mustMatchToken(ts, ts.GWT, "msg.no.paren"); return pn; case TokenStream.NAME: String name = ts.getString(); - sourceAddString(ts.NAME, name); return nf.createName(name); case TokenStream.NUMBER_INT: int n = (int)ts.getNumber(); - sourceAddNumber(n); return nf.createNumber(n); case TokenStream.NUMBER: double d = ts.getNumber(); - sourceAddNumber(d); return nf.createNumber(d); case TokenStream.STRING: String s = ts.getString(); - sourceAddString(ts.STRING, s); return nf.createString(s); case TokenStream.REGEXP: { String flags = ts.regExpFlags; ts.regExpFlags = null; String re = ts.getString(); - sourceAddString(ts.REGEXP, '/' + re + '/' + flags); return nf.createRegExp(re, flags); } case TokenStream.PRIMARY: - sourceAdd((char) ts.PRIMARY); - sourceAdd((char) ts.getOp()); return nf.createLeaf(ts.PRIMARY, ts.getOp()); case TokenStream.RESERVED: @@ -1379,139 +1165,11 @@ public class Parser { return null; // should never reach here } - /** - * The following methods save decompilation information about the source. - * Source information is returned from the parser as a String associated with - * function nodes and with the toplevel script. When saved in the constant - * pool of a class, this string will be UTF-8 encoded, and token values will - * occupy a single byte. - * - * Source is saved (mostly) as token numbers. The tokens saved pretty much - * correspond to the token stream of a 'canonical' representation of the input - * program, as directed by the parser. (There were a few cases where tokens - * could have been left out where decompiler could easily reconstruct them, - * but I left them in for clarity). (I also looked adding source collection to - * TokenStream instead, where I could have limited the changes to a few lines - * in getToken... but this wouldn't have saved any space in the resulting - * source representation, and would have meant that I'd have to duplicate - * parser logic in the decompiler to disambiguate situations where newlines - * are important.) NativeFunction.decompile expands the tokens back into their - * string representations, using simple lookahead to correct spacing and - * indentation. - * - * Token types with associated ops (ASSIGN, SHOP, PRIMARY, etc.) are saved as - * two-token pairs. Number tokens are stored inline, as a NUMBER token, a - * character representing the type, and either 1 or 4 characters representing - * the bit-encoding of the number. String types NAME, STRING and OBJECT are - * currently stored as a token type, followed by a character giving the length - * of the string (assumed to be less than 2^16), followed by the characters of - * the string inlined into the source string. Changing this to some reference - * to to the string in the compiled class' constant pool would probably save a - * lot of space... but would require some method of deriving the final - * constant pool entry from information available at parse time. - * - * Nested functions need a similar mechanism... fortunately the nested - * functions for a given function are generated in source order. Nested - * functions are encoded as FUNCTION followed by a function number (encoded as - * a character), which is enough information to find the proper generated - * NativeFunction instance. - * - */ - private void sourceAdd(char c) { - if (sourceTop == sourceBuffer.length) { - increaseSourceCapacity(sourceTop + 1); - } - sourceBuffer[sourceTop] = c; - ++sourceTop; - } - - private void sourceAddString(int type, String str) { - int L = str.length(); - // java string length < 2^16? - if (Context.check && L > Character.MAX_VALUE) - Context.codeBug(); - - if (sourceTop + L + 2 > sourceBuffer.length) { - increaseSourceCapacity(sourceTop + L + 2); - } - sourceAdd((char) type); - sourceAdd((char) L); - str.getChars(0, L, sourceBuffer, sourceTop); - sourceTop += L; - } - - private void sourceAddNumber(double n) { - sourceAdd((char) TokenStream.NUMBER); - - /* - * encode the number in the source stream. Save as NUMBER type (char | char - * char char char) where type is 'D' - double, 'S' - short, 'J' - long. - * - * We need to retain float vs. integer type info to keep the behavior of - * liveconnect type-guessing the same after decompilation. (Liveconnect - * tries to present 1.0 to Java as a float/double) OPT: This is no longer - * true. We could compress the format. - * - * This may not be the most space-efficient encoding; the chars created - * below may take up to 3 bytes in constant pool UTF-8 encoding, so a Double - * could take up to 12 bytes. - */ - - long lbits = Double.doubleToLongBits(n); - sourceAdd('D'); - sourceAdd((char) (lbits >> 48)); - sourceAdd((char) (lbits >> 32)); - sourceAdd((char) (lbits >> 16)); - sourceAdd((char) lbits); - } - - private void sourceAddNumber(int n) { - sourceAdd((char) TokenStream.NUMBER_INT); - - // we can ignore negative values, bc they're already prefixed - // by UNARYOP SUB - if (Context.check && (long) n < 0) - Context.codeBug(); - - // will it fit in a char? - // this gives a short encoding for integer values up to 2^16. - if ((long) n <= Character.MAX_VALUE) { - sourceAdd('S'); - sourceAdd((char) (long) n); - } else { // Integral, but won't fit in a char. Store as a long. - sourceAdd('J'); - sourceAdd((char) ((long) n >> 48)); - sourceAdd((char) ((long) n >> 32)); - sourceAdd((char) ((long) n >> 16)); - sourceAdd((char) (long) n); - } - } - - private void increaseSourceCapacity(int minimalCapacity) { - // Call this only when capacity increase is must - if (Context.check && minimalCapacity <= sourceBuffer.length) - Context.codeBug(); - int newCapacity = sourceBuffer.length * 2; - if (newCapacity < minimalCapacity) { - newCapacity = minimalCapacity; - } - char[] tmp = new char[newCapacity]; - System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop); - sourceBuffer = tmp; - } - - private String sourceToString(int offset) { - if (Context.check && (offset < 0 || sourceTop < offset)) - Context.codeBug(); - return new String(sourceBuffer, offset, sourceTop - offset); - } - private int lastExprEndLine; // Hack to handle function expr termination. private IRFactory nf; private ErrorReporter er; private boolean ok; // Did the parse encounter an error? - private char[] sourceBuffer = new char[128]; private int sourceTop; private int functionNumber; private final boolean insideFunction;