9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.parser;
27
28 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX;
30 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
31 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
32 import static jdk.nashorn.internal.parser.TokenType.CASE;
33 import static jdk.nashorn.internal.parser.TokenType.CATCH;
34 import static jdk.nashorn.internal.parser.TokenType.COLON;
35 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
36 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
37 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
38 import static jdk.nashorn.internal.parser.TokenType.ELSE;
39 import static jdk.nashorn.internal.parser.TokenType.EOF;
40 import static jdk.nashorn.internal.parser.TokenType.EOL;
41 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
42 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
43 import static jdk.nashorn.internal.parser.TokenType.IDENT;
44 import static jdk.nashorn.internal.parser.TokenType.IF;
45 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
46 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
47 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
48 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
49 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
372 */
373 private Block newBlock() {
374 return lc.push(new Block(token, Token.descPosition(token)));
375 }
376
377 /**
378 * Set up a new function block.
379 *
380 * @param ident Name of function.
381 * @return New block.
382 */
383 private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
384 // Build function name.
385 final StringBuilder sb = new StringBuilder();
386
387 final FunctionNode parentFunction = lc.getCurrentFunction();
388 if (parentFunction != null && !parentFunction.isProgram()) {
389 sb.append(parentFunction.getName()).append('$');
390 }
391
392 sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.symbolName());
393 final String name = namespace.uniqueName(sb.toString());
394 assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript().
395
396 int flags = 0;
397 if (parentFunction == null) {
398 flags |= FunctionNode.IS_PROGRAM;
399 }
400 if (isStrictMode) {
401 flags |= FunctionNode.IS_STRICT;
402 }
403 if (env._specialize_calls != null) {
404 if (env._specialize_calls.contains(name)) {
405 flags |= FunctionNode.CAN_SPECIALIZE;
406 }
407 }
408
409 // Start new block.
410 FunctionNode functionNode =
411 new FunctionNode(
412 source,
413 line, //TODO?
414 token,
415 Token.descPosition(token),
416 startToken,
417 namespace,
418 ident,
419 name,
420 parameters,
421 kind,
422 flags);
423
424 lc.push(functionNode);
425 // Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
426 // FunctionNode.
427 newBlock();
428
429 return functionNode;
430 }
431
432 /**
433 * Restore the current block.
434 */
435 private Block restoreBlock(final Block block) {
436 return lc.pop(block);
437 }
438
439
440 private FunctionNode restoreFunctionNode(final FunctionNode functionNode, final long lastToken) {
441 final Block newBody = restoreBlock(lc.getFunctionBody(functionNode));
442
621 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
622 // Set up the script to append elements.
623
624 FunctionNode script = newFunctionNode(
625 functionToken,
626 new IdentNode(functionToken, Token.descPosition(functionToken), scriptName),
627 new ArrayList<IdentNode>(),
628 FunctionNode.Kind.SCRIPT);
629
630 functionDeclarations = new ArrayList<>();
631 sourceElements();
632 addFunctionDeclarations(script);
633 functionDeclarations = null;
634
635 expect(EOF);
636
637 script.setFinish(source.getLength() - 1);
638
639 script = restoreFunctionNode(script, token); //commit code
640 script = script.setBody(lc, script.getBody().setNeedsScope(lc));
641
642 return script;
643 }
644
645 /**
646 * Directive value or null if statement is not a directive.
647 *
648 * @param stmt Statement to be checked
649 * @return Directive value if the given statement is a directive
650 */
651 private String getDirective(final Node stmt) {
652 if (stmt instanceof ExpressionStatement) {
653 final Node expr = ((ExpressionStatement)stmt).getExpression();
654 if (expr instanceof LiteralNode) {
655 final LiteralNode<?> lit = (LiteralNode<?>)expr;
656 final long litToken = lit.getToken();
657 final TokenType tt = Token.descType(litToken);
658 // A directive is either a string or an escape string
659 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
660 // Make sure that we don't unescape anything. Return as seen in source!
1775 * Literal
1776 * ArrayLiteral
1777 * ObjectLiteral
1778 * ( Expression )
1779 *
1780 * See 11.1
1781 *
1782 * Parse primary expression.
1783 * @return Expression node.
1784 */
1785 @SuppressWarnings("fallthrough")
1786 private Expression primaryExpression() {
1787 // Capture first token.
1788 final int primaryLine = line;
1789 final long primaryToken = token;
1790
1791 switch (type) {
1792 case THIS:
1793 final String name = type.getName();
1794 next();
1795 return new IdentNode(primaryToken, finish, name);
1796 case IDENT:
1797 final IdentNode ident = getIdent();
1798 if (ident == null) {
1799 break;
1800 }
1801 detectSpecialProperty(ident);
1802 return ident;
1803 case OCTAL:
1804 if (isStrictMode) {
1805 throw error(AbstractParser.message("strict.no.octal"), token);
1806 }
1807 case STRING:
1808 case ESCSTRING:
1809 case DECIMAL:
1810 case HEXADECIMAL:
1811 case FLOATING:
1812 case REGEX:
1813 case XML:
1814 return getLiteral();
2115 final String ident = (String)expectValue(IDENT);
2116
2117 if (type != COLON) {
2118 final long getSetToken = propertyToken;
2119
2120 switch (ident) {
2121 case "get":
2122 final PropertyKey getIdent = propertyName();
2123 final String getterName = getIdent.getPropertyName();
2124 final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2125 expect(LPAREN);
2126 expect(RPAREN);
2127 functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER);
2128 return new PropertyNode(propertyToken, finish, getIdent, null, functionNode, null);
2129
2130 case "set":
2131 final PropertyKey setIdent = propertyName();
2132 final String setterName = setIdent.getPropertyName();
2133 final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2134 expect(LPAREN);
2135 final IdentNode argIdent = getIdent();
2136 verifyStrictIdent(argIdent, "setter argument");
2137 expect(RPAREN);
2138 List<IdentNode> parameters = new ArrayList<>();
2139 parameters.add(argIdent);
2140 functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
2141 return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
2142
2143 default:
2144 break;
2145 }
2146 }
2147
2148 propertyName = new IdentNode(propertyToken, finish, ident).setIsPropertyName();
2149 } else {
2150 propertyName = propertyName();
2151 }
2152
2153 expect(COLON);
2154
2155 return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2156 }
2157
2158 /**
2159 * LeftHandSideExpression :
2431 final long functionToken = token;
2432 final int functionLine = line;
2433 // FUNCTION is tested in caller.
2434 next();
2435
2436 IdentNode name = null;
2437
2438 if (type == IDENT || isNonStrictModeIdent()) {
2439 name = getIdent();
2440 verifyStrictIdent(name, "function name");
2441 } else if (isStatement) {
2442 // Nashorn extension: anonymous function statements
2443 if (env._no_syntax_extensions) {
2444 expect(IDENT);
2445 }
2446 }
2447
2448 // name is null, generate anonymous name
2449 boolean isAnonymous = false;
2450 if (name == null) {
2451 final String tmpName = "_L" + functionLine;
2452 name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2453 isAnonymous = true;
2454 }
2455
2456 expect(LPAREN);
2457 final List<IdentNode> parameters = formalParameterList();
2458 expect(RPAREN);
2459
2460 FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL);
2461
2462 if (isStatement) {
2463 if (topLevel) {
2464 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
2465 } else if (isStrictMode) {
2466 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2467 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2468 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2469 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2470 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2471 }
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.parser;
27
28 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
30 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
31 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
32 import static jdk.nashorn.internal.parser.TokenType.CASE;
33 import static jdk.nashorn.internal.parser.TokenType.CATCH;
34 import static jdk.nashorn.internal.parser.TokenType.COLON;
35 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
36 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
37 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
38 import static jdk.nashorn.internal.parser.TokenType.ELSE;
39 import static jdk.nashorn.internal.parser.TokenType.EOF;
40 import static jdk.nashorn.internal.parser.TokenType.EOL;
41 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
42 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
43 import static jdk.nashorn.internal.parser.TokenType.IDENT;
44 import static jdk.nashorn.internal.parser.TokenType.IF;
45 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
46 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
47 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
48 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
49 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
372 */
373 private Block newBlock() {
374 return lc.push(new Block(token, Token.descPosition(token)));
375 }
376
377 /**
378 * Set up a new function block.
379 *
380 * @param ident Name of function.
381 * @return New block.
382 */
383 private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
384 // Build function name.
385 final StringBuilder sb = new StringBuilder();
386
387 final FunctionNode parentFunction = lc.getCurrentFunction();
388 if (parentFunction != null && !parentFunction.isProgram()) {
389 sb.append(parentFunction.getName()).append('$');
390 }
391
392 assert ident.getName() != null;
393 sb.append(ident.getName());
394
395 final String name = namespace.uniqueName(sb.toString());
396 assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript().
397
398 int flags = 0;
399 if (parentFunction == null) {
400 flags |= FunctionNode.IS_PROGRAM;
401 }
402 if (isStrictMode) {
403 flags |= FunctionNode.IS_STRICT;
404 }
405 if (env._specialize_calls != null) {
406 if (env._specialize_calls.contains(name)) {
407 flags |= FunctionNode.CAN_SPECIALIZE;
408 }
409 }
410
411 // Start new block.
412 FunctionNode functionNode =
413 new FunctionNode(
414 source,
415 line, //TODO?
416 token,
417 Token.descPosition(token),
418 startToken,
419 namespace,
420 ident,
421 name,
422 parameters,
423 kind,
424 flags,
425 sourceURL);
426
427 lc.push(functionNode);
428 // Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
429 // FunctionNode.
430 newBlock();
431
432 return functionNode;
433 }
434
435 /**
436 * Restore the current block.
437 */
438 private Block restoreBlock(final Block block) {
439 return lc.pop(block);
440 }
441
442
443 private FunctionNode restoreFunctionNode(final FunctionNode functionNode, final long lastToken) {
444 final Block newBody = restoreBlock(lc.getFunctionBody(functionNode));
445
624 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
625 // Set up the script to append elements.
626
627 FunctionNode script = newFunctionNode(
628 functionToken,
629 new IdentNode(functionToken, Token.descPosition(functionToken), scriptName),
630 new ArrayList<IdentNode>(),
631 FunctionNode.Kind.SCRIPT);
632
633 functionDeclarations = new ArrayList<>();
634 sourceElements();
635 addFunctionDeclarations(script);
636 functionDeclarations = null;
637
638 expect(EOF);
639
640 script.setFinish(source.getLength() - 1);
641
642 script = restoreFunctionNode(script, token); //commit code
643 script = script.setBody(lc, script.getBody().setNeedsScope(lc));
644 // user may have directive comment to set sourceURL
645 if (sourceURL != null) {
646 script = script.setSourceURL(lc, sourceURL);
647 }
648
649 return script;
650 }
651
652 /**
653 * Directive value or null if statement is not a directive.
654 *
655 * @param stmt Statement to be checked
656 * @return Directive value if the given statement is a directive
657 */
658 private String getDirective(final Node stmt) {
659 if (stmt instanceof ExpressionStatement) {
660 final Node expr = ((ExpressionStatement)stmt).getExpression();
661 if (expr instanceof LiteralNode) {
662 final LiteralNode<?> lit = (LiteralNode<?>)expr;
663 final long litToken = lit.getToken();
664 final TokenType tt = Token.descType(litToken);
665 // A directive is either a string or an escape string
666 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
667 // Make sure that we don't unescape anything. Return as seen in source!
1782 * Literal
1783 * ArrayLiteral
1784 * ObjectLiteral
1785 * ( Expression )
1786 *
1787 * See 11.1
1788 *
1789 * Parse primary expression.
1790 * @return Expression node.
1791 */
1792 @SuppressWarnings("fallthrough")
1793 private Expression primaryExpression() {
1794 // Capture first token.
1795 final int primaryLine = line;
1796 final long primaryToken = token;
1797
1798 switch (type) {
1799 case THIS:
1800 final String name = type.getName();
1801 next();
1802 lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS);
1803 return new IdentNode(primaryToken, finish, name);
1804 case IDENT:
1805 final IdentNode ident = getIdent();
1806 if (ident == null) {
1807 break;
1808 }
1809 detectSpecialProperty(ident);
1810 return ident;
1811 case OCTAL:
1812 if (isStrictMode) {
1813 throw error(AbstractParser.message("strict.no.octal"), token);
1814 }
1815 case STRING:
1816 case ESCSTRING:
1817 case DECIMAL:
1818 case HEXADECIMAL:
1819 case FLOATING:
1820 case REGEX:
1821 case XML:
1822 return getLiteral();
2123 final String ident = (String)expectValue(IDENT);
2124
2125 if (type != COLON) {
2126 final long getSetToken = propertyToken;
2127
2128 switch (ident) {
2129 case "get":
2130 final PropertyKey getIdent = propertyName();
2131 final String getterName = getIdent.getPropertyName();
2132 final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2133 expect(LPAREN);
2134 expect(RPAREN);
2135 functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER);
2136 return new PropertyNode(propertyToken, finish, getIdent, null, functionNode, null);
2137
2138 case "set":
2139 final PropertyKey setIdent = propertyName();
2140 final String setterName = setIdent.getPropertyName();
2141 final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2142 expect(LPAREN);
2143 // be sloppy and allow missing setter parameter even though
2144 // spec does not permit it!
2145 final IdentNode argIdent;
2146 if (type == IDENT || isNonStrictModeIdent()) {
2147 argIdent = getIdent();
2148 verifyStrictIdent(argIdent, "setter argument");
2149 } else {
2150 argIdent = null;
2151 }
2152 expect(RPAREN);
2153 List<IdentNode> parameters = new ArrayList<>();
2154 if (argIdent != null) {
2155 parameters.add(argIdent);
2156 }
2157 functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
2158 return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
2159
2160 default:
2161 break;
2162 }
2163 }
2164
2165 propertyName = new IdentNode(propertyToken, finish, ident).setIsPropertyName();
2166 } else {
2167 propertyName = propertyName();
2168 }
2169
2170 expect(COLON);
2171
2172 return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2173 }
2174
2175 /**
2176 * LeftHandSideExpression :
2448 final long functionToken = token;
2449 final int functionLine = line;
2450 // FUNCTION is tested in caller.
2451 next();
2452
2453 IdentNode name = null;
2454
2455 if (type == IDENT || isNonStrictModeIdent()) {
2456 name = getIdent();
2457 verifyStrictIdent(name, "function name");
2458 } else if (isStatement) {
2459 // Nashorn extension: anonymous function statements
2460 if (env._no_syntax_extensions) {
2461 expect(IDENT);
2462 }
2463 }
2464
2465 // name is null, generate anonymous name
2466 boolean isAnonymous = false;
2467 if (name == null) {
2468 final String tmpName = ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2469 name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2470 isAnonymous = true;
2471 }
2472
2473 expect(LPAREN);
2474 final List<IdentNode> parameters = formalParameterList();
2475 expect(RPAREN);
2476
2477 FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL);
2478
2479 if (isStatement) {
2480 if (topLevel) {
2481 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
2482 } else if (isStrictMode) {
2483 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2484 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2485 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2486 } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2487 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2488 }
|