JS parser: removed unused decompilation info
This commit is contained in:
@@ -127,7 +127,7 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object pn = nf.createScript(tempBlock, ts.getSourceName(), baseLineno, ts
|
Object pn = nf.createScript(tempBlock, ts.getSourceName(), baseLineno, ts
|
||||||
.getLineno(), sourceToString(0));
|
.getLineno(), null);
|
||||||
((Node) pn).setIsSyntheticBlock(true);
|
((Node) pn).setIsSyntheticBlock(true);
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,6 @@ public class Parser {
|
|||||||
Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) {
|
Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)) {
|
||||||
// Extension to ECMA: if 'function <name>' does not follow
|
// Extension to ECMA: if 'function <name>' does not follow
|
||||||
// by '(', assume <name> starts memberExpr
|
// by '(', assume <name> starts memberExpr
|
||||||
sourceAddString(ts.NAME, name);
|
|
||||||
Object memberExprHead = nf.createName(name);
|
Object memberExprHead = nf.createName(name);
|
||||||
name = null;
|
name = null;
|
||||||
memberExprNode = memberExprTail(ts, false, memberExprHead);
|
memberExprNode = memberExprTail(ts, false, memberExprHead);
|
||||||
@@ -200,16 +199,6 @@ public class Parser {
|
|||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.parms");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.parms");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memberExprNode != null) {
|
|
||||||
// transform 'function' <memberExpr> to <memberExpr> = 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;
|
++functionNumber;
|
||||||
|
|
||||||
// Save current source top to restore it on exit not to include
|
// Save current source top to restore it on exit not to include
|
||||||
@@ -218,53 +207,32 @@ public class Parser {
|
|||||||
int savedFunctionNumber = functionNumber;
|
int savedFunctionNumber = functionNumber;
|
||||||
Object args;
|
Object args;
|
||||||
Object body;
|
Object body;
|
||||||
String source;
|
|
||||||
try {
|
try {
|
||||||
functionNumber = 0;
|
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);
|
args = nf.createLeaf(ts.LP);
|
||||||
|
|
||||||
if (!ts.matchToken(ts.GWT)) {
|
if (!ts.matchToken(ts.GWT)) {
|
||||||
boolean first = true;
|
|
||||||
do {
|
do {
|
||||||
if (!first)
|
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
first = false;
|
|
||||||
mustMatchToken(ts, ts.NAME, "msg.no.parm");
|
mustMatchToken(ts, ts.NAME, "msg.no.parm");
|
||||||
String s = ts.getString();
|
String s = ts.getString();
|
||||||
nf.addChildToBack(args, nf.createName(s));
|
nf.addChildToBack(args, nf.createName(s));
|
||||||
|
|
||||||
sourceAddString(ts.NAME, s);
|
|
||||||
} while (ts.matchToken(ts.COMMA));
|
} while (ts.matchToken(ts.COMMA));
|
||||||
|
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.parms");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.parms");
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
|
|
||||||
mustMatchToken(ts, ts.LC, "msg.no.brace.body");
|
mustMatchToken(ts, ts.LC, "msg.no.brace.body");
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
body = parseFunctionBody(ts);
|
body = parseFunctionBody(ts);
|
||||||
mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");
|
mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
// skip the last EOL so nested functions work...
|
// skip the last EOL so nested functions work...
|
||||||
|
|
||||||
// name might be null;
|
|
||||||
source = sourceToString(savedSourceTop);
|
|
||||||
} finally {
|
} finally {
|
||||||
sourceTop = savedSourceTop;
|
sourceTop = savedSourceTop;
|
||||||
functionNumber = savedFunctionNumber;
|
functionNumber = savedFunctionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object pn = nf.createFunction(name, args, body, ts.getSourceName(),
|
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) {
|
if (memberExprNode != null) {
|
||||||
pn = nf.createBinary(ts.ASSIGN, ts.NOP, memberExprNode, pn);
|
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
|
// Add EOL but only if function is not part of expression, in which
|
||||||
// case it gets SEMI + EOL from Statement.
|
// case it gets SEMI + EOL from Statement.
|
||||||
if (!isExpr) {
|
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);
|
wellTerminated(ts, ts.FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,10 +261,8 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn;
|
Object pn;
|
||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.cond");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.cond");
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
pn = expr(ts, false);
|
pn = expr(ts, false);
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.cond");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.cond");
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
|
|
||||||
// there's a check here in jsparse.c that corrects = to ==
|
// there's a check here in jsparse.c that corrects = to ==
|
||||||
|
|
||||||
@@ -390,22 +350,13 @@ public class Parser {
|
|||||||
case TokenStream.IF: {
|
case TokenStream.IF: {
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
|
|
||||||
sourceAdd((char) ts.IF);
|
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
Object cond = condition(ts);
|
Object cond = condition(ts);
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
Object ifTrue = statement(ts);
|
Object ifTrue = statement(ts);
|
||||||
Object ifFalse = null;
|
Object ifFalse = null;
|
||||||
if (ts.matchToken(ts.ELSE)) {
|
if (ts.matchToken(ts.ELSE)) {
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.ELSE);
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
ifFalse = statement(ts);
|
ifFalse = statement(ts);
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
|
pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -413,35 +364,24 @@ public class Parser {
|
|||||||
case TokenStream.SWITCH: {
|
case TokenStream.SWITCH: {
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
|
|
||||||
sourceAdd((char) ts.SWITCH);
|
|
||||||
pn = nf.createSwitch(ts.getLineno());
|
pn = nf.createSwitch(ts.getLineno());
|
||||||
|
|
||||||
Object cur_case = null; // to kill warning
|
Object cur_case = null; // to kill warning
|
||||||
Object case_statements;
|
Object case_statements;
|
||||||
|
|
||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.switch");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.switch");
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
nf.addChildToBack(pn, expr(ts, false));
|
nf.addChildToBack(pn, expr(ts, false));
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.switch");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.switch");
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
mustMatchToken(ts, ts.LC, "msg.no.brace.switch");
|
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) {
|
while ((tt = ts.getToken()) != ts.RC && tt != ts.EOF) {
|
||||||
switch (tt) {
|
switch (tt) {
|
||||||
case TokenStream.CASE:
|
case TokenStream.CASE:
|
||||||
sourceAdd((char) ts.CASE);
|
|
||||||
cur_case = nf.createUnary(ts.CASE, expr(ts, false));
|
cur_case = nf.createUnary(ts.CASE, expr(ts, false));
|
||||||
sourceAdd((char) ts.COLON);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TokenStream.DEFAULT:
|
case TokenStream.DEFAULT:
|
||||||
cur_case = nf.createLeaf(ts.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
|
// XXX check that there isn't more than one default
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -463,22 +403,15 @@ public class Parser {
|
|||||||
|
|
||||||
nf.addChildToBack(pn, cur_case);
|
nf.addChildToBack(pn, cur_case);
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenStream.WHILE: {
|
case TokenStream.WHILE: {
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
|
|
||||||
sourceAdd((char) ts.WHILE);
|
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
Object cond = condition(ts);
|
Object cond = condition(ts);
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
Object body = statement(ts);
|
Object body = statement(ts);
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
pn = nf.createWhile(cond, body, lineno);
|
pn = nf.createWhile(cond, body, lineno);
|
||||||
break;
|
break;
|
||||||
@@ -486,17 +419,11 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TokenStream.DO: {
|
case TokenStream.DO: {
|
||||||
sourceAdd((char) ts.DO);
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
|
|
||||||
Object body = statement(ts);
|
Object body = statement(ts);
|
||||||
|
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
mustMatchToken(ts, ts.WHILE, "msg.no.while.do");
|
mustMatchToken(ts, ts.WHILE, "msg.no.while.do");
|
||||||
sourceAdd((char) ts.WHILE);
|
|
||||||
Object cond = condition(ts);
|
Object cond = condition(ts);
|
||||||
|
|
||||||
pn = nf.createDoWhile(body, cond, lineno);
|
pn = nf.createDoWhile(body, cond, lineno);
|
||||||
@@ -506,7 +433,6 @@ public class Parser {
|
|||||||
case TokenStream.FOR: {
|
case TokenStream.FOR: {
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
|
|
||||||
sourceAdd((char) ts.FOR);
|
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
|
|
||||||
Object init; // Node init is also foo in 'foo in Object'
|
Object init; // Node init is also foo in 'foo in Object'
|
||||||
@@ -515,7 +441,6 @@ public class Parser {
|
|||||||
Object body;
|
Object body;
|
||||||
|
|
||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.for");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.for");
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
tt = ts.peekToken();
|
tt = ts.peekToken();
|
||||||
if (tt == ts.SEMI) {
|
if (tt == ts.SEMI) {
|
||||||
init = nf.createLeaf(ts.VOID);
|
init = nf.createLeaf(ts.VOID);
|
||||||
@@ -532,12 +457,10 @@ public class Parser {
|
|||||||
tt = ts.peekToken();
|
tt = ts.peekToken();
|
||||||
if (tt == ts.RELOP && ts.getOp() == ts.IN) {
|
if (tt == ts.RELOP && ts.getOp() == ts.IN) {
|
||||||
ts.matchToken(ts.RELOP);
|
ts.matchToken(ts.RELOP);
|
||||||
sourceAdd((char) ts.IN);
|
|
||||||
// 'cond' is the object over which we're iterating
|
// 'cond' is the object over which we're iterating
|
||||||
cond = expr(ts, false);
|
cond = expr(ts, false);
|
||||||
} else { // ordinary for loop
|
} else { // ordinary for loop
|
||||||
mustMatchToken(ts, ts.SEMI, "msg.no.semi.for");
|
mustMatchToken(ts, ts.SEMI, "msg.no.semi.for");
|
||||||
sourceAdd((char) ts.SEMI);
|
|
||||||
if (ts.peekToken() == ts.SEMI) {
|
if (ts.peekToken() == ts.SEMI) {
|
||||||
// no loop condition
|
// no loop condition
|
||||||
cond = nf.createLeaf(ts.VOID);
|
cond = nf.createLeaf(ts.VOID);
|
||||||
@@ -546,7 +469,6 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mustMatchToken(ts, ts.SEMI, "msg.no.semi.for.cond");
|
mustMatchToken(ts, ts.SEMI, "msg.no.semi.for.cond");
|
||||||
sourceAdd((char) ts.SEMI);
|
|
||||||
if (ts.peekToken() == ts.GWT) {
|
if (ts.peekToken() == ts.GWT) {
|
||||||
incr = nf.createLeaf(ts.VOID);
|
incr = nf.createLeaf(ts.VOID);
|
||||||
} else {
|
} else {
|
||||||
@@ -555,12 +477,7 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.for.ctrl");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren.for.ctrl");
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
body = statement(ts);
|
body = statement(ts);
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
if (incr == null) {
|
if (incr == null) {
|
||||||
// cond could be null if 'in obj' got eaten by the init node.
|
// cond could be null if 'in obj' got eaten by the init node.
|
||||||
@@ -579,12 +496,7 @@ public class Parser {
|
|||||||
Object finallyblock = null;
|
Object finallyblock = null;
|
||||||
|
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
sourceAdd((char) ts.TRY);
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
tryblock = statement(ts);
|
tryblock = statement(ts);
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
catchblocks = nf.createLeaf(TokenStream.BLOCK);
|
catchblocks = nf.createLeaf(TokenStream.BLOCK);
|
||||||
|
|
||||||
@@ -595,47 +507,32 @@ public class Parser {
|
|||||||
if (sawDefaultCatch) {
|
if (sawDefaultCatch) {
|
||||||
reportError(ts, "msg.catch.unreachable");
|
reportError(ts, "msg.catch.unreachable");
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.CATCH);
|
|
||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.catch");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.catch");
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
|
|
||||||
mustMatchToken(ts, ts.NAME, "msg.bad.catchcond");
|
mustMatchToken(ts, ts.NAME, "msg.bad.catchcond");
|
||||||
String varName = ts.getString();
|
String varName = ts.getString();
|
||||||
sourceAddString(ts.NAME, varName);
|
|
||||||
|
|
||||||
Object catchCond = null;
|
Object catchCond = null;
|
||||||
if (ts.matchToken(ts.IF)) {
|
if (ts.matchToken(ts.IF)) {
|
||||||
sourceAdd((char) ts.IF);
|
|
||||||
catchCond = expr(ts, false);
|
catchCond = expr(ts, false);
|
||||||
} else {
|
} else {
|
||||||
sawDefaultCatch = true;
|
sawDefaultCatch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mustMatchToken(ts, ts.GWT, "msg.bad.catchcond");
|
mustMatchToken(ts, ts.GWT, "msg.bad.catchcond");
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock");
|
mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock");
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
nf.addChildToBack(catchblocks, nf.createCatch(varName, catchCond,
|
nf.addChildToBack(catchblocks, nf.createCatch(varName, catchCond,
|
||||||
statements(ts), ts.getLineno()));
|
statements(ts), ts.getLineno()));
|
||||||
|
|
||||||
mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");
|
mustMatchToken(ts, ts.RC, "msg.no.brace.after.body");
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
}
|
}
|
||||||
} else if (peek != ts.FINALLY) {
|
} else if (peek != ts.FINALLY) {
|
||||||
mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally");
|
mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts.matchToken(ts.FINALLY)) {
|
if (ts.matchToken(ts.FINALLY)) {
|
||||||
sourceAdd((char) ts.FINALLY);
|
|
||||||
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
finallyblock = statement(ts);
|
finallyblock = statement(ts);
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock,
|
pn = nf.createTryCatchFinally(tryblock, catchblocks, finallyblock,
|
||||||
@@ -645,7 +542,6 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
case TokenStream.THROW: {
|
case TokenStream.THROW: {
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
sourceAdd((char) ts.THROW);
|
|
||||||
pn = nf.createThrow(expr(ts, false), lineno);
|
pn = nf.createThrow(expr(ts, false), lineno);
|
||||||
if (lineno == ts.getLineno())
|
if (lineno == ts.getLineno())
|
||||||
wellTerminated(ts, ts.ERROR);
|
wellTerminated(ts, ts.ERROR);
|
||||||
@@ -654,34 +550,21 @@ public class Parser {
|
|||||||
case TokenStream.BREAK: {
|
case TokenStream.BREAK: {
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
|
|
||||||
sourceAdd((char) ts.BREAK);
|
|
||||||
|
|
||||||
// matchLabel only matches if there is one
|
// matchLabel only matches if there is one
|
||||||
String label = matchLabel(ts);
|
String label = matchLabel(ts);
|
||||||
if (label != null) {
|
|
||||||
sourceAddString(ts.NAME, label);
|
|
||||||
}
|
|
||||||
pn = nf.createBreak(label, lineno);
|
pn = nf.createBreak(label, lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TokenStream.CONTINUE: {
|
case TokenStream.CONTINUE: {
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
|
|
||||||
sourceAdd((char) ts.CONTINUE);
|
|
||||||
|
|
||||||
// matchLabel only matches if there is one
|
// matchLabel only matches if there is one
|
||||||
String label = matchLabel(ts);
|
String label = matchLabel(ts);
|
||||||
if (label != null) {
|
|
||||||
sourceAddString(ts.NAME, label);
|
|
||||||
}
|
|
||||||
pn = nf.createContinue(label, lineno);
|
pn = nf.createContinue(label, lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TokenStream.DEBUGGER: {
|
case TokenStream.DEBUGGER: {
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
|
|
||||||
sourceAdd((char) ts.DEBUGGER);
|
|
||||||
|
|
||||||
pn = nf.createDebugger(lineno);
|
pn = nf.createDebugger(lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -694,21 +577,11 @@ public class Parser {
|
|||||||
|
|
||||||
skipsemi = true;
|
skipsemi = true;
|
||||||
|
|
||||||
sourceAdd((char) ts.WITH);
|
|
||||||
int lineno = ts.getLineno();
|
int lineno = ts.getLineno();
|
||||||
mustMatchToken(ts, ts.LP, "msg.no.paren.with");
|
mustMatchToken(ts, ts.LP, "msg.no.paren.with");
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
Object obj = expr(ts, false);
|
Object obj = expr(ts, false);
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.with");
|
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);
|
Object body = statement(ts);
|
||||||
|
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
|
|
||||||
pn = nf.createWith(obj, body, lineno);
|
pn = nf.createWith(obj, body, lineno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -722,9 +595,6 @@ public class Parser {
|
|||||||
case TokenStream.RETURN: {
|
case TokenStream.RETURN: {
|
||||||
Object retExpr = null;
|
Object retExpr = null;
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
|
|
||||||
sourceAdd((char) ts.RETURN);
|
|
||||||
|
|
||||||
// bail if we're not in a (toplevel) function
|
// bail if we're not in a (toplevel) function
|
||||||
if ((!insideFunction) && ((ts.flags & ts.TSF_FUNCTION) == 0)) {
|
if ((!insideFunction) && ((ts.flags & ts.TSF_FUNCTION) == 0)) {
|
||||||
reportError(ts, "msg.bad.return");
|
reportError(ts, "msg.bad.return");
|
||||||
@@ -796,8 +666,6 @@ public class Parser {
|
|||||||
|
|
||||||
// depend on decompiling lookahead to guess that that
|
// depend on decompiling lookahead to guess that that
|
||||||
// last name was a label.
|
// last name was a label.
|
||||||
sourceAdd((char) ts.COLON);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,10 +694,6 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ts.matchToken(ts.SEMI);
|
ts.matchToken(ts.SEMI);
|
||||||
if (!skipsemi) {
|
|
||||||
sourceAdd((char) ts.SEMI);
|
|
||||||
sourceAdd((char) ts.EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
@@ -837,21 +701,12 @@ public class Parser {
|
|||||||
private Object variables(TokenStream ts, boolean inForInit)
|
private Object variables(TokenStream ts, boolean inForInit)
|
||||||
throws IOException, JavaScriptException {
|
throws IOException, JavaScriptException {
|
||||||
Object pn = nf.createVariables(ts.getLineno());
|
Object pn = nf.createVariables(ts.getLineno());
|
||||||
boolean first = true;
|
|
||||||
|
|
||||||
sourceAdd((char) ts.VAR);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Object name;
|
Object name;
|
||||||
Object init;
|
Object init;
|
||||||
mustMatchToken(ts, ts.NAME, "msg.bad.var");
|
mustMatchToken(ts, ts.NAME, "msg.bad.var");
|
||||||
String s = ts.getString();
|
String s = ts.getString();
|
||||||
|
|
||||||
if (!first)
|
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
sourceAddString(ts.NAME, s);
|
|
||||||
name = nf.createName(s);
|
name = nf.createName(s);
|
||||||
|
|
||||||
// omitted check for argument hiding
|
// omitted check for argument hiding
|
||||||
@@ -860,9 +715,6 @@ public class Parser {
|
|||||||
if (ts.getOp() != ts.NOP)
|
if (ts.getOp() != ts.NOP)
|
||||||
reportError(ts, "msg.bad.var.init");
|
reportError(ts, "msg.bad.var.init");
|
||||||
|
|
||||||
sourceAdd((char) ts.ASSIGN);
|
|
||||||
sourceAdd((char) ts.NOP);
|
|
||||||
|
|
||||||
init = assignExpr(ts, inForInit);
|
init = assignExpr(ts, inForInit);
|
||||||
nf.addChildToBack(name, init);
|
nf.addChildToBack(name, init);
|
||||||
}
|
}
|
||||||
@@ -877,7 +729,6 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn = assignExpr(ts, inForInit);
|
Object pn = assignExpr(ts, inForInit);
|
||||||
while (ts.matchToken(ts.COMMA)) {
|
while (ts.matchToken(ts.COMMA)) {
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, inForInit));
|
pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -889,8 +740,6 @@ public class Parser {
|
|||||||
|
|
||||||
if (ts.matchToken(ts.ASSIGN)) {
|
if (ts.matchToken(ts.ASSIGN)) {
|
||||||
// omitted: "invalid assignment left-hand side" check.
|
// omitted: "invalid assignment left-hand side" check.
|
||||||
sourceAdd((char) ts.ASSIGN);
|
|
||||||
sourceAdd((char) ts.getOp());
|
|
||||||
pn = nf
|
pn = nf
|
||||||
.createBinary(ts.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit));
|
.createBinary(ts.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
@@ -906,10 +755,8 @@ public class Parser {
|
|||||||
Object pn = orExpr(ts, inForInit);
|
Object pn = orExpr(ts, inForInit);
|
||||||
|
|
||||||
if (ts.matchToken(ts.HOOK)) {
|
if (ts.matchToken(ts.HOOK)) {
|
||||||
sourceAdd((char) ts.HOOK);
|
|
||||||
ifTrue = assignExpr(ts, false);
|
ifTrue = assignExpr(ts, false);
|
||||||
mustMatchToken(ts, ts.COLON, "msg.no.colon.cond");
|
mustMatchToken(ts, ts.COLON, "msg.no.colon.cond");
|
||||||
sourceAdd((char) ts.COLON);
|
|
||||||
ifFalse = assignExpr(ts, inForInit);
|
ifFalse = assignExpr(ts, inForInit);
|
||||||
return nf.createTernary(pn, ifTrue, ifFalse);
|
return nf.createTernary(pn, ifTrue, ifFalse);
|
||||||
}
|
}
|
||||||
@@ -921,7 +768,6 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn = andExpr(ts, inForInit);
|
Object pn = andExpr(ts, inForInit);
|
||||||
if (ts.matchToken(ts.OR)) {
|
if (ts.matchToken(ts.OR)) {
|
||||||
sourceAdd((char) ts.OR);
|
|
||||||
pn = nf.createBinary(ts.OR, pn, orExpr(ts, inForInit));
|
pn = nf.createBinary(ts.OR, pn, orExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -932,7 +778,6 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn = bitOrExpr(ts, inForInit);
|
Object pn = bitOrExpr(ts, inForInit);
|
||||||
if (ts.matchToken(ts.AND)) {
|
if (ts.matchToken(ts.AND)) {
|
||||||
sourceAdd((char) ts.AND);
|
|
||||||
pn = nf.createBinary(ts.AND, pn, andExpr(ts, inForInit));
|
pn = nf.createBinary(ts.AND, pn, andExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,7 +788,6 @@ public class Parser {
|
|||||||
throws IOException, JavaScriptException {
|
throws IOException, JavaScriptException {
|
||||||
Object pn = bitXorExpr(ts, inForInit);
|
Object pn = bitXorExpr(ts, inForInit);
|
||||||
while (ts.matchToken(ts.BITOR)) {
|
while (ts.matchToken(ts.BITOR)) {
|
||||||
sourceAdd((char) ts.BITOR);
|
|
||||||
pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, inForInit));
|
pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -953,7 +797,6 @@ public class Parser {
|
|||||||
throws IOException, JavaScriptException {
|
throws IOException, JavaScriptException {
|
||||||
Object pn = bitAndExpr(ts, inForInit);
|
Object pn = bitAndExpr(ts, inForInit);
|
||||||
while (ts.matchToken(ts.BITXOR)) {
|
while (ts.matchToken(ts.BITXOR)) {
|
||||||
sourceAdd((char) ts.BITXOR);
|
|
||||||
pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, inForInit));
|
pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -963,7 +806,6 @@ public class Parser {
|
|||||||
throws IOException, JavaScriptException {
|
throws IOException, JavaScriptException {
|
||||||
Object pn = eqExpr(ts, inForInit);
|
Object pn = eqExpr(ts, inForInit);
|
||||||
while (ts.matchToken(ts.BITAND)) {
|
while (ts.matchToken(ts.BITAND)) {
|
||||||
sourceAdd((char) ts.BITAND);
|
|
||||||
pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, inForInit));
|
pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -973,8 +815,6 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn = relExpr(ts, inForInit);
|
Object pn = relExpr(ts, inForInit);
|
||||||
while (ts.matchToken(ts.EQOP)) {
|
while (ts.matchToken(ts.EQOP)) {
|
||||||
sourceAdd((char) ts.EQOP);
|
|
||||||
sourceAdd((char) ts.getOp());
|
|
||||||
pn = nf.createBinary(ts.EQOP, ts.getOp(), pn, relExpr(ts, inForInit));
|
pn = nf.createBinary(ts.EQOP, ts.getOp(), pn, relExpr(ts, inForInit));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -989,8 +829,7 @@ public class Parser {
|
|||||||
ts.ungetToken(ts.RELOP);
|
ts.ungetToken(ts.RELOP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.RELOP);
|
|
||||||
sourceAdd((char) op);
|
|
||||||
pn = nf.createBinary(ts.RELOP, op, pn, shiftExpr(ts));
|
pn = nf.createBinary(ts.RELOP, op, pn, shiftExpr(ts));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -1000,8 +839,6 @@ public class Parser {
|
|||||||
JavaScriptException {
|
JavaScriptException {
|
||||||
Object pn = addExpr(ts);
|
Object pn = addExpr(ts);
|
||||||
while (ts.matchToken(ts.SHOP)) {
|
while (ts.matchToken(ts.SHOP)) {
|
||||||
sourceAdd((char) ts.SHOP);
|
|
||||||
sourceAdd((char) ts.getOp());
|
|
||||||
pn = nf.createBinary(ts.SHOP, ts.getOp(), pn, addExpr(ts));
|
pn = nf.createBinary(ts.SHOP, ts.getOp(), pn, addExpr(ts));
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -1013,7 +850,6 @@ public class Parser {
|
|||||||
Object pn = mulExpr(ts);
|
Object pn = mulExpr(ts);
|
||||||
|
|
||||||
while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) {
|
while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) {
|
||||||
sourceAdd((char) tt);
|
|
||||||
// flushNewLines
|
// flushNewLines
|
||||||
pn = nf.createBinary(tt, pn, mulExpr(ts));
|
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) {
|
while ((tt = ts.peekToken()) == ts.MUL || tt == ts.DIV || tt == ts.MOD) {
|
||||||
tt = ts.getToken();
|
tt = ts.getToken();
|
||||||
sourceAdd((char) tt);
|
|
||||||
pn = nf.createBinary(tt, pn, unaryExpr(ts));
|
pn = nf.createBinary(tt, pn, unaryExpr(ts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1047,23 +882,17 @@ public class Parser {
|
|||||||
|
|
||||||
switch (tt) {
|
switch (tt) {
|
||||||
case TokenStream.UNARYOP:
|
case TokenStream.UNARYOP:
|
||||||
sourceAdd((char) ts.UNARYOP);
|
|
||||||
sourceAdd((char) ts.getOp());
|
|
||||||
return nf.createUnary(ts.UNARYOP, ts.getOp(), unaryExpr(ts));
|
return nf.createUnary(ts.UNARYOP, ts.getOp(), unaryExpr(ts));
|
||||||
|
|
||||||
case TokenStream.ADD:
|
case TokenStream.ADD:
|
||||||
case TokenStream.SUB:
|
case TokenStream.SUB:
|
||||||
sourceAdd((char) ts.UNARYOP);
|
|
||||||
sourceAdd((char) tt);
|
|
||||||
return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts));
|
return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts));
|
||||||
|
|
||||||
case TokenStream.INC:
|
case TokenStream.INC:
|
||||||
case TokenStream.DEC:
|
case TokenStream.DEC:
|
||||||
sourceAdd((char) tt);
|
|
||||||
return nf.createUnary(tt, ts.PRE, memberExpr(ts, true));
|
return nf.createUnary(tt, ts.PRE, memberExpr(ts, true));
|
||||||
|
|
||||||
case TokenStream.DELPROP:
|
case TokenStream.DELPROP:
|
||||||
sourceAdd((char) ts.DELPROP);
|
|
||||||
return nf.createUnary(ts.DELPROP, unaryExpr(ts));
|
return nf.createUnary(ts.DELPROP, unaryExpr(ts));
|
||||||
|
|
||||||
case TokenStream.ERROR:
|
case TokenStream.ERROR:
|
||||||
@@ -1087,7 +916,6 @@ public class Parser {
|
|||||||
if (((peeked = ts.peekToken()) == ts.INC || peeked == ts.DEC)
|
if (((peeked = ts.peekToken()) == ts.INC || peeked == ts.DEC)
|
||||||
&& ts.getLineno() == lineno) {
|
&& ts.getLineno() == lineno) {
|
||||||
int pf = ts.getToken();
|
int pf = ts.getToken();
|
||||||
sourceAdd((char) pf);
|
|
||||||
return nf.createUnary(pf, ts.POST, pn);
|
return nf.createUnary(pf, ts.POST, pn);
|
||||||
}
|
}
|
||||||
return pn;
|
return pn;
|
||||||
@@ -1103,17 +931,12 @@ public class Parser {
|
|||||||
matched = ts.matchToken(ts.GWT);
|
matched = ts.matchToken(ts.GWT);
|
||||||
ts.flags &= ~ts.TSF_REGEXP;
|
ts.flags &= ~ts.TSF_REGEXP;
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
boolean first = true;
|
|
||||||
do {
|
do {
|
||||||
if (!first)
|
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
first = false;
|
|
||||||
nf.addChildToBack(listNode, assignExpr(ts, false));
|
nf.addChildToBack(listNode, assignExpr(ts, false));
|
||||||
} while (ts.matchToken(ts.COMMA));
|
} while (ts.matchToken(ts.COMMA));
|
||||||
|
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren.arg");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren.arg");
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
return listNode;
|
return listNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,14 +953,12 @@ public class Parser {
|
|||||||
if (tt == ts.NEW) {
|
if (tt == ts.NEW) {
|
||||||
/* Eat the NEW token. */
|
/* Eat the NEW token. */
|
||||||
ts.getToken();
|
ts.getToken();
|
||||||
sourceAdd((char) ts.NEW);
|
|
||||||
|
|
||||||
/* Make a NEW node to append to. */
|
/* Make a NEW node to append to. */
|
||||||
pn = nf.createLeaf(ts.NEW);
|
pn = nf.createLeaf(ts.NEW);
|
||||||
nf.addChildToBack(pn, memberExpr(ts, false));
|
nf.addChildToBack(pn, memberExpr(ts, false));
|
||||||
|
|
||||||
if (ts.matchToken(ts.LP)) {
|
if (ts.matchToken(ts.LP)) {
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
/* Add the arguments to pn, if any are supplied. */
|
/* Add the arguments to pn, if any are supplied. */
|
||||||
pn = argumentList(ts, pn);
|
pn = argumentList(ts, pn);
|
||||||
}
|
}
|
||||||
@@ -1170,10 +991,8 @@ public class Parser {
|
|||||||
int tt;
|
int tt;
|
||||||
while ((tt = ts.getToken()) > ts.EOF) {
|
while ((tt = ts.getToken()) > ts.EOF) {
|
||||||
if (tt == ts.DOT) {
|
if (tt == ts.DOT) {
|
||||||
sourceAdd((char) ts.DOT);
|
|
||||||
mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot");
|
mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot");
|
||||||
String s = ts.getString();
|
String s = ts.getString();
|
||||||
sourceAddString(ts.NAME, s);
|
|
||||||
pn = nf.createBinary(ts.DOT, pn, nf.createName(ts.getString()));
|
pn = nf.createBinary(ts.DOT, pn, nf.createName(ts.getString()));
|
||||||
/*
|
/*
|
||||||
* pn = nf.createBinary(ts.DOT, pn, memberExpr(ts)) is the version in
|
* pn = nf.createBinary(ts.DOT, pn, memberExpr(ts)) is the version in
|
||||||
@@ -1182,17 +1001,13 @@ public class Parser {
|
|||||||
*/
|
*/
|
||||||
lastExprEndLine = ts.getLineno();
|
lastExprEndLine = ts.getLineno();
|
||||||
} else if (tt == ts.LB) {
|
} else if (tt == ts.LB) {
|
||||||
sourceAdd((char) ts.LB);
|
|
||||||
pn = nf.createBinary(ts.LB, pn, expr(ts, false));
|
pn = nf.createBinary(ts.LB, pn, expr(ts, false));
|
||||||
|
|
||||||
mustMatchToken(ts, ts.RB, "msg.no.bracket.index");
|
mustMatchToken(ts, ts.RB, "msg.no.bracket.index");
|
||||||
sourceAdd((char) ts.RB);
|
|
||||||
lastExprEndLine = ts.getLineno();
|
lastExprEndLine = ts.getLineno();
|
||||||
} else if (allowCallSyntax && tt == ts.LP) {
|
} else if (allowCallSyntax && tt == ts.LP) {
|
||||||
/* make a call node */
|
/* make a call node */
|
||||||
|
|
||||||
pn = nf.createUnary(ts.CALL, pn);
|
pn = nf.createUnary(ts.CALL, pn);
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
|
|
||||||
/* Add the arguments to pn, if any are supplied. */
|
/* Add the arguments to pn, if any are supplied. */
|
||||||
pn = argumentList(ts, pn);
|
pn = argumentList(ts, pn);
|
||||||
@@ -1222,7 +1037,6 @@ public class Parser {
|
|||||||
return function(ts, true);
|
return function(ts, true);
|
||||||
|
|
||||||
case TokenStream.LB: {
|
case TokenStream.LB: {
|
||||||
sourceAdd((char) ts.LB);
|
|
||||||
pn = nf.createLeaf(ts.ARRAYLIT);
|
pn = nf.createLeaf(ts.ARRAYLIT);
|
||||||
|
|
||||||
ts.flags |= ts.TSF_REGEXP;
|
ts.flags |= ts.TSF_REGEXP;
|
||||||
@@ -1230,17 +1044,11 @@ public class Parser {
|
|||||||
ts.flags &= ~ts.TSF_REGEXP;
|
ts.flags &= ~ts.TSF_REGEXP;
|
||||||
|
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
boolean first = true;
|
|
||||||
do {
|
do {
|
||||||
ts.flags |= ts.TSF_REGEXP;
|
ts.flags |= ts.TSF_REGEXP;
|
||||||
tt = ts.peekToken();
|
tt = ts.peekToken();
|
||||||
ts.flags &= ~ts.TSF_REGEXP;
|
ts.flags &= ~ts.TSF_REGEXP;
|
||||||
|
|
||||||
if (!first)
|
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
else
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
if (tt == ts.RB) { // to fix [,,,].length behavior...
|
if (tt == ts.RB) { // to fix [,,,].length behavior...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1254,42 +1062,31 @@ public class Parser {
|
|||||||
} while (ts.matchToken(ts.COMMA));
|
} while (ts.matchToken(ts.COMMA));
|
||||||
mustMatchToken(ts, ts.RB, "msg.no.bracket.arg");
|
mustMatchToken(ts, ts.RB, "msg.no.bracket.arg");
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.RB);
|
|
||||||
return nf.createArrayLiteral(pn);
|
return nf.createArrayLiteral(pn);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenStream.LC: {
|
case TokenStream.LC: {
|
||||||
pn = nf.createLeaf(ts.OBJLIT);
|
pn = nf.createLeaf(ts.OBJLIT);
|
||||||
|
|
||||||
sourceAdd((char) ts.LC);
|
|
||||||
if (!ts.matchToken(ts.RC)) {
|
if (!ts.matchToken(ts.RC)) {
|
||||||
|
|
||||||
boolean first = true;
|
|
||||||
commaloop : do {
|
commaloop : do {
|
||||||
Object property;
|
Object property;
|
||||||
|
|
||||||
if (!first)
|
|
||||||
sourceAdd((char) ts.COMMA);
|
|
||||||
else
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
tt = ts.getToken();
|
tt = ts.getToken();
|
||||||
switch (tt) {
|
switch (tt) {
|
||||||
// map NAMEs to STRINGs in object literal context.
|
// map NAMEs to STRINGs in object literal context.
|
||||||
case TokenStream.NAME:
|
case TokenStream.NAME:
|
||||||
case TokenStream.STRING:
|
case TokenStream.STRING:
|
||||||
String s = ts.getString();
|
|
||||||
sourceAddString(ts.NAME, s);
|
|
||||||
property = nf.createString(ts.getString());
|
property = nf.createString(ts.getString());
|
||||||
break;
|
break;
|
||||||
case TokenStream.NUMBER_INT:
|
case TokenStream.NUMBER_INT:
|
||||||
int n = (int) ts.getNumber();
|
int n = (int) ts.getNumber();
|
||||||
sourceAddNumber(n);
|
|
||||||
property = nf.createNumber(n);
|
property = nf.createNumber(n);
|
||||||
break;
|
break;
|
||||||
case TokenStream.NUMBER:
|
case TokenStream.NUMBER:
|
||||||
double d = ts.getNumber();
|
double d = ts.getNumber();
|
||||||
sourceAddNumber(d);
|
|
||||||
property = nf.createNumber(d);
|
property = nf.createNumber(d);
|
||||||
break;
|
break;
|
||||||
case TokenStream.RC:
|
case TokenStream.RC:
|
||||||
@@ -1304,7 +1101,6 @@ public class Parser {
|
|||||||
|
|
||||||
// OBJLIT is used as ':' in object literal for
|
// OBJLIT is used as ':' in object literal for
|
||||||
// decompilation to solve spacing ambiguity.
|
// decompilation to solve spacing ambiguity.
|
||||||
sourceAdd((char) ts.OBJLIT);
|
|
||||||
nf.addChildToBack(pn, property);
|
nf.addChildToBack(pn, property);
|
||||||
nf.addChildToBack(pn, assignExpr(ts, false));
|
nf.addChildToBack(pn, assignExpr(ts, false));
|
||||||
|
|
||||||
@@ -1312,7 +1108,6 @@ public class Parser {
|
|||||||
|
|
||||||
mustMatchToken(ts, ts.RC, "msg.no.brace.prop");
|
mustMatchToken(ts, ts.RC, "msg.no.brace.prop");
|
||||||
}
|
}
|
||||||
sourceAdd((char) ts.RC);
|
|
||||||
return nf.createObjectLiteral(pn);
|
return nf.createObjectLiteral(pn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,43 +1119,34 @@ public class Parser {
|
|||||||
* the structure of the parse tree? also TOK_LP is already overloaded (I
|
* the structure of the parse tree? also TOK_LP is already overloaded (I
|
||||||
* think) in the C IR as 'function call.'
|
* think) in the C IR as 'function call.'
|
||||||
*/
|
*/
|
||||||
sourceAdd((char) ts.LP);
|
|
||||||
pn = expr(ts, false);
|
pn = expr(ts, false);
|
||||||
sourceAdd((char) ts.GWT);
|
|
||||||
mustMatchToken(ts, ts.GWT, "msg.no.paren");
|
mustMatchToken(ts, ts.GWT, "msg.no.paren");
|
||||||
return pn;
|
return pn;
|
||||||
|
|
||||||
case TokenStream.NAME:
|
case TokenStream.NAME:
|
||||||
String name = ts.getString();
|
String name = ts.getString();
|
||||||
sourceAddString(ts.NAME, name);
|
|
||||||
return nf.createName(name);
|
return nf.createName(name);
|
||||||
|
|
||||||
case TokenStream.NUMBER_INT:
|
case TokenStream.NUMBER_INT:
|
||||||
int n = (int)ts.getNumber();
|
int n = (int)ts.getNumber();
|
||||||
sourceAddNumber(n);
|
|
||||||
return nf.createNumber(n);
|
return nf.createNumber(n);
|
||||||
|
|
||||||
case TokenStream.NUMBER:
|
case TokenStream.NUMBER:
|
||||||
double d = ts.getNumber();
|
double d = ts.getNumber();
|
||||||
sourceAddNumber(d);
|
|
||||||
return nf.createNumber(d);
|
return nf.createNumber(d);
|
||||||
|
|
||||||
case TokenStream.STRING:
|
case TokenStream.STRING:
|
||||||
String s = ts.getString();
|
String s = ts.getString();
|
||||||
sourceAddString(ts.STRING, s);
|
|
||||||
return nf.createString(s);
|
return nf.createString(s);
|
||||||
|
|
||||||
case TokenStream.REGEXP: {
|
case TokenStream.REGEXP: {
|
||||||
String flags = ts.regExpFlags;
|
String flags = ts.regExpFlags;
|
||||||
ts.regExpFlags = null;
|
ts.regExpFlags = null;
|
||||||
String re = ts.getString();
|
String re = ts.getString();
|
||||||
sourceAddString(ts.REGEXP, '/' + re + '/' + flags);
|
|
||||||
return nf.createRegExp(re, flags);
|
return nf.createRegExp(re, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenStream.PRIMARY:
|
case TokenStream.PRIMARY:
|
||||||
sourceAdd((char) ts.PRIMARY);
|
|
||||||
sourceAdd((char) ts.getOp());
|
|
||||||
return nf.createLeaf(ts.PRIMARY, ts.getOp());
|
return nf.createLeaf(ts.PRIMARY, ts.getOp());
|
||||||
|
|
||||||
case TokenStream.RESERVED:
|
case TokenStream.RESERVED:
|
||||||
@@ -1379,139 +1165,11 @@ public class Parser {
|
|||||||
return null; // should never reach here
|
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 int lastExprEndLine; // Hack to handle function expr termination.
|
||||||
private IRFactory nf;
|
private IRFactory nf;
|
||||||
private ErrorReporter er;
|
private ErrorReporter er;
|
||||||
private boolean ok; // Did the parse encounter an error?
|
private boolean ok; // Did the parse encounter an error?
|
||||||
|
|
||||||
private char[] sourceBuffer = new char[128];
|
|
||||||
private int sourceTop;
|
private int sourceTop;
|
||||||
private int functionNumber;
|
private int functionNumber;
|
||||||
private final boolean insideFunction;
|
private final boolean insideFunction;
|
||||||
|
|||||||
Reference in New Issue
Block a user