/** * Builds a parse tree from the given sourcereader. * @see #parse(String,String,int) * @throws IOException if the {@link Reader} encounters an error */ public AstRoot parse(Reader sourceReader, String sourceURI, int lineno) throws IOException { if (parseFinished) throw new IllegalStateException("parser reused"); if (compilerEnv.isIdeMode()) { return parse(readFully(sourceReader), sourceURI, lineno); } try { this.sourceURI = sourceURI; ts = new TokenStream(this, sourceReader, null, lineno); return parse(); } finally { parseFinished = true; } }
void addError(String messageId, String messageArg) { addError(messageId, messageArg, ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); }
private AstNode shiftExpr() throws IOException { AstNode pn = addExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; switch (tt) { case Token.LSH: case Token.URSH: case Token.RSH: consumeToken(); pn = new InfixExpression(tt, pn, addExpr(), opPos); continue; } break; } return pn; }
private AstNode orExpr() throws IOException { AstNode pn = andExpr(); if (matchToken(Token.OR)) { int opPos = ts.tokenBeg; pn = new InfixExpression(Token.OR, pn, orExpr(), opPos); } return pn; }
private AstNode andExpr() throws IOException { AstNode pn = bitOrExpr(); if (matchToken(Token.AND)) { int opPos = ts.tokenBeg; pn = new InfixExpression(Token.AND, pn, andExpr(), opPos); } return pn; }
if (pn == null) codeBug(); int pos = pn.getPosition(), lineno = ts.lineno; tailLoop: for (;;) { int tt = peekToken(); switch (tt) { case Token.DOT: case Token.DOTDOT: pn = propertyAccess(tt, pn); break; consumeToken(); int opPos = ts.tokenBeg, rp = -1; mustHaveXML(); setRequiresActivation(); AstNode filter = expr(); int end = getNodeEnd(filter); if (mustMatchToken(Token.RP, "msg.no.paren")) { rp = ts.tokenBeg; end = ts.tokenEnd; consumeToken(); int lb = ts.tokenBeg, rb = -1; AstNode expr = expr(); end = getNodeEnd(expr); if (mustMatchToken(Token.RB, "msg.no.bracket.index")) { rb = ts.tokenBeg; end = ts.tokenEnd;
if (!insideFunction()) { reportError(tt == Token.RETURN ? "msg.bad.return" : "msg.bad.yield"); consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg, end = ts.tokenEnd; switch (peekTokenOrEOL()) { case Token.SEMI: case Token.RC: case Token.RB: case Token.RP: case Token.EOF: case Token.EOL: case Token.ERROR: case Token.YIELD: break; default: e = expr(); end = getNodeEnd(e); if (nowAllSet(before, endFlags, Node.END_RETURNS|Node.END_RETURNS_VALUE)) addStrictWarning("msg.return.inconsistent", "", pos, end - pos); } else { if (!insideFunction()) reportError("msg.bad.yield"); endFlags |= Node.END_YIELDS; ret = new Yield(pos, end - pos, e); setRequiresActivation(); setIsGenerator(); if (!exprContext) { ret = new ExpressionStatement(ret); if (insideFunction()
if (matchToken(Token.NAME)) { name = createNameNode(true, Token.NAME); if (!matchToken(Token.LP)) { if (compilerEnv.isAllowMemberExprAsFunctionName()) { AstNode memberExprHead = name; name = null; memberExprNode = memberExprTail(false, memberExprHead); mustMatchToken(Token.LP, "msg.no.paren.parms"); } else if (matchToken(Token.LP)) { memberExprNode = memberExpr(false); mustMatchToken(Token.LP, "msg.no.paren.parms"); defineSymbol(Token.FUNCTION, name.getIdentifier()); if (insideFunction() || nestingOfWith > 0) { fnNode.setJsDoc(getAndResetJsDoc()); parseFunctionParams(fnNode); fnNode.setBody(parseFunctionBody()); fnNode.setEncodedSourceBounds(functionSourceStart, ts.tokenEnd); fnNode.setLength(ts.tokenEnd - functionSourceStart); ? "msg.no.return.value" : "msg.anon.no.return.value";
int tt = peekToken(), lineno = ts.lineno; AstNode pn; pn = primaryExpr(); } else { consumeToken(); int pos = ts.tokenBeg; NewExpression nx = new NewExpression(pos); AstNode target = memberExpr(false); int end = getNodeEnd(target); nx.setTarget(target); if (matchToken(Token.LP)) { lp = ts.tokenBeg; List<AstNode> args = argumentList(); if (args != null && args.size() > ARGC_LIMIT) reportError("msg.too.many.constructor.args"); int rp = ts.tokenBeg; end = ts.tokenEnd; if (matchToken(Token.LC)) { ObjectLiteral initializer = objectLiteral(); end = getNodeEnd(initializer); nx.setInitializer(initializer); AstNode tail = memberExprTail(allowCallSyntax, pn); tail.setLineno(lineno); return tail;
if (currentToken != Token.LB) codeBug(); int pos = ts.tokenBeg, end = ts.tokenEnd; List<AstNode> elements = new ArrayList<AstNode>(); int skipCount = 0; for (;;) { int tt = peekToken(); if (tt == Token.COMMA) { consumeToken(); afterComma = ts.tokenEnd; if (!after_lb_or_comma) { consumeToken(); pn.setSkipCount(skipCount); if (afterComma != -1) warnTrailingComma("msg.array.trailing.comma", pos, elements, afterComma); break; } else if (tt == Token.FOR && !after_lb_or_comma && elements.size() == 1) { return arrayComprehension(elements.get(0), pos); } else if (tt == Token.EOF) { end = ts.tokenBeg; } else { if (!after_lb_or_comma) { reportError("msg.no.bracket.arg");
private AstNode expr() throws IOException { AstNode pn = assignExpr(); int pos = pn.getPosition(); while (matchToken(Token.COMMA)) { int opPos = ts.tokenBeg; if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) addStrictWarning("msg.no.side.effects", "", pos, nodeEnd(pn) - pos); if (peekToken() == Token.YIELD) reportError("msg.yield.parenthesized"); pn = new InfixExpression(Token.COMMA, pn, assignExpr(), opPos); } return pn; }
AstNode pn = statementHelper(); if (pn != null) { if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) { int beg = pn.getPosition(); beg = Math.max(beg, lineBeginningFor(beg)); addStrictWarning(pn instanceof EmptyExpression ? "msg.extra.trailing.semi" : "msg.no.side.effects", "", beg, nodeEnd(pn) - beg); int tt = peekTokenOrEOL(); consumeToken(); switch (tt) { case Token.ERROR:
private String instrument(final int lineNumber, final ScriptData data) { final Parser parser = new Parser(); final String sourceUriAsString = data.getSourceUriAsString(); final AstRoot root = parser.parse(data.getSourceCode(), sourceUriAsString, lineNumber); root.visit(new InstrumentingNodeVisitor(data, lineNumber - 1)); final String treeSource = root.toSource(); final StringBuilder buf = new StringBuilder( INITIALIZING_CODE.length() + data.getNumberOfStatements() * ARRAY_INITIALIZER.length() + treeSource.length()); buf.append(COMPLETION_MONITOR); buf.append(INITIALIZING_CODE); buf.append(String.format("if(!%s['%s']) {%n", COVERAGE_VARIABLE_NAME, sourceUriAsString)); buf.append(String.format(" %s['%s'] = {};%n", COVERAGE_VARIABLE_NAME, sourceUriAsString)); for (final Integer i : data.getLineNumbersOfAllStatements()) { buf.append(String.format(ARRAY_INITIALIZER, sourceUriAsString, i)); } buf.append(String.format("}%n")); buf.append(treeSource); return buf.toString(); }
while (peekToken() == Token.FOR) { loops.add(arrayComprehensionLoop()); if (peekToken() == Token.IF) { consumeToken(); ifPos = ts.tokenBeg - pos; data = condition(); mustMatchToken(Token.RB, "msg.no.bracket.arg"); ArrayComprehension pn = new ArrayComprehension(pos, ts.tokenEnd - pos); pn.setResult(result);
return; } else { codeBug(); || (definingScope == currentScope && symDeclType == Token.LET))) addError(symDeclType == Token.CONST ? "msg.const.redecl" : symDeclType == Token.LET ? "msg.let.redecl" : symDeclType == Token.VAR ? "msg.var.redecl" : ((currentScope.getType() == Token.IF) || currentScope instanceof Loop)) { addError("msg.let.decl.not.in.block"); return; if (symbol != null) { if (symDeclType == Token.VAR) addStrictWarning("msg.var.redecl", name); else if (symDeclType == Token.LP) { addStrictWarning("msg.var.hides.arg", name); addWarning("msg.dup.parms", name); throw codeBug();
private ConditionData condition() throws IOException { ConditionData data = new ConditionData(); if (mustMatchToken(Token.LP, "msg.no.paren.cond")) data.lp = ts.tokenBeg; data.condition = expr(); if (mustMatchToken(Token.RP, "msg.no.paren.after.cond")) data.rp = ts.tokenBeg; // Report strict warning on code like "if (a = 7) ...". Suppress the // warning if the condition is parenthesized, like "if ((a = 7)) ...". if (data.condition instanceof Assignment) { addStrictWarning("msg.equal.as.assign", "", data.condition.getPosition(), data.condition.getLength()); } return data; }
private void warnMissingSemi(int pos, int end) { // Should probably change this to be a CompilerEnvirons setting, // with an enum Never, Always, Permissive, where Permissive means // don't warn for 1-line functions like function (s) {return x+2} if (compilerEnv.isStrictMode()) { int beg = Math.max(pos, lineBeginningFor(end)); if (end == -1) end = ts.cursor; addStrictWarning("msg.missing.semi", "", beg, end - beg); } }
private void warnTrailingComma(String messageId, int pos, List<?> elems, int commaPos) { if (compilerEnv.getWarnTrailingComma()) { // back up from comma to beginning of line or array/objlit if (!elems.isEmpty()) { pos = ((AstNode)elems.get(0)).getPosition(); } pos = Math.max(pos, lineBeginningFor(commaPos)); addWarning("msg.extra.trailing.comma", pos, commaPos - pos); } }
/** * Builds a parse tree from the given source string. * * @return an {@link AstRoot} object representing the parsed program. If * the parse fails, {@code null} will be returned. (The parse failure will * result in a call to the {@link ErrorReporter} from * {@link CompilerEnvirons}.) */ public AstRoot parse(String sourceString, String sourceURI, int lineno) { if (parseFinished) throw new IllegalStateException("parser reused"); this.sourceURI = sourceURI; if (compilerEnv.isIdeMode()) { this.sourceChars = sourceString.toCharArray(); } this.ts = new TokenStream(this, null, sourceString, lineno); try { return parse(); } catch (IOException iox) { // Should never happen throw new IllegalStateException(); } finally { parseFinished = true; } }