60 import java.util.Collections;
61 import java.util.Deque;
62 import java.util.HashMap;
63 import java.util.HashSet;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Map;
67 import jdk.internal.dynalink.support.NameCodec;
68 import jdk.nashorn.internal.codegen.CompilerConstants;
69 import jdk.nashorn.internal.codegen.Namespace;
70 import jdk.nashorn.internal.ir.AccessNode;
71 import jdk.nashorn.internal.ir.BaseNode;
72 import jdk.nashorn.internal.ir.BinaryNode;
73 import jdk.nashorn.internal.ir.Block;
74 import jdk.nashorn.internal.ir.BlockStatement;
75 import jdk.nashorn.internal.ir.BreakNode;
76 import jdk.nashorn.internal.ir.CallNode;
77 import jdk.nashorn.internal.ir.CaseNode;
78 import jdk.nashorn.internal.ir.CatchNode;
79 import jdk.nashorn.internal.ir.ContinueNode;
80 import jdk.nashorn.internal.ir.EmptyNode;
81 import jdk.nashorn.internal.ir.Expression;
82 import jdk.nashorn.internal.ir.ExpressionStatement;
83 import jdk.nashorn.internal.ir.ForNode;
84 import jdk.nashorn.internal.ir.FunctionNode;
85 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
86 import jdk.nashorn.internal.ir.IdentNode;
87 import jdk.nashorn.internal.ir.IfNode;
88 import jdk.nashorn.internal.ir.IndexNode;
89 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
90 import jdk.nashorn.internal.ir.LabelNode;
91 import jdk.nashorn.internal.ir.LiteralNode;
92 import jdk.nashorn.internal.ir.Node;
93 import jdk.nashorn.internal.ir.ObjectNode;
94 import jdk.nashorn.internal.ir.PropertyKey;
95 import jdk.nashorn.internal.ir.PropertyNode;
96 import jdk.nashorn.internal.ir.ReturnNode;
97 import jdk.nashorn.internal.ir.RuntimeNode;
98 import jdk.nashorn.internal.ir.Statement;
99 import jdk.nashorn.internal.ir.SwitchNode;
100 import jdk.nashorn.internal.ir.TernaryNode;
339 next();
340
341 // Make a fake token for the function.
342 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
343 // Set up the function to append elements.
344
345 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
346 final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
347 lc.push(function);
348
349 final ParserContextBlockNode body = newBlock();
350
351 functionDeclarations = new ArrayList<>();
352 sourceElements(false);
353 addFunctionDeclarations(function);
354 functionDeclarations = null;
355
356 restoreBlock(body);
357 body.setFlag(Block.NEEDS_SCOPE);
358
359 final Block functionBody = new Block(functionToken, source.getLength() - 1, body.getFlags(), body.getStatements());
360 lc.pop(function);
361
362 expect(EOF);
363
364 final FunctionNode functionNode = createFunctionNode(
365 function,
366 functionToken,
367 ident,
368 Collections.<IdentNode>emptyList(),
369 FunctionNode.Kind.NORMAL,
370 functionLine,
371 functionBody);
372 printAST(functionNode);
373 return functionNode;
374 } catch (final Exception e) {
375 handleParseException(e);
376 return null;
377 }
378 }
379
523 private Block getBlock(final boolean needsBraces) {
524 final long blockToken = token;
525 final ParserContextBlockNode newBlock = newBlock();
526 try {
527 // Block opening brace.
528 if (needsBraces) {
529 expect(LBRACE);
530 }
531 // Accumulate block statements.
532 statementList();
533
534 } finally {
535 restoreBlock(newBlock);
536 }
537
538 // Block closing brace.
539 if (needsBraces) {
540 expect(RBRACE);
541 }
542
543 return new Block(blockToken, finish, newBlock.getFlags(), newBlock.getStatements());
544 }
545
546
547 /**
548 * Get all the statements generated by a single statement.
549 * @return Statements.
550 */
551 private Block getStatement() {
552 if (type == LBRACE) {
553 return getBlock(true);
554 }
555 // Set up new block. Captures first token.
556 final ParserContextBlockNode newBlock = newBlock();
557 try {
558 statement(false, false, true);
559 } finally {
560 restoreBlock(newBlock);
561 }
562 return new Block(newBlock.getToken(), finish, newBlock.getFlags(), newBlock.getStatements());
563 }
564
565 /**
566 * Detect calls to special functions.
567 * @param ident Called function.
568 */
569 private void detectSpecialFunction(final IdentNode ident) {
570 final String name = ident.getName();
571
572 if (EVAL.symbolName().equals(name)) {
573 markEval(lc);
574 }
575 }
576
577 /**
578 * Detect use of special properties.
579 * @param ident Referenced property.
580 */
581 private void detectSpecialProperty(final IdentNode ident) {
582 if (isArguments(ident)) {
695 final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
696 final int functionLine = line;
697
698 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
699 final ParserContextFunctionNode script = createParserContextFunctionNode(
700 ident,
701 functionToken,
702 FunctionNode.Kind.SCRIPT,
703 functionLine,
704 Collections.<IdentNode>emptyList());
705 lc.push(script);
706 final ParserContextBlockNode body = newBlock();
707
708 functionDeclarations = new ArrayList<>();
709 sourceElements(allowPropertyFunction);
710 addFunctionDeclarations(script);
711 functionDeclarations = null;
712
713 restoreBlock(body);
714 body.setFlag(Block.NEEDS_SCOPE);
715 final Block programBody = new Block(functionToken, functionLine, body.getFlags(), body.getStatements());
716 lc.pop(script);
717 script.setLastToken(token);
718
719 expect(EOF);
720
721 return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
722 }
723
724 /**
725 * Directive value or null if statement is not a directive.
726 *
727 * @param stmt Statement to be checked
728 * @return Directive value if the given statement is a directive
729 */
730 private String getDirective(final Node stmt) {
731 if (stmt instanceof ExpressionStatement) {
732 final Node expr = ((ExpressionStatement)stmt).getExpression();
733 if (expr instanceof LiteralNode) {
734 final LiteralNode<?> lit = (LiteralNode<?>)expr;
735 final long litToken = lit.getToken();
809 getValue(statement.getToken());
810 }
811
812 // verify that function name as well as parameter names
813 // satisfy strict mode restrictions.
814 verifyStrictIdent(function.getIdent(), "function name");
815 for (final IdentNode param : function.getParameters()) {
816 verifyStrictIdent(param, "function parameter");
817 }
818 }
819 } else if (Context.DEBUG) {
820 final int flag = FunctionNode.getDirectiveFlag(directive);
821 if (flag != 0) {
822 final ParserContextFunctionNode function = lc.getCurrentFunction();
823 function.setFlag(flag);
824 }
825 }
826 }
827 }
828 } catch (final Exception e) {
829 //recover parsing
830 recover(e);
831 }
832
833 // No backtracking from here on.
834 stream.commit(k);
835 }
836 } finally {
837 isStrictMode = oldStrictMode;
838 }
839 }
840
841 /**
842 * Statement :
843 * Block
844 * VariableStatement
845 * EmptyStatement
846 * ExpressionStatement
847 * IfStatement
848 * IterationStatement
849 * ContinueStatement
850 * BreakStatement
1836 // catch clause each with it's own condition.
1837 final Expression ifExpression;
1838 if (!env._no_syntax_extensions && type == IF) {
1839 next();
1840 // Get the exception condition.
1841 ifExpression = expression();
1842 } else {
1843 ifExpression = null;
1844 }
1845
1846 expect(RPAREN);
1847
1848 final ParserContextBlockNode catchBlock = newBlock();
1849 try {
1850 // Get CATCH body.
1851 final Block catchBody = getBlock(true);
1852 final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1853 appendStatement(catchNode);
1854 } finally {
1855 restoreBlock(catchBlock);
1856 catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags(), catchBlock.getStatements()));
1857 }
1858
1859 // If unconditional catch then should to be the end.
1860 if (ifExpression == null) {
1861 break;
1862 }
1863 }
1864
1865 // Prepare to capture finally statement.
1866 Block finallyStatements = null;
1867
1868 if (type == FINALLY) {
1869 next();
1870 finallyStatements = getBlock(true);
1871 }
1872
1873 // Need at least one catch or a finally.
1874 if (catchBlocks.isEmpty() && finallyStatements == null) {
1875 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1876 }
1877
1878 final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1879 // Add try.
1880 assert lc.peek() == outer;
1881 appendStatement(tryNode);
1882 } finally {
1883 restoreBlock(outer);
1884 }
1885
1886 appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags(), outer.getStatements())));
1887 }
1888
1889 /**
1890 * DebuggerStatement :
1891 * debugger ;
1892 *
1893 * See 12.15
1894 *
1895 * Parse debugger statement.
1896 */
1897 private void debuggerStatement() {
1898 // Capture DEBUGGER token.
1899 final int debuggerLine = line;
1900 final long debuggerToken = token;
1901 // DEBUGGER tested in caller.
1902 next();
1903 endOfLine();
1904 appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, Collections.<Expression>emptyList())));
1905 }
1906
1907 /**
1908 * PrimaryExpression :
1909 * this
1910 * Identifier
1911 * Literal
1912 * ArrayLiteral
1913 * ObjectLiteral
1914 * ( Expression )
1915 *
1916 * See 11.1
1917 *
1918 * Parse primary expression.
1919 * @return Expression node.
1920 */
1921 @SuppressWarnings("fallthrough")
1922 private Expression primaryExpression() {
1923 // Capture first token.
1924 final int primaryLine = line;
2864
2865 parameters.trimToSize();
2866 return parameters;
2867 }
2868
2869 /**
2870 * FunctionBody :
2871 * SourceElements?
2872 *
2873 * See 13
2874 *
2875 * Parse function body.
2876 * @return function node (body.)
2877 */
2878 private Block functionBody(final ParserContextFunctionNode functionNode) {
2879 long lastToken = 0L;
2880 ParserContextBlockNode body = null;
2881 final long bodyToken = token;
2882 Block functionBody;
2883 int bodyFinish = 0;
2884
2885
2886 final boolean parseBody;
2887 Object endParserState = null;
2888 try {
2889 // Create a new function block.
2890 body = newBlock();
2891 assert functionNode != null;
2892 final int functionId = functionNode.getId();
2893 parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2894 // Nashorn extension: expression closures
2895 if (!env._no_syntax_extensions && type != LBRACE) {
2896 /*
2897 * Example:
2898 *
2899 * function square(x) x * x;
2900 * print(square(3));
2901 */
2902
2903 // just expression as function body
2904 final Expression expr = assignmentExpression(true);
|
60 import java.util.Collections;
61 import java.util.Deque;
62 import java.util.HashMap;
63 import java.util.HashSet;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Map;
67 import jdk.internal.dynalink.support.NameCodec;
68 import jdk.nashorn.internal.codegen.CompilerConstants;
69 import jdk.nashorn.internal.codegen.Namespace;
70 import jdk.nashorn.internal.ir.AccessNode;
71 import jdk.nashorn.internal.ir.BaseNode;
72 import jdk.nashorn.internal.ir.BinaryNode;
73 import jdk.nashorn.internal.ir.Block;
74 import jdk.nashorn.internal.ir.BlockStatement;
75 import jdk.nashorn.internal.ir.BreakNode;
76 import jdk.nashorn.internal.ir.CallNode;
77 import jdk.nashorn.internal.ir.CaseNode;
78 import jdk.nashorn.internal.ir.CatchNode;
79 import jdk.nashorn.internal.ir.ContinueNode;
80 import jdk.nashorn.internal.ir.DebuggerNode;
81 import jdk.nashorn.internal.ir.EmptyNode;
82 import jdk.nashorn.internal.ir.ErrorNode;
83 import jdk.nashorn.internal.ir.Expression;
84 import jdk.nashorn.internal.ir.ExpressionStatement;
85 import jdk.nashorn.internal.ir.ForNode;
86 import jdk.nashorn.internal.ir.FunctionNode;
87 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
88 import jdk.nashorn.internal.ir.IdentNode;
89 import jdk.nashorn.internal.ir.IfNode;
90 import jdk.nashorn.internal.ir.IndexNode;
91 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
92 import jdk.nashorn.internal.ir.LabelNode;
93 import jdk.nashorn.internal.ir.LiteralNode;
94 import jdk.nashorn.internal.ir.Node;
95 import jdk.nashorn.internal.ir.ObjectNode;
96 import jdk.nashorn.internal.ir.PropertyKey;
97 import jdk.nashorn.internal.ir.PropertyNode;
98 import jdk.nashorn.internal.ir.ReturnNode;
99 import jdk.nashorn.internal.ir.RuntimeNode;
100 import jdk.nashorn.internal.ir.Statement;
101 import jdk.nashorn.internal.ir.SwitchNode;
102 import jdk.nashorn.internal.ir.TernaryNode;
341 next();
342
343 // Make a fake token for the function.
344 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
345 // Set up the function to append elements.
346
347 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
348 final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
349 lc.push(function);
350
351 final ParserContextBlockNode body = newBlock();
352
353 functionDeclarations = new ArrayList<>();
354 sourceElements(false);
355 addFunctionDeclarations(function);
356 functionDeclarations = null;
357
358 restoreBlock(body);
359 body.setFlag(Block.NEEDS_SCOPE);
360
361 final Block functionBody = new Block(functionToken, source.getLength() - 1,
362 body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
363 lc.pop(function);
364
365 expect(EOF);
366
367 final FunctionNode functionNode = createFunctionNode(
368 function,
369 functionToken,
370 ident,
371 Collections.<IdentNode>emptyList(),
372 FunctionNode.Kind.NORMAL,
373 functionLine,
374 functionBody);
375 printAST(functionNode);
376 return functionNode;
377 } catch (final Exception e) {
378 handleParseException(e);
379 return null;
380 }
381 }
382
526 private Block getBlock(final boolean needsBraces) {
527 final long blockToken = token;
528 final ParserContextBlockNode newBlock = newBlock();
529 try {
530 // Block opening brace.
531 if (needsBraces) {
532 expect(LBRACE);
533 }
534 // Accumulate block statements.
535 statementList();
536
537 } finally {
538 restoreBlock(newBlock);
539 }
540
541 // Block closing brace.
542 if (needsBraces) {
543 expect(RBRACE);
544 }
545
546 final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC);
547 return new Block(blockToken, finish, flags, newBlock.getStatements());
548 }
549
550
551 /**
552 * Get all the statements generated by a single statement.
553 * @return Statements.
554 */
555 private Block getStatement() {
556 if (type == LBRACE) {
557 return getBlock(true);
558 }
559 // Set up new block. Captures first token.
560 final ParserContextBlockNode newBlock = newBlock();
561 try {
562 statement(false, false, true);
563 } finally {
564 restoreBlock(newBlock);
565 }
566 return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
567 }
568
569 /**
570 * Detect calls to special functions.
571 * @param ident Called function.
572 */
573 private void detectSpecialFunction(final IdentNode ident) {
574 final String name = ident.getName();
575
576 if (EVAL.symbolName().equals(name)) {
577 markEval(lc);
578 }
579 }
580
581 /**
582 * Detect use of special properties.
583 * @param ident Referenced property.
584 */
585 private void detectSpecialProperty(final IdentNode ident) {
586 if (isArguments(ident)) {
699 final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
700 final int functionLine = line;
701
702 final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
703 final ParserContextFunctionNode script = createParserContextFunctionNode(
704 ident,
705 functionToken,
706 FunctionNode.Kind.SCRIPT,
707 functionLine,
708 Collections.<IdentNode>emptyList());
709 lc.push(script);
710 final ParserContextBlockNode body = newBlock();
711
712 functionDeclarations = new ArrayList<>();
713 sourceElements(allowPropertyFunction);
714 addFunctionDeclarations(script);
715 functionDeclarations = null;
716
717 restoreBlock(body);
718 body.setFlag(Block.NEEDS_SCOPE);
719 final Block programBody = new Block(functionToken, functionLine, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
720 lc.pop(script);
721 script.setLastToken(token);
722
723 expect(EOF);
724
725 return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
726 }
727
728 /**
729 * Directive value or null if statement is not a directive.
730 *
731 * @param stmt Statement to be checked
732 * @return Directive value if the given statement is a directive
733 */
734 private String getDirective(final Node stmt) {
735 if (stmt instanceof ExpressionStatement) {
736 final Node expr = ((ExpressionStatement)stmt).getExpression();
737 if (expr instanceof LiteralNode) {
738 final LiteralNode<?> lit = (LiteralNode<?>)expr;
739 final long litToken = lit.getToken();
813 getValue(statement.getToken());
814 }
815
816 // verify that function name as well as parameter names
817 // satisfy strict mode restrictions.
818 verifyStrictIdent(function.getIdent(), "function name");
819 for (final IdentNode param : function.getParameters()) {
820 verifyStrictIdent(param, "function parameter");
821 }
822 }
823 } else if (Context.DEBUG) {
824 final int flag = FunctionNode.getDirectiveFlag(directive);
825 if (flag != 0) {
826 final ParserContextFunctionNode function = lc.getCurrentFunction();
827 function.setFlag(flag);
828 }
829 }
830 }
831 }
832 } catch (final Exception e) {
833 final int errorLine = line;
834 final long errorToken = token;
835 //recover parsing
836 recover(e);
837 final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
838 final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
839 appendStatement(expressionStatement);
840 }
841
842 // No backtracking from here on.
843 stream.commit(k);
844 }
845 } finally {
846 isStrictMode = oldStrictMode;
847 }
848 }
849
850 /**
851 * Statement :
852 * Block
853 * VariableStatement
854 * EmptyStatement
855 * ExpressionStatement
856 * IfStatement
857 * IterationStatement
858 * ContinueStatement
859 * BreakStatement
1845 // catch clause each with it's own condition.
1846 final Expression ifExpression;
1847 if (!env._no_syntax_extensions && type == IF) {
1848 next();
1849 // Get the exception condition.
1850 ifExpression = expression();
1851 } else {
1852 ifExpression = null;
1853 }
1854
1855 expect(RPAREN);
1856
1857 final ParserContextBlockNode catchBlock = newBlock();
1858 try {
1859 // Get CATCH body.
1860 final Block catchBody = getBlock(true);
1861 final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1862 appendStatement(catchNode);
1863 } finally {
1864 restoreBlock(catchBlock);
1865 catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
1866 }
1867
1868 // If unconditional catch then should to be the end.
1869 if (ifExpression == null) {
1870 break;
1871 }
1872 }
1873
1874 // Prepare to capture finally statement.
1875 Block finallyStatements = null;
1876
1877 if (type == FINALLY) {
1878 next();
1879 finallyStatements = getBlock(true);
1880 }
1881
1882 // Need at least one catch or a finally.
1883 if (catchBlocks.isEmpty() && finallyStatements == null) {
1884 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1885 }
1886
1887 final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1888 // Add try.
1889 assert lc.peek() == outer;
1890 appendStatement(tryNode);
1891 } finally {
1892 restoreBlock(outer);
1893 }
1894
1895 appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
1896 }
1897
1898 /**
1899 * DebuggerStatement :
1900 * debugger ;
1901 *
1902 * See 12.15
1903 *
1904 * Parse debugger statement.
1905 */
1906 private void debuggerStatement() {
1907 // Capture DEBUGGER token.
1908 final int debuggerLine = line;
1909 final long debuggerToken = token;
1910 // DEBUGGER tested in caller.
1911 next();
1912 endOfLine();
1913 appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
1914 }
1915
1916 /**
1917 * PrimaryExpression :
1918 * this
1919 * Identifier
1920 * Literal
1921 * ArrayLiteral
1922 * ObjectLiteral
1923 * ( Expression )
1924 *
1925 * See 11.1
1926 *
1927 * Parse primary expression.
1928 * @return Expression node.
1929 */
1930 @SuppressWarnings("fallthrough")
1931 private Expression primaryExpression() {
1932 // Capture first token.
1933 final int primaryLine = line;
2873
2874 parameters.trimToSize();
2875 return parameters;
2876 }
2877
2878 /**
2879 * FunctionBody :
2880 * SourceElements?
2881 *
2882 * See 13
2883 *
2884 * Parse function body.
2885 * @return function node (body.)
2886 */
2887 private Block functionBody(final ParserContextFunctionNode functionNode) {
2888 long lastToken = 0L;
2889 ParserContextBlockNode body = null;
2890 final long bodyToken = token;
2891 Block functionBody;
2892 int bodyFinish = 0;
2893
2894 final boolean parseBody;
2895 Object endParserState = null;
2896 try {
2897 // Create a new function block.
2898 body = newBlock();
2899 assert functionNode != null;
2900 final int functionId = functionNode.getId();
2901 parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2902 // Nashorn extension: expression closures
2903 if (!env._no_syntax_extensions && type != LBRACE) {
2904 /*
2905 * Example:
2906 *
2907 * function square(x) x * x;
2908 * print(square(3));
2909 */
2910
2911 // just expression as function body
2912 final Expression expr = assignmentExpression(true);
|