?? parser.java
字號:
break bodyLoop; case Token.FUNCTION: consumeToken(); n = function(FunctionNode.FUNCTION_STATEMENT); break; default: n = statement(); break; } nf.addChildToBack(pn, n); } } catch (ParserException e) { // Ignore it } finally { --nestingOfFunction; } return pn; } private Node function(int functionType) throws IOException, ParserException { int syntheticType = functionType; int baseLineno = ts.getLineno(); // line number where source starts int functionSourceStart = decompiler.markFunctionStart(functionType); String name; Node memberExprNode = null; if (matchToken(Token.NAME)) { name = ts.getString(); decompiler.addName(name); if (!matchToken(Token.LP)) { if (compilerEnv.isAllowMemberExprAsFunctionName()) { // Extension to ECMA: if 'function <name>' does not follow // by '(', assume <name> starts memberExpr Node memberExprHead = nf.createName(name); name = ""; memberExprNode = memberExprTail(false, memberExprHead); } mustMatchToken(Token.LP, "msg.no.paren.parms"); } } else if (matchToken(Token.LP)) { // Anonymous function name = ""; } else { name = ""; if (compilerEnv.isAllowMemberExprAsFunctionName()) { // Note that memberExpr can not start with '(' like // in function (1+2).toString(), because 'function (' already // processed as anonymous function memberExprNode = memberExpr(false); } mustMatchToken(Token.LP, "msg.no.paren.parms"); } if (memberExprNode != null) { syntheticType = FunctionNode.FUNCTION_EXPRESSION; } boolean nested = insideFunction(); FunctionNode fnNode = nf.createFunction(name); if (nested || nestingOfWith > 0) { // 1. Nested functions are not affected by the dynamic scope flag // as dynamic scope is already a parent of their scope. // 2. Functions defined under the with statement also immune to // this setup, in which case dynamic scope is ignored in favor // of with object. fnNode.itsIgnoreDynamicScope = true; } int functionIndex = currentScriptOrFn.addFunction(fnNode); int functionSourceEnd; ScriptOrFnNode savedScriptOrFn = currentScriptOrFn; currentScriptOrFn = fnNode; int savedNestingOfWith = nestingOfWith; nestingOfWith = 0; Hashtable savedLabelSet = labelSet; labelSet = null; ObjArray savedLoopSet = loopSet; loopSet = null; ObjArray savedLoopAndSwitchSet = loopAndSwitchSet; loopAndSwitchSet = null; Node body; String source; try { decompiler.addToken(Token.LP); if (!matchToken(Token.RP)) { boolean first = true; do { if (!first) decompiler.addToken(Token.COMMA); first = false; mustMatchToken(Token.NAME, "msg.no.parm"); String s = ts.getString(); if (fnNode.hasParamOrVar(s)) { addWarning("msg.dup.parms", s); } fnNode.addParam(s); decompiler.addName(s); } while (matchToken(Token.COMMA)); mustMatchToken(Token.RP, "msg.no.paren.after.parms"); } decompiler.addToken(Token.RP); mustMatchToken(Token.LC, "msg.no.brace.body"); decompiler.addEOL(Token.LC); body = parseFunctionBody(); mustMatchToken(Token.RC, "msg.no.brace.after.body"); decompiler.addToken(Token.RC); functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart); if (functionType != FunctionNode.FUNCTION_EXPRESSION) { if (compilerEnv.getLanguageVersion() >= Context.VERSION_1_2) { // function f() {} function g() {} is not allowed in 1.2 // or later but for compatibility with old scripts // the check is done only if language is // explicitly set. // XXX warning needed if version == VERSION_DEFAULT ? int tt = peekTokenOrEOL(); if (tt == Token.FUNCTION) { reportError("msg.no.semi.stmt"); } } // Add EOL only if function is not part of expression // since it gets SEMI + EOL from Statement in that case decompiler.addToken(Token.EOL); } } finally { loopAndSwitchSet = savedLoopAndSwitchSet; loopSet = savedLoopSet; labelSet = savedLabelSet; nestingOfWith = savedNestingOfWith; currentScriptOrFn = savedScriptOrFn; } fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd); fnNode.setSourceName(sourceURI); fnNode.setBaseLineno(baseLineno); fnNode.setEndLineno(ts.getLineno()); Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType); if (memberExprNode != null) { pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn); if (functionType != FunctionNode.FUNCTION_EXPRESSION) { // XXX check JScript behavior: should it be createExprStatement? pn = nf.createExprStatementNoReturn(pn, baseLineno); } } return pn; } private Node statements() throws IOException { Node pn = nf.createBlock(ts.getLineno()); int tt; while((tt = peekToken()) > Token.EOF && tt != Token.RC) { nf.addChildToBack(pn, statement()); } return pn; } private Node condition() throws IOException, ParserException { Node pn; mustMatchToken(Token.LP, "msg.no.paren.cond"); decompiler.addToken(Token.LP); pn = expr(false); mustMatchToken(Token.RP, "msg.no.paren.after.cond"); decompiler.addToken(Token.RP); // there's a check here in jsparse.c that corrects = to == return pn; } // match a NAME; return null if no match. private Node matchJumpLabelName() throws IOException, ParserException { Node label = null; int tt = peekTokenOrEOL(); if (tt == Token.NAME) { consumeToken(); String name = ts.getString(); decompiler.addName(name); if (labelSet != null) { label = (Node)labelSet.get(name); } if (label == null) { reportError("msg.undef.label"); } } return label; } private Node statement() throws IOException { try { Node pn = statementHelper(null); if (pn != null) { return pn; } } catch (ParserException e) { } // skip to end of statement int lineno = ts.getLineno(); guessingStatementEnd: for (;;) { int tt = peekTokenOrEOL(); consumeToken(); switch (tt) { case Token.ERROR: case Token.EOF: case Token.EOL: case Token.SEMI: break guessingStatementEnd; } } return nf.createExprStatement(nf.createName("error"), lineno); } /** * Whether the "catch (e: e instanceof Exception) { ... }" syntax * is implemented. */ private Node statementHelper(Node statementLabel) throws IOException, ParserException { Node pn = null; int tt; tt = peekToken(); switch(tt) { case Token.IF: { consumeToken(); decompiler.addToken(Token.IF); int lineno = ts.getLineno(); Node cond = condition(); decompiler.addEOL(Token.LC); Node ifTrue = statement(); Node ifFalse = null; if (matchToken(Token.ELSE)) { decompiler.addToken(Token.RC); decompiler.addToken(Token.ELSE); decompiler.addEOL(Token.LC); ifFalse = statement(); } decompiler.addEOL(Token.RC); pn = nf.createIf(cond, ifTrue, ifFalse, lineno); return pn; } case Token.SWITCH: { consumeToken(); decompiler.addToken(Token.SWITCH); int lineno = ts.getLineno(); mustMatchToken(Token.LP, "msg.no.paren.switch"); decompiler.addToken(Token.LP); pn = enterSwitch(expr(false), lineno, statementLabel); try { mustMatchToken(Token.RP, "msg.no.paren.after.switch"); decompiler.addToken(Token.RP); mustMatchToken(Token.LC, "msg.no.brace.switch"); decompiler.addEOL(Token.LC); boolean hasDefault = false; switchLoop: for (;;) { tt = nextToken(); Node caseExpression; switch (tt) { case Token.RC: break switchLoop; case Token.CASE: decompiler.addToken(Token.CASE); caseExpression = expr(false); mustMatchToken(Token.COLON, "msg.no.colon.case"); decompiler.addEOL(Token.COLON); break; case Token.DEFAULT: if (hasDefault) { reportError("msg.double.switch.default"); } decompiler.addToken(Token.DEFAULT); hasDefault = true; caseExpression = null; mustMatchToken(Token.COLON, "msg.no.colon.case"); decompiler.addEOL(Token.COLON); break; default: reportError("msg.bad.switch"); break switchLoop; } Node block = nf.createLeaf(Token.BLOCK); while ((tt = peekToken()) != Token.RC && tt != Token.CASE && tt != Token.DEFAULT && tt != Token.EOF) { nf.addChildToBack(block, statement()); } // caseExpression == null => add default lable nf.addSwitchCase(pn, caseExpression, block); } decompiler.addEOL(Token.RC); nf.closeSwitch(pn); } finally { exitSwitch(); } return pn; } case Token.WHILE: { consumeToken(); decompiler.addToken(Token.WHILE); Node loop = enterLoop(statementLabel); try { Node cond = condition(); decompiler.addEOL(Token.LC); Node body = statement(); decompiler.addEOL(Token.RC); pn = nf.createWhile(loop, cond, body); } finally { exitLoop(); } return pn; } case Token.DO: { consumeToken(); decompiler.addToken(Token.DO); decompiler.addEOL(Token.LC); Node loop = enterLoop(statementLabel); try { Node body = statement(); decompiler.addToken(Token.RC); mustMatchToken(Token.WHILE, "msg.no.while.do"); decompiler.addToken(Token.WHILE); Node cond = condition(); pn = nf.createDoWhile(loop, body, cond); } finally { exitLoop(); } // Always auto-insert semicon to follow SpiderMonkey: // It is required by EMAScript but is ignored by the rest of // world, see bug 238945 matchToken(Token.SEMI); decompiler.addEOL(Token.SEMI); return pn; } case Token.FOR: { consumeToken(); boolean isForEach = false; decompiler.addToken(Token.FOR); Node loop = enterLoop(statementLabel); try { Node init; // Node init is also foo in 'foo in Object' Node cond; // Node cond is also object in 'foo in Object' Node incr = null; // to kill warning Node body; // See if this is a for each () instead of just a for () if (matchToken(Token.NAME)) { decompiler.addName(ts.getString()); if (ts.getString().equals("each")) { isForEach = true; } else { reportError("msg.no.paren.for"); } } mustMatchToken(Token.LP, "msg.no.paren.for"); decompiler.addToken(Token.LP); tt = peekToken(); if (tt == Token.SEMI) { init = nf.createLeaf(Token.EMPTY); } else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -