Fix warnings in JS parser

This commit is contained in:
Alexey Andreev
2017-05-17 12:29:37 +03:00
parent 9d186cfc66
commit 41ad637bad
@@ -103,15 +103,15 @@ public class Parser extends Observable {
((Node) tempBlock).setIsSyntheticBlock(true); ((Node) tempBlock).setIsSyntheticBlock(true);
while (true) { while (true) {
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.getToken(); tt = ts.getToken();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (tt <= ts.EOF) { if (tt <= TokenStream.EOF) {
break; break;
} }
if (tt == ts.FUNCTION) { if (tt == TokenStream.FUNCTION) {
try { try {
nf.addChildToBack(tempBlock, function(ts, false)); nf.addChildToBack(tempBlock, function(ts, false));
} catch (JavaScriptException e) { } catch (JavaScriptException e) {
@@ -148,7 +148,7 @@ public class Parser extends Observable {
Object pn = nf.createBlock(ts.getLineno()); Object pn = nf.createBlock(ts.getLineno());
try { try {
int tt; int tt;
while ((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) { while ((tt = ts.peekToken()) > TokenStream.EOF && tt != TokenStream.RC) {
if (tt == TokenStream.FUNCTION) { if (tt == TokenStream.FUNCTION) {
ts.getToken(); ts.getToken();
nf.addChildToBack(pn, function(ts, false)); nf.addChildToBack(pn, function(ts, false));
@@ -174,9 +174,9 @@ public class Parser extends Observable {
String name; String name;
Object memberExprNode = null; Object memberExprNode = null;
if (ts.matchToken(ts.NAME)) { if (ts.matchToken(TokenStream.NAME)) {
name = ts.getString(); name = ts.getString();
if (!ts.matchToken(ts.LP)) { if (!ts.matchToken(TokenStream.LP)) {
if (Context.getContext().hasFeature( if (Context.getContext().hasFeature(
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
@@ -185,9 +185,9 @@ public class Parser extends Observable {
name = null; name = null;
memberExprNode = memberExprTail(ts, false, memberExprHead); memberExprNode = memberExprTail(ts, false, memberExprHead);
} }
mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.parms");
} }
} else if (ts.matchToken(ts.LP)) { } else if (ts.matchToken(TokenStream.LP)) {
// Anonymous function // Anonymous function
name = null; name = null;
} else { } else {
@@ -199,7 +199,7 @@ public class Parser extends Observable {
// processed as anonymous function // processed as anonymous function
memberExprNode = memberExpr(ts, false); memberExprNode = memberExpr(ts, false);
} }
mustMatchToken(ts, ts.LP, "msg.no.paren.parms"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.parms");
} }
++functionNumber; ++functionNumber;
@@ -212,22 +212,22 @@ public class Parser extends Observable {
Object body; Object body;
try { try {
functionNumber = 0; functionNumber = 0;
args = nf.createLeaf(ts.LP); args = nf.createLeaf(TokenStream.LP);
if (!ts.matchToken(ts.GWT)) { if (!ts.matchToken(TokenStream.GWT)) {
do { do {
mustMatchToken(ts, ts.NAME, "msg.no.parm"); mustMatchToken(ts, TokenStream.NAME, "msg.no.parm");
String s = ts.getString(); String s = ts.getString();
nf.addChildToBack(args, nf.createName(s)); nf.addChildToBack(args, nf.createName(s));
} while (ts.matchToken(ts.COMMA)); } while (ts.matchToken(TokenStream.COMMA));
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.parms"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.parms");
} }
mustMatchToken(ts, ts.LC, "msg.no.brace.body"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.body");
body = parseFunctionBody(ts); body = parseFunctionBody(ts);
mustMatchToken(ts, ts.RC, "msg.no.brace.after.body"); mustMatchToken(ts, TokenStream.RC, "msg.no.brace.after.body");
// skip the last EOL so nested functions work... // skip the last EOL so nested functions work...
} finally { } finally {
sourceTop = savedSourceTop; sourceTop = savedSourceTop;
@@ -237,13 +237,13 @@ public class Parser extends Observable {
Object pn = nf.createFunction(name, args, body, ts.getSourceName(), Object pn = nf.createFunction(name, args, body, ts.getSourceName(),
baseLineno, ts.getLineno(), null, 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(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn);
} }
// 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) {
wellTerminated(ts, ts.FUNCTION); wellTerminated(ts, TokenStream.FUNCTION);
} }
notifyObservers(new ParserEvents.OnFunctionParsingEnd(ts)); notifyObservers(new ParserEvents.OnFunctionParsingEnd(ts));
@@ -254,7 +254,7 @@ public class Parser extends Observable {
Object pn = nf.createBlock(ts.getLineno()); Object pn = nf.createBlock(ts.getLineno());
int tt; int tt;
while ((tt = ts.peekToken()) > ts.EOF && tt != ts.RC) { while ((tt = ts.peekToken()) > TokenStream.EOF && tt != TokenStream.RC) {
nf.addChildToBack(pn, statement(ts)); nf.addChildToBack(pn, statement(ts));
} }
@@ -264,37 +264,35 @@ public class Parser extends Observable {
private Object condition(TokenStream ts) throws IOException, private Object condition(TokenStream ts) throws IOException,
JavaScriptException { JavaScriptException {
Object pn; Object pn;
mustMatchToken(ts, ts.LP, "msg.no.paren.cond"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.cond");
pn = expr(ts, false); pn = expr(ts, false);
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.cond"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.cond");
// there's a check here in jsparse.c that corrects = to == // there's a check here in jsparse.c that corrects = to ==
return pn; return pn;
} }
private boolean wellTerminated(TokenStream ts, int lastExprType) private void wellTerminated(TokenStream ts, int lastExprType)
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
int tt = ts.peekTokenSameLine(); int tt = ts.peekTokenSameLine();
if (tt == ts.ERROR) { if (tt == TokenStream.ERROR) {
return false; return;
} }
if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) { if (tt != TokenStream.EOF && tt != TokenStream.EOL && tt != TokenStream.SEMI && tt != TokenStream.RC) {
int version = Context.getContext().getLanguageVersion(); int version = Context.getContext().getLanguageVersion();
if ((tt == ts.FUNCTION || lastExprType == ts.FUNCTION) if ((tt == TokenStream.FUNCTION || lastExprType == TokenStream.FUNCTION)
&& (version < Context.VERSION_1_2)) { && (version < Context.VERSION_1_2)) {
/* /*
* Checking against version < 1.2 and version >= 1.0 in the above line * Checking against version < 1.2 and version >= 1.0 in the above line
* breaks old javascript, so we keep it this way for now... XXX warning * breaks old javascript, so we keep it this way for now... XXX warning
* needed? * needed?
*/ */
return true;
} else { } else {
reportError(ts, "msg.no.semi.stmt"); reportError(ts, "msg.no.semi.stmt");
} }
} }
return true;
} }
// match a NAME; return null if no match. // match a NAME; return null if no match.
@@ -305,13 +303,13 @@ public class Parser extends Observable {
String label = null; String label = null;
int tt; int tt;
tt = ts.peekTokenSameLine(); tt = ts.peekTokenSameLine();
if (tt == ts.NAME) { if (tt == TokenStream.NAME) {
ts.getToken(); ts.getToken();
label = ts.getString(); label = ts.getString();
} }
if (lineno == ts.getLineno()) if (lineno == ts.getLineno())
wellTerminated(ts, ts.ERROR); wellTerminated(ts, TokenStream.ERROR);
return label; return label;
} }
@@ -338,27 +336,21 @@ public class Parser extends Observable {
private Object statementHelper(TokenStream ts) throws IOException, private Object statementHelper(TokenStream ts) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = null; Object pn;
// If skipsemi == true, don't add SEMI + EOL to source at the
// end of this statment. For compound statements, IF/FOR etc.
boolean skipsemi = false;
int tt; int tt;
int lastExprType = 0; // For wellTerminated. 0 to avoid warning. int lastExprType; // For wellTerminated
tt = ts.getToken(); tt = ts.getToken();
switch (tt) { switch (tt) {
case TokenStream.IF: { case TokenStream.IF: {
skipsemi = true;
int lineno = ts.getLineno(); int lineno = ts.getLineno();
Object cond = condition(ts); Object cond = condition(ts);
Object ifTrue = statement(ts); Object ifTrue = statement(ts);
Object ifFalse = null; Object ifFalse = null;
if (ts.matchToken(ts.ELSE)) { if (ts.matchToken(TokenStream.ELSE)) {
ifFalse = statement(ts); ifFalse = statement(ts);
} }
pn = nf.createIf(cond, ifTrue, ifFalse, lineno); pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
@@ -366,26 +358,24 @@ public class Parser extends Observable {
} }
case TokenStream.SWITCH: { case TokenStream.SWITCH: {
skipsemi = true;
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, TokenStream.LP, "msg.no.paren.switch");
nf.addChildToBack(pn, expr(ts, false)); nf.addChildToBack(pn, expr(ts, false));
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.switch"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.switch");
mustMatchToken(ts, ts.LC, "msg.no.brace.switch"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.switch");
while ((tt = ts.getToken()) != ts.RC && tt != ts.EOF) { while ((tt = ts.getToken()) != TokenStream.RC && tt != TokenStream.EOF) {
switch (tt) { switch (tt) {
case TokenStream.CASE: case TokenStream.CASE:
cur_case = nf.createUnary(ts.CASE, expr(ts, false)); cur_case = nf.createUnary(TokenStream.CASE, expr(ts, false));
break; break;
case TokenStream.DEFAULT: case TokenStream.DEFAULT:
cur_case = nf.createLeaf(ts.DEFAULT); cur_case = nf.createLeaf(TokenStream.DEFAULT);
// XXX check that there isn't more than one default // XXX check that there isn't more than one default
break; break;
@@ -393,13 +383,13 @@ public class Parser extends Observable {
reportError(ts, "msg.bad.switch"); reportError(ts, "msg.bad.switch");
break; break;
} }
mustMatchToken(ts, ts.COLON, "msg.no.colon.case"); mustMatchToken(ts, TokenStream.COLON, "msg.no.colon.case");
case_statements = nf.createLeaf(TokenStream.BLOCK); case_statements = nf.createLeaf(TokenStream.BLOCK);
((Node) case_statements).setIsSyntheticBlock(true); ((Node) case_statements).setIsSyntheticBlock(true);
while ((tt = ts.peekToken()) != ts.RC && tt != ts.CASE while ((tt = ts.peekToken()) != TokenStream.RC && tt != TokenStream.CASE
&& tt != ts.DEFAULT && tt != ts.EOF) { && tt != TokenStream.DEFAULT && tt != TokenStream.EOF) {
nf.addChildToBack(case_statements, statement(ts)); nf.addChildToBack(case_statements, statement(ts));
} }
// assert cur_case // assert cur_case
@@ -411,8 +401,6 @@ public class Parser extends Observable {
} }
case TokenStream.WHILE: { case TokenStream.WHILE: {
skipsemi = true;
int lineno = ts.getLineno(); int lineno = ts.getLineno();
Object cond = condition(ts); Object cond = condition(ts);
Object body = statement(ts); Object body = statement(ts);
@@ -427,7 +415,7 @@ public class Parser extends Observable {
Object body = statement(ts); Object body = statement(ts);
mustMatchToken(ts, ts.WHILE, "msg.no.while.do"); mustMatchToken(ts, TokenStream.WHILE, "msg.no.while.do");
Object cond = condition(ts); Object cond = condition(ts);
pn = nf.createDoWhile(body, cond, lineno); pn = nf.createDoWhile(body, cond, lineno);
@@ -435,8 +423,6 @@ public class Parser extends Observable {
} }
case TokenStream.FOR: { case TokenStream.FOR: {
skipsemi = true;
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'
@@ -444,12 +430,12 @@ public class Parser extends Observable {
Object incr = null; // to kill warning Object incr = null; // to kill warning
Object body; Object body;
mustMatchToken(ts, ts.LP, "msg.no.paren.for"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.for");
tt = ts.peekToken(); tt = ts.peekToken();
if (tt == ts.SEMI) { if (tt == TokenStream.SEMI) {
init = nf.createLeaf(ts.VOID); init = nf.createLeaf(TokenStream.VOID);
} else { } else {
if (tt == ts.VAR) { if (tt == TokenStream.VAR) {
// set init to a var list or initial // set init to a var list or initial
ts.getToken(); // throw away the 'var' token ts.getToken(); // throw away the 'var' token
init = variables(ts, true); init = variables(ts, true);
@@ -459,28 +445,28 @@ public class Parser extends Observable {
} }
tt = ts.peekToken(); tt = ts.peekToken();
if (tt == ts.RELOP && ts.getOp() == ts.IN) { if (tt == TokenStream.RELOP && ts.getOp() == TokenStream.IN) {
ts.matchToken(ts.RELOP); ts.matchToken(TokenStream.RELOP);
// '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, TokenStream.SEMI, "msg.no.semi.for");
if (ts.peekToken() == ts.SEMI) { if (ts.peekToken() == TokenStream.SEMI) {
// no loop condition // no loop condition
cond = nf.createLeaf(ts.VOID); cond = nf.createLeaf(TokenStream.VOID);
} else { } else {
cond = expr(ts, false); cond = expr(ts, false);
} }
mustMatchToken(ts, ts.SEMI, "msg.no.semi.for.cond"); mustMatchToken(ts, TokenStream.SEMI, "msg.no.semi.for.cond");
if (ts.peekToken() == ts.GWT) { if (ts.peekToken() == TokenStream.GWT) {
incr = nf.createLeaf(ts.VOID); incr = nf.createLeaf(TokenStream.VOID);
} else { } else {
incr = expr(ts, false); incr = expr(ts, false);
} }
} }
mustMatchToken(ts, ts.GWT, "msg.no.paren.for.ctrl"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.for.ctrl");
body = statement(ts); body = statement(ts);
if (incr == null) { if (incr == null) {
@@ -496,46 +482,45 @@ public class Parser extends Observable {
int lineno = ts.getLineno(); int lineno = ts.getLineno();
Object tryblock; Object tryblock;
Object catchblocks = null; Object catchblocks;
Object finallyblock = null; Object finallyblock = null;
skipsemi = true;
tryblock = statement(ts); tryblock = statement(ts);
catchblocks = nf.createLeaf(TokenStream.BLOCK); catchblocks = nf.createLeaf(TokenStream.BLOCK);
boolean sawDefaultCatch = false; boolean sawDefaultCatch = false;
int peek = ts.peekToken(); int peek = ts.peekToken();
if (peek == ts.CATCH) { if (peek == TokenStream.CATCH) {
while (ts.matchToken(ts.CATCH)) { while (ts.matchToken(TokenStream.CATCH)) {
if (sawDefaultCatch) { if (sawDefaultCatch) {
reportError(ts, "msg.catch.unreachable"); reportError(ts, "msg.catch.unreachable");
} }
mustMatchToken(ts, ts.LP, "msg.no.paren.catch"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.catch");
mustMatchToken(ts, ts.NAME, "msg.bad.catchcond"); mustMatchToken(ts, TokenStream.NAME, "msg.bad.catchcond");
String varName = ts.getString(); String varName = ts.getString();
Object catchCond = null; Object catchCond = null;
if (ts.matchToken(ts.IF)) { if (ts.matchToken(TokenStream.IF)) {
catchCond = expr(ts, false); catchCond = expr(ts, false);
} else { } else {
sawDefaultCatch = true; sawDefaultCatch = true;
} }
mustMatchToken(ts, ts.GWT, "msg.bad.catchcond"); mustMatchToken(ts, TokenStream.GWT, "msg.bad.catchcond");
mustMatchToken(ts, ts.LC, "msg.no.brace.catchblock"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.catchblock");
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, TokenStream.RC, "msg.no.brace.after.body");
} }
} else if (peek != ts.FINALLY) { } else if (peek != TokenStream.FINALLY) {
mustMatchToken(ts, ts.FINALLY, "msg.try.no.catchfinally"); mustMatchToken(ts, TokenStream.FINALLY, "msg.try.no.catchfinally");
} }
if (ts.matchToken(ts.FINALLY)) { if (ts.matchToken(TokenStream.FINALLY)) {
finallyblock = statement(ts); finallyblock = statement(ts);
} }
@@ -548,7 +533,7 @@ public class Parser extends Observable {
int lineno = ts.getLineno(); int lineno = ts.getLineno();
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, TokenStream.ERROR);
break; break;
} }
case TokenStream.BREAK: { case TokenStream.BREAK: {
@@ -579,12 +564,10 @@ public class Parser extends Observable {
reportError(ts, "msg.jsni.unsupported.with"); reportError(ts, "msg.jsni.unsupported.with");
skipsemi = true;
int lineno = ts.getLineno(); int lineno = ts.getLineno();
mustMatchToken(ts, ts.LP, "msg.no.paren.with"); mustMatchToken(ts, TokenStream.LP, "msg.no.paren.with");
Object obj = expr(ts, false); Object obj = expr(ts, false);
mustMatchToken(ts, ts.GWT, "msg.no.paren.after.with"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.after.with");
Object body = statement(ts); Object body = statement(ts);
pn = nf.createWith(obj, body, lineno); pn = nf.createWith(obj, body, lineno);
break; break;
@@ -593,30 +576,30 @@ public class Parser extends Observable {
int lineno = ts.getLineno(); int lineno = ts.getLineno();
pn = variables(ts, false); pn = variables(ts, false);
if (ts.getLineno() == lineno) if (ts.getLineno() == lineno)
wellTerminated(ts, ts.ERROR); wellTerminated(ts, TokenStream.ERROR);
break; break;
} }
case TokenStream.RETURN: { case TokenStream.RETURN: {
Object retExpr = null; Object retExpr = null;
int lineno = 0; int lineno = 0;
// 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 & TokenStream.TSF_FUNCTION) == 0)) {
reportError(ts, "msg.bad.return"); reportError(ts, "msg.bad.return");
} }
/* This is ugly, but we don't want to require a semicolon. */ /* This is ugly, but we don't want to require a semicolon. */
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.peekTokenSameLine(); tt = ts.peekTokenSameLine();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (tt != ts.EOF && tt != ts.EOL && tt != ts.SEMI && tt != ts.RC) { if (tt != TokenStream.EOF && tt != TokenStream.EOL && tt != TokenStream.SEMI && tt != TokenStream.RC) {
lineno = ts.getLineno(); lineno = ts.getLineno();
retExpr = expr(ts, false); retExpr = expr(ts, false);
if (ts.getLineno() == lineno) if (ts.getLineno() == lineno)
wellTerminated(ts, ts.ERROR); wellTerminated(ts, TokenStream.ERROR);
ts.flags |= ts.TSF_RETURN_EXPR; ts.flags |= TokenStream.TSF_RETURN_EXPR;
} else { } else {
ts.flags |= ts.TSF_RETURN_VOID; ts.flags |= TokenStream.TSF_RETURN_VOID;
} }
// XXX ASSERT pn // XXX ASSERT pn
@@ -624,18 +607,15 @@ public class Parser extends Observable {
break; break;
} }
case TokenStream.LC: case TokenStream.LC:
skipsemi = true;
pn = statements(ts); pn = statements(ts);
mustMatchToken(ts, ts.RC, "msg.no.brace.block"); mustMatchToken(ts, TokenStream.RC, "msg.no.brace.block");
break; break;
case TokenStream.ERROR: case TokenStream.ERROR:
// Fall thru, to have a node for error recovery to work on // Fall thru, to have a node for error recovery to work on
case TokenStream.EOL: case TokenStream.EOL:
case TokenStream.SEMI: case TokenStream.SEMI:
pn = nf.createLeaf(ts.VOID); pn = nf.createLeaf(TokenStream.VOID);
skipsemi = true;
break; break;
default: { default: {
@@ -646,12 +626,12 @@ public class Parser extends Observable {
pn = expr(ts, false); pn = expr(ts, false);
if (ts.peekToken() == ts.COLON) { if (ts.peekToken() == TokenStream.COLON) {
/* /*
* check that the last thing the tokenizer returned was a NAME and * check that the last thing the tokenizer returned was a NAME and
* that only one token was consumed. * that only one token was consumed.
*/ */
if (lastExprType != ts.NAME || (ts.getTokenno() != tokenno)) if (lastExprType != TokenStream.NAME || (ts.getTokenno() != tokenno))
reportError(ts, "msg.bad.label"); reportError(ts, "msg.bad.label");
ts.getToken(); // eat the COLON ts.getToken(); // eat the COLON
@@ -673,8 +653,8 @@ public class Parser extends Observable {
return pn; return pn;
} }
if (lastExprType == ts.FUNCTION) { if (lastExprType == TokenStream.FUNCTION) {
if (nf.getLeafType(pn) != ts.FUNCTION) { if (nf.getLeafType(pn) != TokenStream.FUNCTION) {
reportError(ts, "msg.syntax"); reportError(ts, "msg.syntax");
} }
} }
@@ -691,13 +671,13 @@ public class Parser extends Observable {
* line number even when they didn't succeed. * line number even when they didn't succeed.
*/ */
if (ts.getLineno() == lineno if (ts.getLineno() == lineno
|| (lastExprType == ts.FUNCTION && ts.getLineno() == lastExprEndLine)) { || (lastExprType == TokenStream.FUNCTION && ts.getLineno() == lastExprEndLine)) {
wellTerminated(ts, lastExprType); wellTerminated(ts, lastExprType);
} }
break; break;
} }
} }
ts.matchToken(ts.SEMI); ts.matchToken(TokenStream.SEMI);
return pn; return pn;
} }
@@ -706,25 +686,27 @@ public class Parser extends Observable {
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
Object pn = nf.createVariables(ts.getLineno()); Object pn = nf.createVariables(ts.getLineno());
for (;;) { while (true) {
Object name; Object name;
Object init; Object init;
mustMatchToken(ts, ts.NAME, "msg.bad.var"); mustMatchToken(ts, TokenStream.NAME, "msg.bad.var");
String s = ts.getString(); String s = ts.getString();
name = nf.createName(s); name = nf.createName(s);
// omitted check for argument hiding // omitted check for argument hiding
if (ts.matchToken(ts.ASSIGN)) { if (ts.matchToken(TokenStream.ASSIGN)) {
if (ts.getOp() != ts.NOP) if (ts.getOp() != TokenStream.NOP) {
reportError(ts, "msg.bad.var.init"); reportError(ts, "msg.bad.var.init");
}
init = assignExpr(ts, inForInit); init = assignExpr(ts, inForInit);
nf.addChildToBack(name, init); nf.addChildToBack(name, init);
} }
nf.addChildToBack(pn, name); nf.addChildToBack(pn, name);
if (!ts.matchToken(ts.COMMA)) if (!ts.matchToken(TokenStream.COMMA)) {
break; break;
}
} }
return pn; return pn;
} }
@@ -732,8 +714,8 @@ public class Parser extends Observable {
private Object expr(TokenStream ts, boolean inForInit) throws IOException, private Object expr(TokenStream ts, boolean inForInit) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = assignExpr(ts, inForInit); Object pn = assignExpr(ts, inForInit);
while (ts.matchToken(ts.COMMA)) { while (ts.matchToken(TokenStream.COMMA)) {
pn = nf.createBinary(ts.COMMA, pn, assignExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.COMMA, pn, assignExpr(ts, inForInit));
} }
return pn; return pn;
} }
@@ -742,10 +724,10 @@ public class Parser extends Observable {
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
Object pn = condExpr(ts, inForInit); Object pn = condExpr(ts, inForInit);
if (ts.matchToken(ts.ASSIGN)) { if (ts.matchToken(TokenStream.ASSIGN)) {
// omitted: "invalid assignment left-hand side" check. // omitted: "invalid assignment left-hand side" check.
pn = nf pn = nf
.createBinary(ts.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit)); .createBinary(TokenStream.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit));
} }
return pn; return pn;
@@ -758,9 +740,9 @@ public class Parser extends Observable {
Object pn = orExpr(ts, inForInit); Object pn = orExpr(ts, inForInit);
if (ts.matchToken(ts.HOOK)) { if (ts.matchToken(TokenStream.HOOK)) {
ifTrue = assignExpr(ts, false); ifTrue = assignExpr(ts, false);
mustMatchToken(ts, ts.COLON, "msg.no.colon.cond"); mustMatchToken(ts, TokenStream.COLON, "msg.no.colon.cond");
ifFalse = assignExpr(ts, inForInit); ifFalse = assignExpr(ts, inForInit);
return nf.createTernary(pn, ifTrue, ifFalse); return nf.createTernary(pn, ifTrue, ifFalse);
} }
@@ -771,8 +753,8 @@ public class Parser extends Observable {
private Object orExpr(TokenStream ts, boolean inForInit) throws IOException, private Object orExpr(TokenStream ts, boolean inForInit) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = andExpr(ts, inForInit); Object pn = andExpr(ts, inForInit);
if (ts.matchToken(ts.OR)) { if (ts.matchToken(TokenStream.OR)) {
pn = nf.createBinary(ts.OR, pn, orExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.OR, pn, orExpr(ts, inForInit));
} }
return pn; return pn;
@@ -781,8 +763,8 @@ public class Parser extends Observable {
private Object andExpr(TokenStream ts, boolean inForInit) throws IOException, private Object andExpr(TokenStream ts, boolean inForInit) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = bitOrExpr(ts, inForInit); Object pn = bitOrExpr(ts, inForInit);
if (ts.matchToken(ts.AND)) { if (ts.matchToken(TokenStream.AND)) {
pn = nf.createBinary(ts.AND, pn, andExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.AND, pn, andExpr(ts, inForInit));
} }
return pn; return pn;
@@ -791,8 +773,8 @@ public class Parser extends Observable {
private Object bitOrExpr(TokenStream ts, boolean inForInit) private Object bitOrExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
Object pn = bitXorExpr(ts, inForInit); Object pn = bitXorExpr(ts, inForInit);
while (ts.matchToken(ts.BITOR)) { while (ts.matchToken(TokenStream.BITOR)) {
pn = nf.createBinary(ts.BITOR, pn, bitXorExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.BITOR, pn, bitXorExpr(ts, inForInit));
} }
return pn; return pn;
} }
@@ -800,8 +782,8 @@ public class Parser extends Observable {
private Object bitXorExpr(TokenStream ts, boolean inForInit) private Object bitXorExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
Object pn = bitAndExpr(ts, inForInit); Object pn = bitAndExpr(ts, inForInit);
while (ts.matchToken(ts.BITXOR)) { while (ts.matchToken(TokenStream.BITXOR)) {
pn = nf.createBinary(ts.BITXOR, pn, bitAndExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.BITXOR, pn, bitAndExpr(ts, inForInit));
} }
return pn; return pn;
} }
@@ -809,8 +791,8 @@ public class Parser extends Observable {
private Object bitAndExpr(TokenStream ts, boolean inForInit) private Object bitAndExpr(TokenStream ts, boolean inForInit)
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
Object pn = eqExpr(ts, inForInit); Object pn = eqExpr(ts, inForInit);
while (ts.matchToken(ts.BITAND)) { while (ts.matchToken(TokenStream.BITAND)) {
pn = nf.createBinary(ts.BITAND, pn, eqExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.BITAND, pn, eqExpr(ts, inForInit));
} }
return pn; return pn;
} }
@@ -818,8 +800,8 @@ public class Parser extends Observable {
private Object eqExpr(TokenStream ts, boolean inForInit) throws IOException, private Object eqExpr(TokenStream ts, boolean inForInit) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = relExpr(ts, inForInit); Object pn = relExpr(ts, inForInit);
while (ts.matchToken(ts.EQOP)) { while (ts.matchToken(TokenStream.EQOP)) {
pn = nf.createBinary(ts.EQOP, ts.getOp(), pn, relExpr(ts, inForInit)); pn = nf.createBinary(TokenStream.EQOP, ts.getOp(), pn, relExpr(ts, inForInit));
} }
return pn; return pn;
} }
@@ -827,14 +809,14 @@ public class Parser extends Observable {
private Object relExpr(TokenStream ts, boolean inForInit) throws IOException, private Object relExpr(TokenStream ts, boolean inForInit) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = shiftExpr(ts); Object pn = shiftExpr(ts);
while (ts.matchToken(ts.RELOP)) { while (ts.matchToken(TokenStream.RELOP)) {
int op = ts.getOp(); int op = ts.getOp();
if (inForInit && op == ts.IN) { if (inForInit && op == TokenStream.IN) {
ts.ungetToken(ts.RELOP); ts.ungetToken(TokenStream.RELOP);
break; break;
} }
pn = nf.createBinary(ts.RELOP, op, pn, shiftExpr(ts)); pn = nf.createBinary(TokenStream.RELOP, op, pn, shiftExpr(ts));
} }
return pn; return pn;
} }
@@ -842,8 +824,8 @@ public class Parser extends Observable {
private Object shiftExpr(TokenStream ts) throws IOException, private Object shiftExpr(TokenStream ts) throws IOException,
JavaScriptException { JavaScriptException {
Object pn = addExpr(ts); Object pn = addExpr(ts);
while (ts.matchToken(ts.SHOP)) { while (ts.matchToken(TokenStream.SHOP)) {
pn = nf.createBinary(ts.SHOP, ts.getOp(), pn, addExpr(ts)); pn = nf.createBinary(TokenStream.SHOP, ts.getOp(), pn, addExpr(ts));
} }
return pn; return pn;
} }
@@ -853,7 +835,7 @@ public class Parser extends Observable {
int tt; int tt;
Object pn = mulExpr(ts); Object pn = mulExpr(ts);
while ((tt = ts.getToken()) == ts.ADD || tt == ts.SUB) { while ((tt = ts.getToken()) == TokenStream.ADD || tt == TokenStream.SUB) {
// flushNewLines // flushNewLines
pn = nf.createBinary(tt, pn, mulExpr(ts)); pn = nf.createBinary(tt, pn, mulExpr(ts));
} }
@@ -868,7 +850,7 @@ public class Parser extends Observable {
Object pn = unaryExpr(ts); Object pn = unaryExpr(ts);
while ((tt = ts.peekToken()) == ts.MUL || tt == ts.DIV || tt == ts.MOD) { while ((tt = ts.peekToken()) == TokenStream.MUL || tt == TokenStream.DIV || tt == TokenStream.MOD) {
tt = ts.getToken(); tt = ts.getToken();
pn = nf.createBinary(tt, pn, unaryExpr(ts)); pn = nf.createBinary(tt, pn, unaryExpr(ts));
} }
@@ -880,24 +862,24 @@ public class Parser extends Observable {
JavaScriptException { JavaScriptException {
int tt; int tt;
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.getToken(); tt = ts.getToken();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
switch (tt) { switch (tt) {
case TokenStream.UNARYOP: case TokenStream.UNARYOP:
return nf.createUnary(ts.UNARYOP, ts.getOp(), unaryExpr(ts)); return nf.createUnary(TokenStream.UNARYOP, ts.getOp(), unaryExpr(ts));
case TokenStream.ADD: case TokenStream.ADD:
case TokenStream.SUB: case TokenStream.SUB:
return nf.createUnary(ts.UNARYOP, tt, unaryExpr(ts)); return nf.createUnary(TokenStream.UNARYOP, tt, unaryExpr(ts));
case TokenStream.INC: case TokenStream.INC:
case TokenStream.DEC: case TokenStream.DEC:
return nf.createUnary(tt, ts.PRE, memberExpr(ts, true)); return nf.createUnary(tt, TokenStream.PRE, memberExpr(ts, true));
case TokenStream.DELPROP: case TokenStream.DELPROP:
return nf.createUnary(ts.DELPROP, unaryExpr(ts)); return nf.createUnary(TokenStream.DELPROP, unaryExpr(ts));
case TokenStream.ERROR: case TokenStream.ERROR:
break; break;
@@ -917,10 +899,10 @@ public class Parser extends Observable {
* calls. It'd be better if they had similar behavior... * calls. It'd be better if they had similar behavior...
*/ */
int peeked; int peeked;
if (((peeked = ts.peekToken()) == ts.INC || peeked == ts.DEC) if (((peeked = ts.peekToken()) == TokenStream.INC || peeked == TokenStream.DEC)
&& ts.getLineno() == lineno) { && ts.getLineno() == lineno) {
int pf = ts.getToken(); int pf = ts.getToken();
return nf.createUnary(pf, ts.POST, pn); return nf.createUnary(pf, TokenStream.POST, pn);
} }
return pn; return pn;
} }
@@ -931,15 +913,15 @@ public class Parser extends Observable {
private Object argumentList(TokenStream ts, Object listNode) private Object argumentList(TokenStream ts, Object listNode)
throws IOException, JavaScriptException { throws IOException, JavaScriptException {
boolean matched; boolean matched;
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
matched = ts.matchToken(ts.GWT); matched = ts.matchToken(TokenStream.GWT);
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (!matched) { if (!matched) {
do { do {
nf.addChildToBack(listNode, assignExpr(ts, false)); nf.addChildToBack(listNode, assignExpr(ts, false));
} while (ts.matchToken(ts.COMMA)); } while (ts.matchToken(TokenStream.COMMA));
mustMatchToken(ts, ts.GWT, "msg.no.paren.arg"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.arg");
} }
return listNode; return listNode;
} }
@@ -951,18 +933,18 @@ public class Parser extends Observable {
Object pn; Object pn;
/* Check for new expressions. */ /* Check for new expressions. */
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.peekToken(); tt = ts.peekToken();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (tt == ts.NEW) { if (tt == TokenStream.NEW) {
/* Eat the NEW token. */ /* Eat the NEW token. */
ts.getToken(); ts.getToken();
/* Make a NEW node to append to. */ /* Make a NEW node to append to. */
pn = nf.createLeaf(ts.NEW); pn = nf.createLeaf(TokenStream.NEW);
nf.addChildToBack(pn, memberExpr(ts, false)); nf.addChildToBack(pn, memberExpr(ts, false));
if (ts.matchToken(ts.LP)) { if (ts.matchToken(TokenStream.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);
} }
@@ -979,7 +961,7 @@ public class Parser extends Observable {
* argument to the constructor. * argument to the constructor.
*/ */
tt = ts.peekToken(); tt = ts.peekToken();
if (tt == ts.LC) { if (tt == TokenStream.LC) {
nf.addChildToBack(pn, primaryExpr(ts)); nf.addChildToBack(pn, primaryExpr(ts));
} }
} else { } else {
@@ -993,26 +975,26 @@ public class Parser extends Observable {
Object pn) throws IOException, JavaScriptException { Object pn) throws IOException, JavaScriptException {
lastExprEndLine = ts.getLineno(); lastExprEndLine = ts.getLineno();
int tt; int tt;
while ((tt = ts.getToken()) > ts.EOF) { while ((tt = ts.getToken()) > TokenStream.EOF) {
if (tt == ts.DOT) { if (tt == TokenStream.DOT) {
ts.treatKeywordAsIdentifier = true; ts.treatKeywordAsIdentifier = true;
mustMatchToken(ts, ts.NAME, "msg.no.name.after.dot"); mustMatchToken(ts, TokenStream.NAME, "msg.no.name.after.dot");
ts.treatKeywordAsIdentifier = false; ts.treatKeywordAsIdentifier = false;
pn = nf.createBinary(ts.DOT, pn, nf.createName(ts.getString())); pn = nf.createBinary(TokenStream.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
* Brendan's IR C version. Not in ECMA... does it reflect the 'new' * Brendan's IR C version. Not in ECMA... does it reflect the 'new'
* operator syntax he mentioned? * operator syntax he mentioned?
*/ */
lastExprEndLine = ts.getLineno(); lastExprEndLine = ts.getLineno();
} else if (tt == ts.LB) { } else if (tt == TokenStream.LB) {
pn = nf.createBinary(ts.LB, pn, expr(ts, false)); pn = nf.createBinary(TokenStream.LB, pn, expr(ts, false));
mustMatchToken(ts, ts.RB, "msg.no.bracket.index"); mustMatchToken(ts, TokenStream.RB, "msg.no.bracket.index");
lastExprEndLine = ts.getLineno(); lastExprEndLine = ts.getLineno();
} else if (allowCallSyntax && tt == ts.LP) { } else if (allowCallSyntax && tt == TokenStream.LP) {
/* make a call node */ /* make a call node */
pn = nf.createUnary(ts.CALL, pn); pn = nf.createUnary(TokenStream.CALL, pn);
/* 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);
@@ -1032,9 +1014,9 @@ public class Parser extends Observable {
Object pn; Object pn;
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.getToken(); tt = ts.getToken();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
switch (tt) { switch (tt) {
@@ -1042,39 +1024,39 @@ public class Parser extends Observable {
return function(ts, true); return function(ts, true);
case TokenStream.LB: { case TokenStream.LB: {
pn = nf.createLeaf(ts.ARRAYLIT); pn = nf.createLeaf(TokenStream.ARRAYLIT);
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
boolean matched = ts.matchToken(ts.RB); boolean matched = ts.matchToken(TokenStream.RB);
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (!matched) { if (!matched) {
do { do {
ts.flags |= ts.TSF_REGEXP; ts.flags |= TokenStream.TSF_REGEXP;
tt = ts.peekToken(); tt = ts.peekToken();
ts.flags &= ~ts.TSF_REGEXP; ts.flags &= ~TokenStream.TSF_REGEXP;
if (tt == ts.RB) { // to fix [,,,].length behavior... if (tt == TokenStream.RB) { // to fix [,,,].length behavior...
break; break;
} }
if (tt == ts.COMMA) { if (tt == TokenStream.COMMA) {
nf.addChildToBack(pn, nf.createLeaf(ts.PRIMARY, ts.UNDEFINED)); nf.addChildToBack(pn, nf.createLeaf(TokenStream.PRIMARY, TokenStream.UNDEFINED));
} else { } else {
nf.addChildToBack(pn, assignExpr(ts, false)); nf.addChildToBack(pn, assignExpr(ts, false));
} }
} while (ts.matchToken(ts.COMMA)); } while (ts.matchToken(TokenStream.COMMA));
mustMatchToken(ts, ts.RB, "msg.no.bracket.arg"); mustMatchToken(ts, TokenStream.RB, "msg.no.bracket.arg");
} }
return nf.createArrayLiteral(pn); return nf.createArrayLiteral(pn);
} }
case TokenStream.LC: { case TokenStream.LC: {
pn = nf.createLeaf(ts.OBJLIT); pn = nf.createLeaf(TokenStream.OBJLIT);
if (!ts.matchToken(ts.RC)) { if (!ts.matchToken(TokenStream.RC)) {
commaloop : do { commaloop : do {
Object property; Object property;
@@ -1102,16 +1084,16 @@ public class Parser extends Observable {
reportError(ts, "msg.bad.prop"); reportError(ts, "msg.bad.prop");
break commaloop; break commaloop;
} }
mustMatchToken(ts, ts.COLON, "msg.no.colon.prop"); mustMatchToken(ts, TokenStream.COLON, "msg.no.colon.prop");
// 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.
nf.addChildToBack(pn, property); nf.addChildToBack(pn, property);
nf.addChildToBack(pn, assignExpr(ts, false)); nf.addChildToBack(pn, assignExpr(ts, false));
} while (ts.matchToken(ts.COMMA)); } while (ts.matchToken(TokenStream.COMMA));
mustMatchToken(ts, ts.RC, "msg.no.brace.prop"); mustMatchToken(ts, TokenStream.RC, "msg.no.brace.prop");
} }
return nf.createObjectLiteral(pn); return nf.createObjectLiteral(pn);
} }
@@ -1125,7 +1107,7 @@ public class Parser extends Observable {
* think) in the C IR as 'function call.' * think) in the C IR as 'function call.'
*/ */
pn = expr(ts, false); pn = expr(ts, false);
mustMatchToken(ts, ts.GWT, "msg.no.paren"); mustMatchToken(ts, TokenStream.GWT, "msg.no.paren");
return pn; return pn;
case TokenStream.NAME: case TokenStream.NAME:
@@ -1152,7 +1134,7 @@ public class Parser extends Observable {
} }
case TokenStream.PRIMARY: case TokenStream.PRIMARY:
return nf.createLeaf(ts.PRIMARY, ts.getOp()); return nf.createLeaf(TokenStream.PRIMARY, ts.getOp());
case TokenStream.ERROR: case TokenStream.ERROR:
/* the scanner or one of its subroutines reported the error. */ /* the scanner or one of its subroutines reported the error. */
@@ -1167,8 +1149,7 @@ public class Parser extends Observable {
} }
private int lastExprEndLine; // Hack to handle function expr termination. private int lastExprEndLine; // Hack to handle function expr termination.
private IRFactory nf; private final IRFactory nf;
private ErrorReporter er;
private boolean ok; // Did the parse encounter an error? private boolean ok; // Did the parse encounter an error?
private int sourceTop; private int sourceTop;