< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java

Print this page




 875     }
 876 
 877     /**
 878      * @param topLevel does this statement occur at the "top level" of a script or a function?
 879      * @param allowPropertyFunction allow property "get" and "set" functions?
 880      * @param singleStatement are we in a single statement context?
 881      */
 882     private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
 883         if (type == FUNCTION) {
 884             // As per spec (ECMA section 12), function declarations as arbitrary statement
 885             // is not "portable". Implementation can issue a warning or disallow the same.
 886             functionExpression(true, topLevel);
 887             return;
 888         }
 889 
 890         switch (type) {
 891         case LBRACE:
 892             block();
 893             break;
 894         case VAR:
 895             variableStatement(type, true);
 896             break;
 897         case SEMICOLON:
 898             emptyStatement();
 899             break;
 900         case IF:
 901             ifStatement();
 902             break;
 903         case FOR:
 904             forStatement();
 905             break;
 906         case WHILE:
 907             whileStatement();
 908             break;
 909         case DO:
 910             doStatement();
 911             break;
 912         case CONTINUE:
 913             continueStatement();
 914             break;
 915         case BREAK:


 929             break;
 930         case THROW:
 931             throwStatement();
 932             break;
 933         case TRY:
 934             tryStatement();
 935             break;
 936         case DEBUGGER:
 937             debuggerStatement();
 938             break;
 939         case RPAREN:
 940         case RBRACKET:
 941         case EOF:
 942             expect(SEMICOLON);
 943             break;
 944         default:
 945             if (useBlockScope() && (type == LET || type == CONST)) {
 946                 if (singleStatement) {
 947                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
 948                 }
 949                 variableStatement(type, true);
 950                 break;
 951             }
 952             if (env._const_as_var && type == CONST) {
 953                 variableStatement(TokenType.VAR, true);
 954                 break;
 955             }
 956 
 957             if (type == IDENT || isNonStrictModeIdent()) {
 958                 if (T(k + 1) == COLON) {
 959                     labelStatement();
 960                     return;
 961                 }
 962                 if(allowPropertyFunction) {
 963                     final String ident = (String)getValue();
 964                     final long propertyToken = token;
 965                     final int propertyLine = line;
 966                     if("get".equals(ident)) {
 967                         next();
 968                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
 969                         return;
 970                     } else if("set".equals(ident)) {
 971                         next();
 972                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
 973                         return;


1030      *
1031      * @param ident         Identifier that is verified
1032      * @param contextString String used in error message to give context to the user
1033      */
1034     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1035         if (isStrictMode) {
1036             switch (ident.getName()) {
1037             case "eval":
1038             case "arguments":
1039                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1040             default:
1041                 break;
1042             }
1043 
1044             if (ident.isFutureStrictName()) {
1045                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1046             }
1047         }
1048     }
1049 
1050     /**
1051      * VariableStatement :
1052      *      var VariableDeclarationList ;
1053      *
1054      * VariableDeclarationList :
1055      *      VariableDeclaration
1056      *      VariableDeclarationList , VariableDeclaration
1057      *
1058      * VariableDeclaration :
1059      *      Identifier Initializer?
1060      *
1061      * Initializer :
1062      *      = AssignmentExpression
1063      *
1064      * See 12.2
1065      *
1066      * Parse a VAR statement.
1067      * @param isStatement True if a statement (not used in a FOR.)
1068      */
1069     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1070         return variableStatement(varType, isStatement, -1);
1071     }
1072 
1073     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1074         // VAR tested in caller.
1075         next();
1076 
1077         final List<VarNode> vars = new ArrayList<>();
1078         int varFlags = 0;
1079         if (varType == LET) {
1080             varFlags |= VarNode.IS_LET;
1081         } else if (varType == CONST) {
1082             varFlags |= VarNode.IS_CONST;
1083         }
1084 
1085         while (true) {
1086             // Get starting token.
1087             final int  varLine  = line;
1088             final long varToken = token;
1089             // Get name of var.
1090             final IdentNode name = getIdent();


1198         if (type == ELSE) {
1199             next();
1200             fail = getStatement();
1201         }
1202 
1203         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1204     }
1205 
1206     /**
1207      * ... IterationStatement:
1208      *           ...
1209      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1210      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1211      *           for ( LeftHandSideExpression in Expression ) Statement
1212      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1213      *
1214      * See 12.6
1215      *
1216      * Parse a FOR statement.
1217      */

1218     private void forStatement() {
1219         final long forToken = token;
1220         final int forLine = line;
1221         // start position of this for statement. This is used
1222         // for sort order for variables declared in the initializer
1223         // part of this 'for' statement (if any).
1224         final int forStart = Token.descPosition(forToken);
1225         // When ES6 for-let is enabled we create a container block to capture the LET.
1226         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1227 
1228         // Create FOR node, capturing FOR token.
1229         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1230         lc.push(forNode);
1231         Block body = null;
1232         List<VarNode> vars = null;
1233         Expression init = null;
1234         JoinPredecessorExpression test = null;
1235         JoinPredecessorExpression modify = null;
1236 
1237         int flags = 0;

1238 
1239         try {
1240             // FOR tested in caller.
1241             next();
1242 
1243             // Nashorn extension: for each expression.
1244             // iterate property values rather than property names.
1245             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1246                 flags |= ForNode.IS_FOR_EACH;
1247                 next();
1248             }
1249 
1250             expect(LPAREN);
1251 
1252             switch (type) {
1253             case VAR:
1254                 // Var declaration captured in for outer block.
1255                 vars = variableStatement(type, false, forStart);
1256                 break;
1257             case SEMICOLON:


1275 
1276             switch (type) {
1277             case SEMICOLON:
1278                 // for (init; test; modify)
1279 
1280                 // for each (init; test; modify) is invalid
1281                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1282                     throw error(AbstractParser.message("for.each.without.in"), token);
1283                 }
1284 
1285                 expect(SEMICOLON);
1286                 if (type != SEMICOLON) {
1287                     test = joinPredecessorExpression();
1288                 }
1289                 expect(SEMICOLON);
1290                 if (type != RPAREN) {
1291                     modify = joinPredecessorExpression();
1292                 }
1293                 break;
1294 








1295             case IN:
1296                 flags |= ForNode.IS_FOR_IN;

1297                 test = new JoinPredecessorExpression();
1298                 if (vars != null) {
1299                     // for (var i in obj)
1300                     if (vars.size() == 1) {
1301                         init = new IdentNode(vars.get(0).getName());
1302                     } else {
1303                         // for (var i, j in obj) is invalid
1304                         throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
1305                     }
1306 
1307                 } else {
1308                     // for (expr in obj)
1309                     assert init != null : "for..in init expression can not be null here";
1310 
1311                     // check if initial expression is a valid L-value
1312                     if (!(init instanceof AccessNode ||
1313                           init instanceof IndexNode ||
1314                           init instanceof IdentNode)) {
1315                         throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1316                     }
1317 
1318                     if (init instanceof IdentNode) {
1319                         if (!checkIdentLValue((IdentNode)init)) {
1320                             throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1321                         }
1322                         verifyStrictIdent((IdentNode)init, "for-in iterator");
1323                     }
1324                 }
1325 
1326                 next();
1327 
1328                 // Get the collection expression.
1329                 modify = joinPredecessorExpression();
1330                 break;
1331 
1332             default:
1333                 expect(SEMICOLON);
1334                 break;
1335             }
1336 
1337             expect(RPAREN);
1338 
1339             // Set the for body.
1340             body = getStatement();
1341         } finally {
1342             lc.pop(forNode);
1343 
1344             if (vars != null) {
1345                 for (final VarNode var : vars) {
1346                     appendStatement(var);
1347                 }
1348             }
1349             if (body != null) {




 875     }
 876 
 877     /**
 878      * @param topLevel does this statement occur at the "top level" of a script or a function?
 879      * @param allowPropertyFunction allow property "get" and "set" functions?
 880      * @param singleStatement are we in a single statement context?
 881      */
 882     private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
 883         if (type == FUNCTION) {
 884             // As per spec (ECMA section 12), function declarations as arbitrary statement
 885             // is not "portable". Implementation can issue a warning or disallow the same.
 886             functionExpression(true, topLevel);
 887             return;
 888         }
 889 
 890         switch (type) {
 891         case LBRACE:
 892             block();
 893             break;
 894         case VAR:
 895             variableStatement(type);
 896             break;
 897         case SEMICOLON:
 898             emptyStatement();
 899             break;
 900         case IF:
 901             ifStatement();
 902             break;
 903         case FOR:
 904             forStatement();
 905             break;
 906         case WHILE:
 907             whileStatement();
 908             break;
 909         case DO:
 910             doStatement();
 911             break;
 912         case CONTINUE:
 913             continueStatement();
 914             break;
 915         case BREAK:


 929             break;
 930         case THROW:
 931             throwStatement();
 932             break;
 933         case TRY:
 934             tryStatement();
 935             break;
 936         case DEBUGGER:
 937             debuggerStatement();
 938             break;
 939         case RPAREN:
 940         case RBRACKET:
 941         case EOF:
 942             expect(SEMICOLON);
 943             break;
 944         default:
 945             if (useBlockScope() && (type == LET || type == CONST)) {
 946                 if (singleStatement) {
 947                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
 948                 }
 949                 variableStatement(type);
 950                 break;
 951             }
 952             if (env._const_as_var && type == CONST) {
 953                 variableStatement(TokenType.VAR);
 954                 break;
 955             }
 956 
 957             if (type == IDENT || isNonStrictModeIdent()) {
 958                 if (T(k + 1) == COLON) {
 959                     labelStatement();
 960                     return;
 961                 }
 962                 if(allowPropertyFunction) {
 963                     final String ident = (String)getValue();
 964                     final long propertyToken = token;
 965                     final int propertyLine = line;
 966                     if("get".equals(ident)) {
 967                         next();
 968                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
 969                         return;
 970                     } else if("set".equals(ident)) {
 971                         next();
 972                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
 973                         return;


1030      *
1031      * @param ident         Identifier that is verified
1032      * @param contextString String used in error message to give context to the user
1033      */
1034     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1035         if (isStrictMode) {
1036             switch (ident.getName()) {
1037             case "eval":
1038             case "arguments":
1039                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1040             default:
1041                 break;
1042             }
1043 
1044             if (ident.isFutureStrictName()) {
1045                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1046             }
1047         }
1048     }
1049 
1050     /*
1051      * VariableStatement :
1052      *      var VariableDeclarationList ;
1053      *
1054      * VariableDeclarationList :
1055      *      VariableDeclaration
1056      *      VariableDeclarationList , VariableDeclaration
1057      *
1058      * VariableDeclaration :
1059      *      Identifier Initializer?
1060      *
1061      * Initializer :
1062      *      = AssignmentExpression
1063      *
1064      * See 12.2
1065      *
1066      * Parse a VAR statement.
1067      * @param isStatement True if a statement (not used in a FOR.)
1068      */
1069     private List<VarNode> variableStatement(final TokenType varType) {
1070         return variableStatement(varType, true, -1);
1071     }
1072 
1073     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1074         // VAR tested in caller.
1075         next();
1076 
1077         final List<VarNode> vars = new ArrayList<>();
1078         int varFlags = 0;
1079         if (varType == LET) {
1080             varFlags |= VarNode.IS_LET;
1081         } else if (varType == CONST) {
1082             varFlags |= VarNode.IS_CONST;
1083         }
1084 
1085         while (true) {
1086             // Get starting token.
1087             final int  varLine  = line;
1088             final long varToken = token;
1089             // Get name of var.
1090             final IdentNode name = getIdent();


1198         if (type == ELSE) {
1199             next();
1200             fail = getStatement();
1201         }
1202 
1203         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1204     }
1205 
1206     /**
1207      * ... IterationStatement:
1208      *           ...
1209      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1210      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1211      *           for ( LeftHandSideExpression in Expression ) Statement
1212      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1213      *
1214      * See 12.6
1215      *
1216      * Parse a FOR statement.
1217      */
1218     @SuppressWarnings("fallthrough")
1219     private void forStatement() {
1220         final long forToken = token;
1221         final int forLine = line;
1222         // start position of this for statement. This is used
1223         // for sort order for variables declared in the initializer
1224         // part of this 'for' statement (if any).
1225         final int forStart = Token.descPosition(forToken);
1226         // When ES6 for-let is enabled we create a container block to capture the LET.
1227         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1228 
1229         // Create FOR node, capturing FOR token.
1230         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1231         lc.push(forNode);
1232         Block body = null;
1233         List<VarNode> vars = null;
1234         Expression init = null;
1235         JoinPredecessorExpression test = null;
1236         JoinPredecessorExpression modify = null;
1237 
1238         int flags = 0;
1239         boolean isForOf = false;
1240 
1241         try {
1242             // FOR tested in caller.
1243             next();
1244 
1245             // Nashorn extension: for each expression.
1246             // iterate property values rather than property names.
1247             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1248                 flags |= ForNode.IS_FOR_EACH;
1249                 next();
1250             }
1251 
1252             expect(LPAREN);
1253 
1254             switch (type) {
1255             case VAR:
1256                 // Var declaration captured in for outer block.
1257                 vars = variableStatement(type, false, forStart);
1258                 break;
1259             case SEMICOLON:


1277 
1278             switch (type) {
1279             case SEMICOLON:
1280                 // for (init; test; modify)
1281 
1282                 // for each (init; test; modify) is invalid
1283                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1284                     throw error(AbstractParser.message("for.each.without.in"), token);
1285                 }
1286 
1287                 expect(SEMICOLON);
1288                 if (type != SEMICOLON) {
1289                     test = joinPredecessorExpression();
1290                 }
1291                 expect(SEMICOLON);
1292                 if (type != RPAREN) {
1293                     modify = joinPredecessorExpression();
1294                 }
1295                 break;
1296 
1297             case IDENT:
1298                 if (env._es6 && "of".equals(getValue())) {
1299                     isForOf = true;
1300                     // fall through
1301                 } else {
1302                     expect(SEMICOLON); // fail with expected message
1303                     break;
1304                 }
1305             case IN:
1306 
1307                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
1308                 test = new JoinPredecessorExpression();
1309                 if (vars != null) {
1310                     // for (var i in obj)
1311                     if (vars.size() == 1) {
1312                         init = new IdentNode(vars.get(0).getName());
1313                     } else {
1314                         // for (var i, j in obj) is invalid
1315                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
1316                     }

1317                 } else {
1318                     // for (expr in obj)
1319                     assert init != null : "for..in/of init expression can not be null here";
1320 
1321                     // check if initial expression is a valid L-value
1322                     if (!(init instanceof AccessNode ||
1323                           init instanceof IndexNode ||
1324                           init instanceof IdentNode)) {
1325                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1326                     }
1327 
1328                     if (init instanceof IdentNode) {
1329                         if (!checkIdentLValue((IdentNode)init)) {
1330                             throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1331                         }
1332                         verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
1333                     }
1334                 }
1335 
1336                 next();
1337 
1338                 // For-of only allows AssignmentExpression.
1339                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
1340                 break;
1341 
1342             default:
1343                 expect(SEMICOLON);
1344                 break;
1345             }
1346 
1347             expect(RPAREN);
1348 
1349             // Set the for body.
1350             body = getStatement();
1351         } finally {
1352             lc.pop(forNode);
1353 
1354             if (vars != null) {
1355                 for (final VarNode var : vars) {
1356                     appendStatement(var);
1357                 }
1358             }
1359             if (body != null) {


< prev index next >