| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 // TODO(jimhug): Error recovery needs major work! | 5 // TODO(jimhug): Error recovery needs major work! |
| 6 /** | 6 /** |
| 7 * A simple recursive descent parser for the dart language. | 7 * A simple recursive descent parser for the dart language. |
| 8 * | 8 * |
| 9 * This parser is designed to be more permissive than the official | 9 * This parser is designed to be more permissive than the official |
| 10 * Dart grammar. It is expected that many grammar errors would be | 10 * Dart grammar. It is expected that many grammar errors would be |
| (...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 | 1059 |
| 1060 case TokenKind.SUPER: | 1060 case TokenKind.SUPER: |
| 1061 _eat(TokenKind.SUPER); | 1061 _eat(TokenKind.SUPER); |
| 1062 return new SuperExpression(_makeSpan(start)); | 1062 return new SuperExpression(_makeSpan(start)); |
| 1063 | 1063 |
| 1064 case TokenKind.CONST: | 1064 case TokenKind.CONST: |
| 1065 _eat(TokenKind.CONST); | 1065 _eat(TokenKind.CONST); |
| 1066 if (_peekKind(TokenKind.LBRACK) || _peekKind(TokenKind.INDEX)) { | 1066 if (_peekKind(TokenKind.LBRACK) || _peekKind(TokenKind.INDEX)) { |
| 1067 return finishListLiteral(start, true, null); | 1067 return finishListLiteral(start, true, null); |
| 1068 } else if (_peekKind(TokenKind.LBRACE)) { | 1068 } else if (_peekKind(TokenKind.LBRACE)) { |
| 1069 return finishMapLiteral(start, true, null); | 1069 return finishMapLiteral(start, true, null, null); |
| 1070 } else if (_peekKind(TokenKind.LT)) { | 1070 } else if (_peekKind(TokenKind.LT)) { |
| 1071 return finishTypedLiteral(start, true); | 1071 return finishTypedLiteral(start, true); |
| 1072 } else { | 1072 } else { |
| 1073 return finishNewExpression(start, true); | 1073 return finishNewExpression(start, true); |
| 1074 } | 1074 } |
| 1075 | 1075 |
| 1076 case TokenKind.NEW: | 1076 case TokenKind.NEW: |
| 1077 _eat(TokenKind.NEW); | 1077 _eat(TokenKind.NEW); |
| 1078 return finishNewExpression(start, false); | 1078 return finishNewExpression(start, false); |
| 1079 | 1079 |
| 1080 case TokenKind.LPAREN: | 1080 case TokenKind.LPAREN: |
| 1081 return _parenOrLambda(); | 1081 return _parenOrLambda(); |
| 1082 | 1082 |
| 1083 case TokenKind.LBRACK: | 1083 case TokenKind.LBRACK: |
| 1084 case TokenKind.INDEX: | 1084 case TokenKind.INDEX: |
| 1085 return finishListLiteral(start, false, null); | 1085 return finishListLiteral(start, false, null); |
| 1086 case TokenKind.LBRACE: | 1086 case TokenKind.LBRACE: |
| 1087 return finishMapLiteral(start, false, null); | 1087 return finishMapLiteral(start, false, null, null); |
| 1088 | 1088 |
| 1089 // Literals | 1089 // Literals |
| 1090 case TokenKind.NULL: | 1090 case TokenKind.NULL: |
| 1091 _eat(TokenKind.NULL); | 1091 _eat(TokenKind.NULL); |
| 1092 return _makeLiteral(Value.fromNull(_makeSpan(start))); | 1092 return _makeLiteral(Value.fromNull(_makeSpan(start))); |
| 1093 | 1093 |
| 1094 // TODO(jimhug): Make Literal creation less wasteful - no dup span/text. | 1094 // TODO(jimhug): Make Literal creation less wasteful - no dup span/text. |
| 1095 case TokenKind.TRUE: | 1095 case TokenKind.TRUE: |
| 1096 _eat(TokenKind.TRUE); | 1096 _eat(TokenKind.TRUE); |
| 1097 return _makeLiteral(Value.fromBool(true, _makeSpan(start))); | 1097 return _makeLiteral(Value.fromBool(true, _makeSpan(start))); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 finishNewExpression(int start, bool isConst) { | 1337 finishNewExpression(int start, bool isConst) { |
| 1338 var type = type(); | 1338 var type = type(); |
| 1339 var name = null; | 1339 var name = null; |
| 1340 if (_maybeEat(TokenKind.DOT)) { | 1340 if (_maybeEat(TokenKind.DOT)) { |
| 1341 name = identifier(); | 1341 name = identifier(); |
| 1342 } | 1342 } |
| 1343 var args = arguments(); | 1343 var args = arguments(); |
| 1344 return new NewExpression(isConst, type, name, args, _makeSpan(start)); | 1344 return new NewExpression(isConst, type, name, args, _makeSpan(start)); |
| 1345 } | 1345 } |
| 1346 | 1346 |
| 1347 finishListLiteral(int start, bool isConst, TypeReference type) { | 1347 finishListLiteral(int start, bool isConst, TypeReference itemType) { |
| 1348 if (_maybeEat(TokenKind.INDEX)) { | 1348 if (_maybeEat(TokenKind.INDEX)) { |
| 1349 // This is an empty array. | 1349 // This is an empty array. |
| 1350 return new ListExpression(isConst, type, [], _makeSpan(start)); | 1350 return new ListExpression(isConst, itemType, [], _makeSpan(start)); |
| 1351 } | 1351 } |
| 1352 | 1352 |
| 1353 var values = []; | 1353 var values = []; |
| 1354 _eat(TokenKind.LBRACK); | 1354 _eat(TokenKind.LBRACK); |
| 1355 while (!_maybeEat(TokenKind.RBRACK)) { | 1355 while (!_maybeEat(TokenKind.RBRACK)) { |
| 1356 values.add(expression()); | 1356 values.add(expression()); |
| 1357 if (_recover && !_recoverTo(TokenKind.RBRACK, TokenKind.COMMA)) break; | 1357 if (_recover && !_recoverTo(TokenKind.RBRACK, TokenKind.COMMA)) break; |
| 1358 if (!_maybeEat(TokenKind.COMMA)) { | 1358 if (!_maybeEat(TokenKind.COMMA)) { |
| 1359 _eat(TokenKind.RBRACK); | 1359 _eat(TokenKind.RBRACK); |
| 1360 break; | 1360 break; |
| 1361 } | 1361 } |
| 1362 } | 1362 } |
| 1363 return new ListExpression(isConst, type, values, _makeSpan(start)); | 1363 return new ListExpression(isConst, itemType, values, _makeSpan(start)); |
| 1364 } | 1364 } |
| 1365 | 1365 |
| 1366 finishMapLiteral(int start, bool isConst, TypeReference type) { | 1366 finishMapLiteral(int start, bool isConst, |
| 1367 TypeReference keyType, TypeReference valueType) { |
| 1367 var items = []; | 1368 var items = []; |
| 1368 _eat(TokenKind.LBRACE); | 1369 _eat(TokenKind.LBRACE); |
| 1369 while (!_maybeEat(TokenKind.RBRACE)) { | 1370 while (!_maybeEat(TokenKind.RBRACE)) { |
| 1370 // This is deliberately overly permissive - checked in later pass. | 1371 // This is deliberately overly permissive - checked in later pass. |
| 1371 items.add(expression()); | 1372 items.add(expression()); |
| 1372 _eat(TokenKind.COLON); | 1373 _eat(TokenKind.COLON); |
| 1373 items.add(expression()); | 1374 items.add(expression()); |
| 1374 if (_recover && !_recoverTo(TokenKind.RBRACE, TokenKind.COMMA)) break; | 1375 if (_recover && !_recoverTo(TokenKind.RBRACE, TokenKind.COMMA)) break; |
| 1375 if (!_maybeEat(TokenKind.COMMA)) { | 1376 if (!_maybeEat(TokenKind.COMMA)) { |
| 1376 _eat(TokenKind.RBRACE); | 1377 _eat(TokenKind.RBRACE); |
| 1377 break; | 1378 break; |
| 1378 } | 1379 } |
| 1379 } | 1380 } |
| 1380 return new MapExpression(isConst, type, items, _makeSpan(start)); | 1381 return new MapExpression(isConst, keyType, valueType, items, |
| 1382 _makeSpan(start)); |
| 1381 } | 1383 } |
| 1382 | 1384 |
| 1383 finishTypedLiteral(int start, bool isConst) { | 1385 finishTypedLiteral(int start, bool isConst) { |
| 1384 var span = _makeSpan(start); | 1386 var span = _makeSpan(start); |
| 1385 var typeToBeNamedLater = new NameTypeReference(false, null, null, span); | 1387 |
| 1386 var genericType = addTypeArguments(typeToBeNamedLater, 0); | 1388 final typeToBeNamedLater = new NameTypeReference(false, null, null, span); |
| 1389 final genericType = addTypeArguments(typeToBeNamedLater, 0); |
| 1390 final typeArgs = genericType.typeArguments; |
| 1387 | 1391 |
| 1388 if (_peekKind(TokenKind.LBRACK) || _peekKind(TokenKind.INDEX)) { | 1392 if (_peekKind(TokenKind.LBRACK) || _peekKind(TokenKind.INDEX)) { |
| 1389 genericType.baseType = new TypeReference(span, world.listType); | 1393 if (typeArgs.length != 1) { |
| 1390 return finishListLiteral(start, isConst, genericType); | 1394 world.error('exactly one type argument expected for list', |
| 1395 genericType.span); |
| 1396 } |
| 1397 return finishListLiteral(start, isConst, typeArgs[0]); |
| 1391 } else if (_peekKind(TokenKind.LBRACE)) { | 1398 } else if (_peekKind(TokenKind.LBRACE)) { |
| 1392 genericType.baseType = new TypeReference(span, world.mapType); | 1399 var keyType, valueType; |
| 1393 final typeArgs = genericType.typeArguments; | |
| 1394 // TODO(sigmund): Would be nice to allow arbitrary keys here (this is | |
| 1395 // currently not allowed by the spec). | |
| 1396 if (typeArgs.length == 1) { | 1400 if (typeArgs.length == 1) { |
| 1397 genericType.typeArguments = | 1401 keyType = null; |
| 1398 [new TypeReference(span, world.stringType), typeArgs[0]]; | 1402 valueType = typeArgs[0]; |
| 1399 } else if (typeArgs.length == 2) { | 1403 } else if (typeArgs.length == 2) { |
| 1400 var keyType = typeArgs[0]; | 1404 var keyType = typeArgs[0]; |
| 1401 if (keyType is! NameTypeReference || keyType.name.name != "String") { | 1405 // making key explicit is just a warning. |
| 1402 world.error('the key type of a map literal is implicitly "String"', | 1406 world.warning( |
| 1403 keyType.span); | 1407 'a map literal takes one type argument specifying the value type', |
| 1404 } else { | 1408 keyType.span); |
| 1405 // making key explicit is just a warning. | 1409 valueType = typeArgs[1]; |
| 1406 world.warning( | |
| 1407 'a map literal takes one type argument specifying the value type', | |
| 1408 keyType.span); | |
| 1409 } | |
| 1410 } // o.w. the type system will detect the mismatch in type arguments. | 1410 } // o.w. the type system will detect the mismatch in type arguments. |
| 1411 return finishMapLiteral(start, isConst, genericType); | 1411 return finishMapLiteral(start, isConst, keyType, valueType); |
| 1412 } else { | 1412 } else { |
| 1413 _errorExpected('array or map literal'); | 1413 _errorExpected('array or map literal'); |
| 1414 } | 1414 } |
| 1415 } | 1415 } |
| 1416 | 1416 |
| 1417 /////////////////////////////////////////////////////////////////// | 1417 /////////////////////////////////////////////////////////////////// |
| 1418 // Some auxilary productions. | 1418 // Some auxilary productions. |
| 1419 /////////////////////////////////////////////////////////////////// | 1419 /////////////////////////////////////////////////////////////////// |
| 1420 _readModifiers() { | 1420 _readModifiers() { |
| 1421 var modifiers = null; | 1421 var modifiers = null; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 int _pos = 0; | 1699 int _pos = 0; |
| 1700 next() { | 1700 next() { |
| 1701 var token = tokens[_pos]; | 1701 var token = tokens[_pos]; |
| 1702 ++_pos; | 1702 ++_pos; |
| 1703 if (_pos == tokens.length) { | 1703 if (_pos == tokens.length) { |
| 1704 parser.tokenizer = previousTokenizer; | 1704 parser.tokenizer = previousTokenizer; |
| 1705 } | 1705 } |
| 1706 return token; | 1706 return token; |
| 1707 } | 1707 } |
| 1708 } | 1708 } |
| OLD | NEW |