Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Utilities for building JS ASTs at runtime. Contains a builder class | 5 // Utilities for building JS ASTs at runtime. Contains a builder class |
| 6 // and a parser that parses part of the language. | 6 // and a parser that parses part of the language. |
| 7 | 7 |
| 8 part of js; | 8 part of js; |
| 9 | 9 |
| 10 | 10 |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 '|': 12, | 509 '|': 12, |
| 510 '^': 11, | 510 '^': 11, |
| 511 '&': 10, | 511 '&': 10, |
| 512 '!=': 9, '==': 9, '!==': 9, '===': 9, | 512 '!=': 9, '==': 9, '!==': 9, '===': 9, |
| 513 '<': 8, '<=': 8, '>=': 8, '>': 8, 'in': 8, 'instanceof': 8, | 513 '<': 8, '<=': 8, '>=': 8, '>': 8, 'in': 8, 'instanceof': 8, |
| 514 '<<': 7, '>>': 7, '>>>': 7, | 514 '<<': 7, '>>': 7, '>>>': 7, |
| 515 '+': 6, '-': 6, | 515 '+': 6, '-': 6, |
| 516 '*': 5, '/': 5, '%': 5 | 516 '*': 5, '/': 5, '%': 5 |
| 517 }; | 517 }; |
| 518 static final UNARY_OPERATORS = | 518 static final UNARY_OPERATORS = |
| 519 ['++', '--', '+', '-', '~', '!', 'typeof', 'void', 'delete'].toSet(); | 519 ['++', '--', '+', '-', '~', '!', 'typeof', 'void', 'delete', 'await'] |
| 520 .toSet(); | |
| 520 | 521 |
| 521 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS = | 522 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS = |
| 522 ['typeof', 'void', 'delete', 'in', 'instanceof'].toSet(); | 523 ['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet(); |
| 523 | 524 |
| 524 static int category(int code) { | 525 static int category(int code) { |
| 525 if (code >= CATEGORIES.length) return OTHER; | 526 if (code >= CATEGORIES.length) return OTHER; |
| 526 return CATEGORIES[code]; | 527 return CATEGORIES[code]; |
| 527 } | 528 } |
| 528 | 529 |
| 529 String getDelimited(int startPosition) { | 530 String getDelimited(int startPosition) { |
| 530 position = startPosition; | 531 position = startPosition; |
| 531 int delimiter = src.codeUnitAt(startPosition); | 532 int delimiter = src.codeUnitAt(startPosition); |
| 532 int currentCode; | 533 int currentCode; |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 786 } else { | 787 } else { |
| 787 String argumentName = lastToken; | 788 String argumentName = lastToken; |
| 788 expectCategory(ALPHA); | 789 expectCategory(ALPHA); |
| 789 params.add(new Parameter(argumentName)); | 790 params.add(new Parameter(argumentName)); |
| 790 } | 791 } |
| 791 if (acceptCategory(COMMA)) continue; | 792 if (acceptCategory(COMMA)) continue; |
| 792 expectCategory(RPAREN); | 793 expectCategory(RPAREN); |
| 793 break; | 794 break; |
| 794 } | 795 } |
| 795 } | 796 } |
| 796 | 797 AsyncModifier asyncModifier; |
| 798 if (acceptString('async')) { | |
| 799 if (acceptString('*')) { | |
| 800 asyncModifier = const AsyncModifier.asyncStar(); | |
| 801 } else { | |
| 802 asyncModifier = const AsyncModifier.async(); | |
| 803 } | |
| 804 } else if (acceptString('sync')) { | |
| 805 if (!acceptString('*')) error("Only sync* is valid - sync is implied"); | |
| 806 asyncModifier = const AsyncModifier.syncStar(); | |
| 807 } else { | |
| 808 asyncModifier = const AsyncModifier.sync(); | |
| 809 } | |
| 797 expectCategory(LBRACE); | 810 expectCategory(LBRACE); |
| 798 Block block = parseBlock(); | 811 Block block = parseBlock(); |
| 799 return new Fun(params, block); | 812 return new Fun(params, block, asyncModifier: asyncModifier); |
| 800 } | 813 } |
| 801 | 814 |
| 802 Expression parseObjectInitializer() { | 815 Expression parseObjectInitializer() { |
| 803 List<Property> properties = <Property>[]; | 816 List<Property> properties = <Property>[]; |
| 804 for (;;) { | 817 for (;;) { |
| 805 if (acceptCategory(RBRACE)) break; | 818 if (acceptCategory(RBRACE)) break; |
| 806 // Limited subset: keys are identifiers, no 'get' or 'set' properties. | 819 // Limited subset: keys are identifiers, no 'get' or 'set' properties. |
| 807 Literal propertyName; | 820 Literal propertyName; |
| 808 String identifier = lastToken; | 821 String identifier = lastToken; |
| 809 if (acceptCategory(ALPHA)) { | 822 if (acceptCategory(ALPHA)) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 911 } | 924 } |
| 912 // If we don't accept '++' or '--' due to skippedNewline a newline, no other | 925 // If we don't accept '++' or '--' due to skippedNewline a newline, no other |
| 913 // part of the parser will accept the token and we will get an error at the | 926 // part of the parser will accept the token and we will get an error at the |
| 914 // whole expression level. | 927 // whole expression level. |
| 915 return expression; | 928 return expression; |
| 916 } | 929 } |
| 917 | 930 |
| 918 Expression parseUnaryHigh() { | 931 Expression parseUnaryHigh() { |
| 919 String operator = lastToken; | 932 String operator = lastToken; |
| 920 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && | 933 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && |
| 921 (acceptString("++") || acceptString("--"))) { | 934 (acceptString("++") || acceptString("--") || acceptString('await'))) { |
| 935 if (operator == "await") return new Await(parsePostfix()); | |
| 922 return new Prefix(operator, parsePostfix()); | 936 return new Prefix(operator, parsePostfix()); |
| 923 } | 937 } |
| 924 return parsePostfix(); | 938 return parsePostfix(); |
| 925 } | 939 } |
| 926 | 940 |
| 927 Expression parseUnaryLow() { | 941 Expression parseUnaryLow() { |
| 928 String operator = lastToken; | 942 String operator = lastToken; |
| 929 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && | 943 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && |
| 930 operator != "++" && operator != "--") { | 944 operator != "++" && operator != "--") { |
| 931 expectCategory(SYMBOL); | 945 expectCategory(SYMBOL); |
| 946 if (operator == "await") return new Await(parsePostfix()); | |
| 932 return new Prefix(operator, parseUnaryLow()); | 947 return new Prefix(operator, parseUnaryLow()); |
| 933 } | 948 } |
| 934 return parseUnaryHigh(); | 949 return parseUnaryHigh(); |
| 935 } | 950 } |
| 936 | 951 |
| 937 Expression parseBinary(int maxPrecedence) { | 952 Expression parseBinary(int maxPrecedence) { |
| 938 Expression lhs = parseUnaryLow(); | 953 Expression lhs = parseUnaryLow(); |
| 939 int minPrecedence; | 954 int minPrecedence; |
| 940 String lastSymbol; | 955 String lastSymbol; |
| 941 Expression rhs; // This is null first time around. | 956 Expression rhs; // This is null first time around. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1084 if (acceptString('function')) return parseFunctionDeclaration(); | 1099 if (acceptString('function')) return parseFunctionDeclaration(); |
| 1085 | 1100 |
| 1086 if (acceptString('try')) return parseTry(); | 1101 if (acceptString('try')) return parseTry(); |
| 1087 | 1102 |
| 1088 if (acceptString('var')) { | 1103 if (acceptString('var')) { |
| 1089 Expression declarations = parseVariableDeclarationList(); | 1104 Expression declarations = parseVariableDeclarationList(); |
| 1090 expectSemicolon(); | 1105 expectSemicolon(); |
| 1091 return new ExpressionStatement(declarations); | 1106 return new ExpressionStatement(declarations); |
| 1092 } | 1107 } |
| 1093 | 1108 |
| 1094 if (lastToken == 'case' || | 1109 if (acceptString('while')) return parseWhile(); |
| 1095 lastToken == 'do' || | 1110 |
| 1096 lastToken == 'while' || | 1111 if (acceptString('do')) return parseDo(); |
| 1097 lastToken == 'switch' || | 1112 |
| 1098 lastToken == 'with') { | 1113 if (acceptString('switch')) return parseSwitch(); |
| 1114 | |
| 1115 if (lastToken == 'case') error("Case outside switch."); | |
| 1116 | |
| 1117 if (lastToken == 'default') error("Default outside switch."); | |
| 1118 | |
| 1119 if (lastToken == 'with') { | |
| 1099 error('Not implemented in mini parser'); | 1120 error('Not implemented in mini parser'); |
| 1100 } | 1121 } |
| 1101 } | 1122 } |
| 1102 | 1123 |
| 1103 | |
| 1104 // TODO: label: statement | |
| 1105 | |
| 1106 bool checkForInterpolatedStatement = lastCategory == HASH; | 1124 bool checkForInterpolatedStatement = lastCategory == HASH; |
| 1107 | 1125 |
| 1108 Expression expression = parseExpression(); | 1126 Expression expression = parseExpression(); |
| 1127 | |
| 1128 if (expression is VariableUse && acceptCategory(COLON)) { | |
| 1129 return new LabeledStatement(expression.name, parseStatement()); | |
| 1130 } | |
| 1131 | |
| 1109 expectSemicolon(); | 1132 expectSemicolon(); |
| 1110 | 1133 |
| 1111 if (checkForInterpolatedStatement) { | 1134 if (checkForInterpolatedStatement) { |
| 1112 // 'Promote' the interpolated expression `#;` to an interpolated | 1135 // 'Promote' the interpolated expression `#;` to an interpolated |
| 1113 // statement. | 1136 // statement. |
| 1114 if (expression is InterpolatedExpression) { | 1137 if (expression is InterpolatedExpression) { |
| 1115 assert(identical(interpolatedValues.last, expression)); | 1138 assert(identical(interpolatedValues.last, expression)); |
| 1116 InterpolatedStatement statement = | 1139 InterpolatedStatement statement = |
| 1117 new InterpolatedStatement(expression.nameOrPosition); | 1140 new InterpolatedStatement(expression.nameOrPosition); |
| 1118 interpolatedValues[interpolatedValues.length - 1] = statement; | 1141 interpolatedValues[interpolatedValues.length - 1] = statement; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1228 Block finallyPart = null; | 1251 Block finallyPart = null; |
| 1229 if (acceptString('finally')) { | 1252 if (acceptString('finally')) { |
| 1230 expectCategory(LBRACE); | 1253 expectCategory(LBRACE); |
| 1231 finallyPart = parseBlock(); | 1254 finallyPart = parseBlock(); |
| 1232 } else { | 1255 } else { |
| 1233 if (catchPart == null) error("expected 'finally'"); | 1256 if (catchPart == null) error("expected 'finally'"); |
| 1234 } | 1257 } |
| 1235 return new Try(body, catchPart, finallyPart); | 1258 return new Try(body, catchPart, finallyPart); |
| 1236 } | 1259 } |
| 1237 | 1260 |
| 1261 SwitchClause parseSwitchClause() { | |
| 1262 Expression expression = null; | |
| 1263 if (acceptString('case')) { | |
| 1264 expression = parseExpression(); | |
| 1265 acceptCategory(COLON); | |
|
asgerf
2015/01/16 16:23:26
I think this should be expectCategory
sigurdm
2015/01/20 07:54:56
Done.
| |
| 1266 } else { | |
| 1267 if (!acceptString('default')) { | |
| 1268 error('expected case or default'); | |
| 1269 } | |
| 1270 expectCategory(COLON); | |
| 1271 } | |
| 1272 List statements = new List<Statement>(); | |
| 1273 while (lastCategory != RBRACE && | |
| 1274 lastToken != 'case' && | |
| 1275 lastToken != 'default') { | |
| 1276 statements.add(parseStatement()); | |
| 1277 } | |
| 1278 return expression == null | |
| 1279 ? new Default(new Block(statements)) | |
| 1280 : new Case(expression, new Block(statements)); | |
| 1281 } | |
| 1282 | |
| 1283 Statement parseWhile() { | |
| 1284 expectCategory(LPAREN); | |
| 1285 Expression condition = parseExpression(); | |
| 1286 expectCategory(RPAREN); | |
| 1287 Statement body = parseStatement(); | |
| 1288 return new While(condition, body); | |
| 1289 } | |
| 1290 | |
| 1291 Statement parseDo() { | |
| 1292 Statement body = parseStatement(); | |
| 1293 getToken(); | |
| 1294 if (lastToken == "while") error("Missing while after do body."); | |
|
asgerf
2015/01/16 16:23:26
lastToken != 'while'
sigurdm
2015/01/20 07:54:56
Yes - thank you!
| |
| 1295 expectCategory(LPAREN); | |
| 1296 Expression condition = parseExpression(); | |
| 1297 expectCategory(RPAREN); | |
| 1298 expectSemicolon(); | |
| 1299 return new Do(body, condition); | |
| 1300 } | |
| 1301 | |
| 1302 Statement parseSwitch() { | |
| 1303 expectCategory(LPAREN); | |
| 1304 Expression key = parseExpression(); | |
| 1305 expectCategory(RPAREN); | |
| 1306 expectCategory(LBRACE); | |
| 1307 List<SwitchClause> clauses = new List<SwitchClause>(); | |
| 1308 while(lastCategory != RBRACE) { | |
| 1309 clauses.add(parseSwitchClause()); | |
| 1310 } | |
| 1311 expectCategory(RBRACE); | |
| 1312 return new Switch(key, clauses); | |
| 1313 } | |
| 1314 | |
| 1238 Catch parseCatch() { | 1315 Catch parseCatch() { |
| 1239 expectCategory(LPAREN); | 1316 expectCategory(LPAREN); |
| 1240 String identifier = lastToken; | 1317 String identifier = lastToken; |
| 1241 expectCategory(ALPHA); | 1318 expectCategory(ALPHA); |
| 1242 expectCategory(RPAREN); | 1319 expectCategory(RPAREN); |
| 1243 expectCategory(LBRACE); | 1320 expectCategory(LBRACE); |
| 1244 Block body = parseBlock(); | 1321 Block body = parseBlock(); |
| 1245 return new Catch(new VariableDeclaration(identifier), body); | 1322 return new Catch(new VariableDeclaration(identifier), body); |
| 1246 } | 1323 } |
| 1247 } | 1324 } |
| OLD | NEW |