src/jdk/nashorn/internal/parser/Parser.java

Print this page




 542         if (needsBraces) {
 543             expect(RBRACE);
 544         }
 545 
 546         newBlock.setFinish(possibleEnd);
 547 
 548         return newBlock;
 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         Block newBlock = newBlock();
 561         try {
 562             statement();
 563         } finally {
 564             newBlock = restoreBlock(newBlock);
 565         }
 566         return newBlock;
 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.


 755      *
 756      * Parse the elements of the script or function.
 757      */
 758     private void sourceElements(final boolean shouldAllowPropertyFunction) {
 759         List<Node>    directiveStmts        = null;
 760         boolean       checkDirective        = true;
 761         boolean       allowPropertyFunction = shouldAllowPropertyFunction;
 762         final boolean oldStrictMode         = isStrictMode;
 763 
 764 
 765         try {
 766             // If is a script, then process until the end of the script.
 767             while (type != EOF) {
 768                 // Break if the end of a code block.
 769                 if (type == RBRACE) {
 770                     break;
 771                 }
 772 
 773                 try {
 774                     // Get the next element.
 775                     statement(true, allowPropertyFunction);
 776                     allowPropertyFunction = false;
 777 
 778                     // check for directive prologues
 779                     if (checkDirective) {
 780                         // skip any debug statement like line number to get actual first line
 781                         final Node lastStatement = lc.getLastStatement();
 782 
 783                         // get directive prologue, if any
 784                         final String directive = getDirective(lastStatement);
 785 
 786                         // If we have seen first non-directive statement,
 787                         // no more directive statements!!
 788                         checkDirective = directive != null;
 789 
 790                         if (checkDirective) {
 791                             if (!oldStrictMode) {
 792                                 if (directiveStmts == null) {
 793                                     directiveStmts = new ArrayList<>();
 794                                 }
 795                                 directiveStmts.add(lastStatement);


 845      *      VariableStatement
 846      *      EmptyStatement
 847      *      ExpressionStatement
 848      *      IfStatement
 849      *      IterationStatement
 850      *      ContinueStatement
 851      *      BreakStatement
 852      *      ReturnStatement
 853      *      WithStatement
 854      *      LabelledStatement
 855      *      SwitchStatement
 856      *      ThrowStatement
 857      *      TryStatement
 858      *      DebuggerStatement
 859      *
 860      * see 12
 861      *
 862      * Parse any of the basic statement types.
 863      */
 864     private void statement() {
 865         statement(false, false);
 866     }
 867 
 868     /**
 869      * @param topLevel does this statement occur at the "top level" of a script or a function?


 870      */
 871     private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
 872         if (type == FUNCTION) {
 873             // As per spec (ECMA section 12), function declarations as arbitrary statement
 874             // is not "portable". Implementation can issue a warning or disallow the same.
 875             functionExpression(true, topLevel);
 876             return;
 877         }
 878 
 879         switch (type) {
 880         case LBRACE:
 881             block();
 882             break;
 883         case VAR:
 884             variableStatement(type, true);
 885             break;
 886         case SEMICOLON:
 887             emptyStatement();
 888             break;
 889         case IF:
 890             ifStatement();
 891             break;


 915             break;
 916         case SWITCH:
 917             switchStatement();
 918             break;
 919         case THROW:
 920             throwStatement();
 921             break;
 922         case TRY:
 923             tryStatement();
 924             break;
 925         case DEBUGGER:
 926             debuggerStatement();
 927             break;
 928         case RPAREN:
 929         case RBRACKET:
 930         case EOF:
 931             expect(SEMICOLON);
 932             break;
 933         default:
 934             if (useBlockScope() && (type == LET || type == CONST)) {



 935                 variableStatement(type, true);
 936                 break;
 937             }
 938             if (env._const_as_var && type == CONST) {
 939                 variableStatement(TokenType.VAR, true);
 940                 break;
 941             }
 942 
 943             if (type == IDENT || isNonStrictModeIdent()) {
 944                 if (T(k + 1) == COLON) {
 945                     labelStatement();
 946                     return;
 947                 }
 948                 if(allowPropertyFunction) {
 949                     final String ident = (String)getValue();
 950                     final long propertyToken = token;
 951                     final int propertyLine = line;
 952                     if("get".equals(ident)) {
 953                         next();
 954                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));


1040      * VariableDeclarationList :
1041      *      VariableDeclaration
1042      *      VariableDeclarationList , VariableDeclaration
1043      *
1044      * VariableDeclaration :
1045      *      Identifier Initializer?
1046      *
1047      * Initializer :
1048      *      = AssignmentExpression
1049      *
1050      * See 12.2
1051      *
1052      * Parse a VAR statement.
1053      * @param isStatement True if a statement (not used in a FOR.)
1054      */
1055     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1056         // VAR tested in caller.
1057         next();
1058 
1059         final List<VarNode> vars = new ArrayList<>();
1060         int varFlags = VarNode.IS_STATEMENT;
1061         if (varType == LET) {
1062             varFlags |= VarNode.IS_LET;
1063         } else if (varType == CONST) {
1064             varFlags |= VarNode.IS_CONST;
1065         }
1066 
1067         while (true) {
1068             // Get starting token.
1069             final int  varLine  = line;
1070             final long varToken = token;
1071             // Get name of var.
1072             final IdentNode name = getIdent();
1073             verifyStrictIdent(name, "variable name");
1074 
1075             // Assume no init.
1076             Expression init = null;
1077 
1078             // Look for initializer assignment.
1079             if (type == ASSIGN) {
1080                 next();


1193     }
1194 
1195     /**
1196      * ... IterationStatement:
1197      *           ...
1198      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1199      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1200      *           for ( LeftHandSideExpression in Expression ) Statement
1201      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1202      *
1203      * See 12.6
1204      *
1205      * Parse a FOR statement.
1206      */
1207     private void forStatement() {
1208         // When ES6 for-let is enabled we create a container block to capture the LET.
1209         final int startLine = start;
1210         Block outer = useBlockScope() ? newBlock() : null;
1211 
1212         // Create FOR node, capturing FOR token.
1213         ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
1214         lc.push(forNode);
1215 
1216         try {
1217             // FOR tested in caller.
1218             next();
1219 
1220             // Nashorn extension: for each expression.
1221             // iterate property values rather than property names.
1222             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1223                 forNode = forNode.setIsForEach(lc);
1224                 next();
1225             }
1226 
1227             expect(LPAREN);
1228 
1229             List<VarNode> vars = null;
1230 
1231             switch (type) {
1232             case VAR:
1233                 // Var statements captured in for outer block.
1234                 vars = variableStatement(type, false);
1235                 break;
1236             case SEMICOLON:
1237                 break;
1238             default:
1239                 if (useBlockScope() && (type == LET || type == CONST)) {
1240                     // LET/CONST captured in container block created above.



1241                     vars = variableStatement(type, false);
1242                     break;
1243                 }
1244                 if (env._const_as_var && type == CONST) {
1245                     // Var statements captured in for outer block.
1246                     vars = variableStatement(TokenType.VAR, false);
1247                     break;
1248                 }
1249 
1250                 final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1251                 forNode = forNode.setInit(lc, expression);
1252                 break;
1253             }
1254 
1255             switch (type) {
1256             case SEMICOLON:
1257                 // for (init; test; modify)
1258 
1259                 // for each (init; test; modify) is invalid
1260                 if (forNode.isForEach()) {
1261                     throw error(AbstractParser.message("for.each.without.in"), token);
1262                 }
1263 
1264                 expect(SEMICOLON);
1265                 if (type != SEMICOLON) {


1306 
1307                 // Get the collection expression.
1308                 forNode = forNode.setModify(lc, joinPredecessorExpression());
1309                 break;
1310 
1311             default:
1312                 expect(SEMICOLON);
1313                 break;
1314             }
1315 
1316             expect(RPAREN);
1317 
1318             // Set the for body.
1319             final Block body = getStatement();
1320             forNode = forNode.setBody(lc, body);
1321             forNode.setFinish(body.getFinish());
1322 
1323             appendStatement(forNode);
1324         } finally {
1325             lc.pop(forNode);


1326             if (outer != null) {
1327                 outer.setFinish(forNode.getFinish());
1328                 outer = restoreBlock(outer);
1329                 appendStatement(new BlockStatement(startLine, outer));
1330             }
1331         }
1332     }
1333 
1334     /**
1335      * ... IterationStatement :
1336      *           ...
1337      *           Expression[NoIn]?; Expression? ; Expression?
1338      *           var VariableDeclarationList[NoIn]; Expression? ; Expression?
1339      *           LeftHandSideExpression in Expression
1340      *           var VariableDeclaration[NoIn] in Expression
1341      *
1342      * See 12.6
1343      *
1344      * Parse the control section of a FOR statement.  Also used for
1345      * comprehensions.
1346      * @param forNode Owning FOR.
1347      */
1348 
1349 
1350     /**
1351      * ...IterationStatement :
1352      *           ...


2682                 if (parametersSet.contains(parameterName)) {
2683                     // redefinition of parameter name
2684                     if (strict) {
2685                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2686                     }
2687                     // rename in non-strict mode
2688                     parameterName = functionNode.uniqueName(parameterName);
2689                     final long parameterToken = parameter.getToken();
2690                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2691                 }
2692 
2693                 parametersSet.add(parameterName);
2694             }
2695         } else if (arity == 1) {
2696             if (isArguments(parameters.get(0))) {
2697                 functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2698             }
2699         }
2700 
2701         if (isStatement) {
2702             int varFlags = VarNode.IS_STATEMENT;
2703             if (!topLevel && useBlockScope()) {
2704                 // mark ES6 block functions as lexically scoped
2705                 varFlags |= VarNode.IS_LET;
2706             }
2707             final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
2708             if (topLevel) {
2709                 functionDeclarations.add(varNode);
2710             } else if (useBlockScope()) {
2711                 prependStatement(varNode); // Hoist to beginning of current block
2712             } else {
2713                 appendStatement(varNode);
2714             }
2715         }
2716 
2717         return functionNode;
2718     }
2719 
2720     private String getDefaultValidFunctionName(final int functionLine) {
2721         final String defaultFunctionName = getDefaultFunctionName();
2722         return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2723     }
2724 
2725     private static boolean isValidIdentifier(final String name) {
2726         if(name == null || name.isEmpty()) {




 542         if (needsBraces) {
 543             expect(RBRACE);
 544         }
 545 
 546         newBlock.setFinish(possibleEnd);
 547 
 548         return newBlock;
 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         Block newBlock = newBlock();
 561         try {
 562             statement(false, false, true);
 563         } finally {
 564             newBlock = restoreBlock(newBlock);
 565         }
 566         return newBlock;
 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.


 755      *
 756      * Parse the elements of the script or function.
 757      */
 758     private void sourceElements(final boolean shouldAllowPropertyFunction) {
 759         List<Node>    directiveStmts        = null;
 760         boolean       checkDirective        = true;
 761         boolean       allowPropertyFunction = shouldAllowPropertyFunction;
 762         final boolean oldStrictMode         = isStrictMode;
 763 
 764 
 765         try {
 766             // If is a script, then process until the end of the script.
 767             while (type != EOF) {
 768                 // Break if the end of a code block.
 769                 if (type == RBRACE) {
 770                     break;
 771                 }
 772 
 773                 try {
 774                     // Get the next element.
 775                     statement(true, allowPropertyFunction, false);
 776                     allowPropertyFunction = false;
 777 
 778                     // check for directive prologues
 779                     if (checkDirective) {
 780                         // skip any debug statement like line number to get actual first line
 781                         final Node lastStatement = lc.getLastStatement();
 782 
 783                         // get directive prologue, if any
 784                         final String directive = getDirective(lastStatement);
 785 
 786                         // If we have seen first non-directive statement,
 787                         // no more directive statements!!
 788                         checkDirective = directive != null;
 789 
 790                         if (checkDirective) {
 791                             if (!oldStrictMode) {
 792                                 if (directiveStmts == null) {
 793                                     directiveStmts = new ArrayList<>();
 794                                 }
 795                                 directiveStmts.add(lastStatement);


 845      *      VariableStatement
 846      *      EmptyStatement
 847      *      ExpressionStatement
 848      *      IfStatement
 849      *      IterationStatement
 850      *      ContinueStatement
 851      *      BreakStatement
 852      *      ReturnStatement
 853      *      WithStatement
 854      *      LabelledStatement
 855      *      SwitchStatement
 856      *      ThrowStatement
 857      *      TryStatement
 858      *      DebuggerStatement
 859      *
 860      * see 12
 861      *
 862      * Parse any of the basic statement types.
 863      */
 864     private void statement() {
 865         statement(false, false, false);
 866     }
 867 
 868     /**
 869      * @param topLevel does this statement occur at the "top level" of a script or a function?
 870      * @param allowPropertyFunction allow property "get" and "set" functions?
 871      * @param singleStatement are we in a single statement context?
 872      */
 873     private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
 874         if (type == FUNCTION) {
 875             // As per spec (ECMA section 12), function declarations as arbitrary statement
 876             // is not "portable". Implementation can issue a warning or disallow the same.
 877             functionExpression(true, topLevel);
 878             return;
 879         }
 880 
 881         switch (type) {
 882         case LBRACE:
 883             block();
 884             break;
 885         case VAR:
 886             variableStatement(type, true);
 887             break;
 888         case SEMICOLON:
 889             emptyStatement();
 890             break;
 891         case IF:
 892             ifStatement();
 893             break;


 917             break;
 918         case SWITCH:
 919             switchStatement();
 920             break;
 921         case THROW:
 922             throwStatement();
 923             break;
 924         case TRY:
 925             tryStatement();
 926             break;
 927         case DEBUGGER:
 928             debuggerStatement();
 929             break;
 930         case RPAREN:
 931         case RBRACKET:
 932         case EOF:
 933             expect(SEMICOLON);
 934             break;
 935         default:
 936             if (useBlockScope() && (type == LET || type == CONST)) {
 937                 if (singleStatement) {
 938                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
 939                 }
 940                 variableStatement(type, true);
 941                 break;
 942             }
 943             if (env._const_as_var && type == CONST) {
 944                 variableStatement(TokenType.VAR, true);
 945                 break;
 946             }
 947 
 948             if (type == IDENT || isNonStrictModeIdent()) {
 949                 if (T(k + 1) == COLON) {
 950                     labelStatement();
 951                     return;
 952                 }
 953                 if(allowPropertyFunction) {
 954                     final String ident = (String)getValue();
 955                     final long propertyToken = token;
 956                     final int propertyLine = line;
 957                     if("get".equals(ident)) {
 958                         next();
 959                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));


1045      * VariableDeclarationList :
1046      *      VariableDeclaration
1047      *      VariableDeclarationList , VariableDeclaration
1048      *
1049      * VariableDeclaration :
1050      *      Identifier Initializer?
1051      *
1052      * Initializer :
1053      *      = AssignmentExpression
1054      *
1055      * See 12.2
1056      *
1057      * Parse a VAR statement.
1058      * @param isStatement True if a statement (not used in a FOR.)
1059      */
1060     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1061         // VAR tested in caller.
1062         next();
1063 
1064         final List<VarNode> vars = new ArrayList<>();
1065         int varFlags = 0;
1066         if (varType == LET) {
1067             varFlags |= VarNode.IS_LET;
1068         } else if (varType == CONST) {
1069             varFlags |= VarNode.IS_CONST;
1070         }
1071 
1072         while (true) {
1073             // Get starting token.
1074             final int  varLine  = line;
1075             final long varToken = token;
1076             // Get name of var.
1077             final IdentNode name = getIdent();
1078             verifyStrictIdent(name, "variable name");
1079 
1080             // Assume no init.
1081             Expression init = null;
1082 
1083             // Look for initializer assignment.
1084             if (type == ASSIGN) {
1085                 next();


1198     }
1199 
1200     /**
1201      * ... IterationStatement:
1202      *           ...
1203      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1204      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1205      *           for ( LeftHandSideExpression in Expression ) Statement
1206      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1207      *
1208      * See 12.6
1209      *
1210      * Parse a FOR statement.
1211      */
1212     private void forStatement() {
1213         // When ES6 for-let is enabled we create a container block to capture the LET.
1214         final int startLine = start;
1215         Block outer = useBlockScope() ? newBlock() : null;
1216 
1217         // Create FOR node, capturing FOR token.
1218         ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, 0);
1219         lc.push(forNode);
1220 
1221         try {
1222             // FOR tested in caller.
1223             next();
1224 
1225             // Nashorn extension: for each expression.
1226             // iterate property values rather than property names.
1227             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1228                 forNode = forNode.setIsForEach(lc);
1229                 next();
1230             }
1231 
1232             expect(LPAREN);
1233 
1234             List<VarNode> vars = null;
1235 
1236             switch (type) {
1237             case VAR:
1238                 // Var declaration captured in for outer block.
1239                 vars = variableStatement(type, false);
1240                 break;
1241             case SEMICOLON:
1242                 break;
1243             default:
1244                 if (useBlockScope() && (type == LET || type == CONST)) {
1245                     if (type == LET) {
1246                         forNode = forNode.setPerIterationScope(lc);
1247                     }
1248                     // LET/CONST declaration captured in container block created above.
1249                     vars = variableStatement(type, false);
1250                     break;
1251                 }
1252                 if (env._const_as_var && type == CONST) {
1253                     // Var declaration captured in for outer block.
1254                     vars = variableStatement(TokenType.VAR, false);
1255                     break;
1256                 }
1257 
1258                 final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1259                 forNode = forNode.setInit(lc, expression);
1260                 break;
1261             }
1262 
1263             switch (type) {
1264             case SEMICOLON:
1265                 // for (init; test; modify)
1266 
1267                 // for each (init; test; modify) is invalid
1268                 if (forNode.isForEach()) {
1269                     throw error(AbstractParser.message("for.each.without.in"), token);
1270                 }
1271 
1272                 expect(SEMICOLON);
1273                 if (type != SEMICOLON) {


1314 
1315                 // Get the collection expression.
1316                 forNode = forNode.setModify(lc, joinPredecessorExpression());
1317                 break;
1318 
1319             default:
1320                 expect(SEMICOLON);
1321                 break;
1322             }
1323 
1324             expect(RPAREN);
1325 
1326             // Set the for body.
1327             final Block body = getStatement();
1328             forNode = forNode.setBody(lc, body);
1329             forNode.setFinish(body.getFinish());
1330 
1331             appendStatement(forNode);
1332         } finally {
1333             lc.pop(forNode);
1334         }
1335 
1336         if (outer != null) {
1337             outer.setFinish(forNode.getFinish());
1338             outer = restoreBlock(outer);
1339             appendStatement(new BlockStatement(startLine, outer));
1340         }
1341     }

1342 
1343     /**
1344      * ... IterationStatement :
1345      *           ...
1346      *           Expression[NoIn]?; Expression? ; Expression?
1347      *           var VariableDeclarationList[NoIn]; Expression? ; Expression?
1348      *           LeftHandSideExpression in Expression
1349      *           var VariableDeclaration[NoIn] in Expression
1350      *
1351      * See 12.6
1352      *
1353      * Parse the control section of a FOR statement.  Also used for
1354      * comprehensions.
1355      * @param forNode Owning FOR.
1356      */
1357 
1358 
1359     /**
1360      * ...IterationStatement :
1361      *           ...


2691                 if (parametersSet.contains(parameterName)) {
2692                     // redefinition of parameter name
2693                     if (strict) {
2694                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2695                     }
2696                     // rename in non-strict mode
2697                     parameterName = functionNode.uniqueName(parameterName);
2698                     final long parameterToken = parameter.getToken();
2699                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2700                 }
2701 
2702                 parametersSet.add(parameterName);
2703             }
2704         } else if (arity == 1) {
2705             if (isArguments(parameters.get(0))) {
2706                 functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2707             }
2708         }
2709 
2710         if (isStatement) {
2711             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;




2712             final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
2713             if (topLevel) {
2714                 functionDeclarations.add(varNode);
2715             } else if (useBlockScope()) {
2716                 prependStatement(varNode); // Hoist to beginning of current block
2717             } else {
2718                 appendStatement(varNode);
2719             }
2720         }
2721 
2722         return functionNode;
2723     }
2724 
2725     private String getDefaultValidFunctionName(final int functionLine) {
2726         final String defaultFunctionName = getDefaultFunctionName();
2727         return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2728     }
2729 
2730     private static boolean isValidIdentifier(final String name) {
2731         if(name == null || name.isEmpty()) {