📄 parser.java
字号:
Node expr = expr(false); pn = nf.createDefaultNamespace(expr, nsLine); break; case Token.NAME: { int lineno = ts.getLineno(); String name = ts.getString(); setCheckForLabel(); pn = expr(false); if (pn.getType() != Token.LABEL) { pn = nf.createExprStatement(pn, lineno); } else { // Parsed the label: push back token should be // colon that primaryExpr left untouched. if (peekToken() != Token.COLON) Kit.codeBug(); consumeToken(); // depend on decompiling lookahead to guess that that // last name was a label. decompiler.addName(name); decompiler.addEOL(Token.COLON); if (labelSet == null) { labelSet = new Hashtable(); } else if (labelSet.containsKey(name)) { reportError("msg.dup.label"); } boolean firstLabel; if (statementLabel == null) { firstLabel = true; statementLabel = pn; } else { // Discard multiple label nodes and use only // the first: it allows to simplify IRFactory firstLabel = false; } labelSet.put(name, statementLabel); try { pn = statementHelper(statementLabel); } finally { labelSet.remove(name); } if (firstLabel) { pn = nf.createLabeledStatement(statementLabel, pn); } return pn; } break; } default: { int lineno = ts.getLineno(); pn = expr(false); pn = nf.createExprStatement(pn, lineno); break; } } int ttFlagged = peekFlaggedToken(); switch (ttFlagged & CLEAR_TI_MASK) { case Token.SEMI: // Consume ';' as a part of expression consumeToken(); break; case Token.ERROR: case Token.EOF: case Token.RC: // Autoinsert ; break; default: if ((ttFlagged & TI_AFTER_EOL) == 0) { // Report error if no EOL or autoinsert ; otherwise reportError("msg.no.semi.stmt"); } break; } decompiler.addEOL(Token.SEMI); return pn; } /** * Returns whether or not the bits in the mask have changed to all set. * @param before bits before change * @param after bits after change * @param mask mask for bits * @return true if all the bits in the mask are set in "after" but not * "before" */ private static final boolean nowAllSet(int before, int after, int mask) { return ((before & mask) != mask) && ((after & mask) == mask); } private Node returnOrYield(int tt, boolean exprContext) throws IOException, ParserException { if (!insideFunction()) { reportError(tt == Token.RETURN ? "msg.bad.return" : "msg.bad.yield"); } consumeToken(); decompiler.addToken(tt); int lineno = ts.getLineno(); Node e; /* This is ugly, but we don't want to require a semicolon. */ switch (peekTokenOrEOL()) { case Token.SEMI: case Token.RC: case Token.EOF: case Token.EOL: case Token.ERROR: case Token.RB: case Token.RP: case Token.YIELD: e = null; break; default: e = expr(false); break; } int before = endFlags; Node ret; if (tt == Token.RETURN) { if (e == null ) { endFlags |= Node.END_RETURNS; } else { endFlags |= Node.END_RETURNS_VALUE; hasReturnValue = true; } ret = nf.createReturn(e, lineno); // see if we need a strict mode warning if (nowAllSet(before, endFlags, Node.END_RETURNS|Node.END_RETURNS_VALUE)) { addStrictWarning("msg.return.inconsistent", ""); } } else { endFlags |= Node.END_YIELDS; ret = nf.createYield(e, lineno); if (!exprContext) ret = new Node(Token.EXPR_VOID, ret, lineno); } // see if we are mixing yields and value returns. if (nowAllSet(before, endFlags, Node.END_YIELDS|Node.END_RETURNS_VALUE)) { String name = ((FunctionNode)currentScriptOrFn).getFunctionName(); if (name.length() == 0) addError("msg.anon.generator.returns", ""); else addError("msg.generator.returns", name); } return ret; } /** * Parse a 'var' or 'const' statement, or a 'var' init list in a for * statement. * @param inFor true if we are currently in the midst of the init * clause of a for. * @param inStatement true if called in a statement (as opposed to an * expression) context * @param declType A token value: either VAR, CONST, or LET depending on * context. * @return The parsed statement * @throws IOException * @throws ParserException */ private Node variables(boolean inFor, int declType) throws IOException, ParserException { Node result = nf.createVariables(declType, ts.getLineno()); boolean first = true; for (;;) { Node destructuring = null; String s = null; int tt = peekToken(); if (tt == Token.LB || tt == Token.LC) { // Destructuring assignment, e.g., var [a,b] = ... destructuring = primaryExpr(); } else { // Simple variable name mustMatchToken(Token.NAME, "msg.bad.var"); s = ts.getString(); if (!first) decompiler.addToken(Token.COMMA); first = false; decompiler.addName(s); defineSymbol(declType, s); } Node init = null; if (matchToken(Token.ASSIGN)) { decompiler.addToken(Token.ASSIGN); init = assignExpr(inFor); } if (destructuring != null) { if (init == null) { if (!inFor) reportError("msg.destruct.assign.no.init"); nf.addChildToBack(result, destructuring); } else { nf.addChildToBack(result, nf.createDestructuringAssignment(declType, destructuring, init)); } } else { Node name = nf.createName(s); if (init != null) nf.addChildToBack(name, init); nf.addChildToBack(result, name); } if (!matchToken(Token.COMMA)) break; } return result; } private Node let(boolean isStatement) throws IOException, ParserException { mustMatchToken(Token.LP, "msg.no.paren.after.let"); decompiler.addToken(Token.LP); Node result = nf.createScopeNode(Token.LET, ts.getLineno()); pushScope(result); try { Node vars = variables(false, Token.LET); nf.addChildToBack(result, vars); mustMatchToken(Token.RP, "msg.no.paren.let"); decompiler.addToken(Token.RP); if (isStatement && peekToken() == Token.LC) { // let statement consumeToken(); decompiler.addEOL(Token.LC); nf.addChildToBack(result, statements(null)); mustMatchToken(Token.RC, "msg.no.curly.let"); decompiler.addToken(Token.RC); } else { // let expression result.setType(Token.LETEXPR); nf.addChildToBack(result, expr(false)); if (isStatement) { // let expression in statement context result = nf.createExprStatement(result, ts.getLineno()); } } } finally { popScope(); } return result; } void defineSymbol(int declType, String name) { Node.Scope definingScope = currentScope.getDefiningScope(name); Node.Scope.Symbol symbol = definingScope != null ? definingScope.getSymbol(name) : null; boolean error = false; if (symbol != null && (symbol.declType == Token.CONST || declType == Token.CONST)) { error = true; } else { switch (declType) { case Token.LET: if (symbol != null && definingScope == currentScope) { error = symbol.declType == Token.LET; } currentScope.putSymbol(name, new Node.Scope.Symbol(declType, name)); break; case Token.VAR: case Token.CONST: case Token.FUNCTION: if (symbol != null) { if (symbol.declType == Token.VAR) addStrictWarning("msg.var.redecl", name); else if (symbol.declType == Token.LP) { addStrictWarning("msg.var.hides.arg", name); } } else { currentScriptOrFn.putSymbol(name, new Node.Scope.Symbol(declType, name)); } break; case Token.LP: if (symbol != null) { // must be duplicate parameter. Second parameter hides the // first, so go ahead and add the second pararameter addWarning("msg.dup.parms", name); } currentScriptOrFn.putSymbol(name, new Node.Scope.Symbol(declType, name)); break; default: throw Kit.codeBug(); } } if (error) { addError(symbol.declType == Token.CONST ? "msg.const.redecl" : symbol.declType == Token.LET ? "msg.let.redecl" : symbol.declType == Token.VAR ? "msg.var.redecl" : symbol.declType == Token.FUNCTION ? "msg.fn.redecl" : "msg.parm.redecl", name); } } private Node expr(boolean inForInit) throws IOException, ParserException { Node pn = assignExpr(inForInit); while (matchToken(Token.COMMA)) { decompiler.addToken(Token.COMMA); if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) addStrictWarning("msg.no.side.effects", ""); if (peekToken() == Token.YIELD) { reportError("msg.yield.parenthesized"); } pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit)); } return pn; } private Node assignExpr(boolean inForInit) throws IOException, ParserException { int tt = peekToken(); if (tt == Token.YIELD) { consumeToken(); return returnOrYield(tt, true); } Node pn = condExpr(inForInit); tt = peekToken(); if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) { consumeToken(); decompiler.addToken(tt); pn = nf.createAssignment(tt, pn, assignExpr(inForInit)); } return pn; } private Node condExpr(boolean inForInit) throws IOException, ParserException { Node pn = orExpr(inForInit); if (matchToken(Token.HOOK)) { decompiler.addToken(Token.HOOK); Node ifTrue = assignExpr(false); mustMatchToken(Token.COLON, "msg.no.colon.cond"); decompiler.addToken(Token.COLON); Node ifFalse = assignExpr(inForInit); return nf.createCondExpr(pn, ifTrue, ifFalse); } return pn; } private Node orExpr(boolean inForInit) throws IOException, ParserException { Node pn = andExpr(inForInit); if (matchToken(Token.OR)) { decompiler.addToken(Token.OR); pn = nf.createBinary(Token.OR, pn, orExpr(inForInit)); } return pn; } private Node andExpr(boolean inForInit) throws IOException, ParserException { Node pn = bitOrExpr(inForInit); if (matchToken(Token.AND)) { decompiler.addToken(Token.AND); pn = nf.createBinary(Token.AND, pn, andExpr(inForInit)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -