Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of scanner; | 5 part of scanner; |
| 6 | 6 |
| 7 class FormalParameterType { | 7 class FormalParameterType { |
| 8 final String type; | 8 final String type; |
| 9 const FormalParameterType(this.type); | 9 const FormalParameterType(this.type); |
| 10 bool get isRequired => this == REQUIRED; | 10 bool get isRequired => this == REQUIRED; |
| (...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 } | 677 } |
| 678 | 678 |
| 679 Token parseTopLevelMember(Token token) { | 679 Token parseTopLevelMember(Token token) { |
| 680 Token start = token; | 680 Token start = token; |
| 681 listener.beginTopLevelMember(token); | 681 listener.beginTopLevelMember(token); |
| 682 | 682 |
| 683 Link<Token> identifiers = findMemberName(token); | 683 Link<Token> identifiers = findMemberName(token); |
| 684 if (identifiers.isEmpty) { | 684 if (identifiers.isEmpty) { |
| 685 return listener.expectedDeclaration(start); | 685 return listener.expectedDeclaration(start); |
| 686 } | 686 } |
| 687 Token afterName = identifiers.head; | |
| 688 identifiers = identifiers.tail; | |
| 689 | |
| 690 if (identifiers.isEmpty) { | |
| 691 return listener.expectedDeclaration(start); | |
| 692 } | |
| 687 Token name = identifiers.head; | 693 Token name = identifiers.head; |
| 688 identifiers = identifiers.tail; | 694 identifiers = identifiers.tail; |
| 689 Token getOrSet; | 695 Token getOrSet; |
| 690 if (!identifiers.isEmpty) { | 696 if (!identifiers.isEmpty) { |
| 691 String value = identifiers.head.stringValue; | 697 String value = identifiers.head.stringValue; |
| 692 if ((identical(value, 'get')) || (identical(value, 'set'))) { | 698 if ((identical(value, 'get')) || (identical(value, 'set'))) { |
| 693 getOrSet = identifiers.head; | 699 getOrSet = identifiers.head; |
| 694 identifiers = identifiers.tail; | 700 identifiers = identifiers.tail; |
| 695 } | 701 } |
| 696 } | 702 } |
| 697 Token type; | 703 Token type; |
| 698 if (!identifiers.isEmpty) { | 704 if (!identifiers.isEmpty) { |
| 699 if (isValidTypeReference(identifiers.head)) { | 705 if (isValidTypeReference(identifiers.head)) { |
| 700 type = identifiers.head; | 706 type = identifiers.head; |
| 701 identifiers = identifiers.tail; | 707 identifiers = identifiers.tail; |
| 702 } | 708 } |
| 703 } | 709 } |
| 704 | 710 |
| 705 token = name.next; | 711 token = afterName; |
| 706 bool isField; | 712 bool isField; |
| 707 while (true) { | 713 while (true) { |
| 708 // Loop to allow the listener to rewrite the token stream for | 714 // Loop to allow the listener to rewrite the token stream for |
| 709 // error handling. | 715 // error handling. |
| 710 final String value = token.stringValue; | 716 final String value = token.stringValue; |
| 711 if ((identical(value, '(')) || (identical(value, '{')) | 717 if ((identical(value, '(')) || (identical(value, '{')) |
| 712 || (identical(value, '=>'))) { | 718 || (identical(value, '=>'))) { |
| 713 isField = false; | 719 isField = false; |
| 714 break; | 720 break; |
| 715 } else if ((identical(value, '=')) || (identical(value, ','))) { | 721 } else if ((identical(value, '=')) || (identical(value, ','))) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 859 listener.endFields(fieldCount, start, semicolon); | 865 listener.endFields(fieldCount, start, semicolon); |
| 860 } | 866 } |
| 861 return token; | 867 return token; |
| 862 } | 868 } |
| 863 | 869 |
| 864 Token parseTopLevelMethod(Token start, | 870 Token parseTopLevelMethod(Token start, |
| 865 Link<Token> modifiers, | 871 Link<Token> modifiers, |
| 866 Token type, | 872 Token type, |
| 867 Token getOrSet, | 873 Token getOrSet, |
| 868 Token name) { | 874 Token name) { |
| 875 | |
| 869 Token externalModifier; | 876 Token externalModifier; |
| 870 for (Token modifier in modifiers) { | 877 for (Token modifier in modifiers) { |
| 871 if (externalModifier == null && optional('external', modifier)) { | 878 if (externalModifier == null && optional('external', modifier)) { |
| 872 externalModifier = modifier; | 879 externalModifier = modifier; |
| 873 } else { | 880 } else { |
| 874 listener.reportError( | 881 listener.reportError( |
| 875 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); | 882 modifier, MessageKind.EXTRANEOUS_MODIFIER, {'modifier': modifier}); |
| 876 } | 883 } |
| 877 } | 884 } |
| 878 if (externalModifier != null) { | 885 if (externalModifier != null) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 898 awaitIsKeyword = previousAwaitIsKeyword; | 905 awaitIsKeyword = previousAwaitIsKeyword; |
| 899 Token endToken = token; | 906 Token endToken = token; |
| 900 token = token.next; | 907 token = token.next; |
| 901 if (token.kind == BAD_INPUT_TOKEN) { | 908 if (token.kind == BAD_INPUT_TOKEN) { |
| 902 token = listener.unexpected(token); | 909 token = listener.unexpected(token); |
| 903 } | 910 } |
| 904 listener.endTopLevelMethod(start, getOrSet, endToken); | 911 listener.endTopLevelMethod(start, getOrSet, endToken); |
| 905 return token; | 912 return token; |
| 906 } | 913 } |
| 907 | 914 |
| 915 /// Looks ahead to find the name of a member. Returns a link of the modifiers, | |
| 916 /// set/get, (operator) name, and either the start of the method body or the | |
| 917 /// end of the declaration. | |
| 918 /// | |
| 919 /// Examples: | |
| 920 /// | |
| 921 /// int get foo; | |
| 922 /// results in | |
| 923 /// [';', 'foo', 'get', 'int'] | |
| 924 /// | |
| 925 /// | |
| 926 /// static const List<int> foo = null; | |
| 927 /// results in | |
| 928 /// ['=', 'foo', 'List', 'const', 'static'] | |
| 929 /// | |
| 930 /// | |
| 931 /// get foo async* { return null } | |
| 932 /// results in | |
| 933 /// ['{', 'foo', 'get'] | |
| 934 /// | |
| 935 /// | |
| 936 /// operator *(arg) => null; | |
| 937 /// results in | |
| 938 /// ['(', '*', 'operator'] | |
| 939 /// | |
| 908 Link<Token> findMemberName(Token token) { | 940 Link<Token> findMemberName(Token token) { |
| 909 Token start = token; | 941 Token start = token; |
| 910 Link<Token> identifiers = const Link<Token>(); | 942 Link<Token> identifiers = const Link<Token>(); |
| 911 while (!identical(token.kind, EOF_TOKEN)) { | 943 |
| 944 // `true` if 'get' has been seen. | |
| 945 bool isGetter = false; | |
| 946 // `true` if an identifier has been seen after 'get'. | |
| 947 bool hasName = false; | |
| 948 | |
| 949 while (token.kind != EOF_TOKEN) { | |
| 912 String value = token.stringValue; | 950 String value = token.stringValue; |
| 913 if ((identical(value, '(')) || (identical(value, '{')) | 951 if (value == 'get') { |
| 914 || (identical(value, '=>'))) { | 952 isGetter = true; |
| 953 } else if (hasName && | |
| 954 (value == 'sync' || value == 'async')) { | |
|
ahe
2016/04/25 12:54:15
FWIW, for sake of performance, it's important that
Johnni Winther
2016/04/25 13:36:02
I was under the imprecision that the VM had optimi
ahe
2016/04/25 13:39:53
It's probably optimized with something like this:
| |
| 955 // Skip. | |
| 956 token = token.next; | |
| 957 value = token.stringValue; | |
| 958 if (value == '*') { | |
| 959 // Skip. | |
| 960 token = token.next; | |
| 961 } | |
| 962 continue; | |
| 963 } else if (value == '(' || | |
| 964 value == '{' || | |
| 965 value == '=>') { | |
| 915 // A method. | 966 // A method. |
| 967 identifiers = identifiers.prepend(token); | |
| 916 return identifiers; | 968 return identifiers; |
| 917 } else if ((identical(value, '=')) || (identical(value, ';')) | 969 } else if (value == '=' || |
| 918 || (identical(value, ','))) { | 970 value == ';' || |
| 971 value == ',') { | |
| 919 // A field or abstract getter. | 972 // A field or abstract getter. |
| 973 identifiers = identifiers.prepend(token); | |
| 920 return identifiers; | 974 return identifiers; |
| 975 } else if (isGetter) { | |
| 976 hasName = true; | |
| 921 } | 977 } |
| 922 identifiers = identifiers.prepend(token); | 978 identifiers = identifiers.prepend(token); |
| 923 if (isValidTypeReference(token)) { | 979 if (isValidTypeReference(token)) { |
| 924 // type ... | 980 // type ... |
| 925 if (optional('.', token.next)) { | 981 if (optional('.', token.next)) { |
| 926 // type '.' ... | 982 // type '.' ... |
| 927 if (token.next.next.isIdentifier()) { | 983 if (token.next.next.isIdentifier()) { |
| 928 // type '.' identifier | 984 // type '.' identifier |
| 929 token = token.next.next; | 985 token = token.next.next; |
| 930 } | 986 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1107 if (isFactoryDeclaration(token)) { | 1163 if (isFactoryDeclaration(token)) { |
| 1108 return parseFactoryMethod(token); | 1164 return parseFactoryMethod(token); |
| 1109 } | 1165 } |
| 1110 Token start = token; | 1166 Token start = token; |
| 1111 listener.beginMember(token); | 1167 listener.beginMember(token); |
| 1112 | 1168 |
| 1113 Link<Token> identifiers = findMemberName(token); | 1169 Link<Token> identifiers = findMemberName(token); |
| 1114 if (identifiers.isEmpty) { | 1170 if (identifiers.isEmpty) { |
| 1115 return listener.expectedDeclaration(start); | 1171 return listener.expectedDeclaration(start); |
| 1116 } | 1172 } |
| 1173 Token afterName = identifiers.head; | |
| 1174 identifiers = identifiers.tail; | |
| 1175 | |
| 1176 if (identifiers.isEmpty) { | |
| 1177 return listener.expectedDeclaration(start); | |
| 1178 } | |
| 1117 Token name = identifiers.head; | 1179 Token name = identifiers.head; |
| 1118 Token afterName = name.next; | |
| 1119 identifiers = identifiers.tail; | 1180 identifiers = identifiers.tail; |
| 1120 if (!identifiers.isEmpty) { | 1181 if (!identifiers.isEmpty) { |
| 1121 if (optional('operator', identifiers.head)) { | 1182 if (optional('operator', identifiers.head)) { |
| 1122 name = identifiers.head; | 1183 name = identifiers.head; |
| 1123 identifiers = identifiers.tail; | 1184 identifiers = identifiers.tail; |
| 1124 } | 1185 } |
| 1125 } | 1186 } |
| 1126 Token getOrSet; | 1187 Token getOrSet; |
| 1127 if (!identifiers.isEmpty) { | 1188 if (!identifiers.isEmpty) { |
| 1128 if (isGetOrSet(identifiers.head)) { | 1189 if (isGetOrSet(identifiers.head)) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1295 listener.handleOperatorName(operator, token); | 1356 listener.handleOperatorName(operator, token); |
| 1296 return token.next; | 1357 return token.next; |
| 1297 } else { | 1358 } else { |
| 1298 return parseIdentifier(token); | 1359 return parseIdentifier(token); |
| 1299 } | 1360 } |
| 1300 } | 1361 } |
| 1301 | 1362 |
| 1302 Token parseFunction(Token token, Token getOrSet) { | 1363 Token parseFunction(Token token, Token getOrSet) { |
| 1303 listener.beginFunction(token); | 1364 listener.beginFunction(token); |
| 1304 token = parseModifiers(token); | 1365 token = parseModifiers(token); |
| 1305 if (identical(getOrSet, token)) token = token.next; | 1366 if (identical(getOrSet, token)) { |
| 1306 if (optional('operator', token)) { | 1367 // get <name> => ... |
| 1368 token = token.next; | |
| 1369 listener.handleNoType(token); | |
| 1370 listener.beginFunctionName(token); | |
| 1371 if (optional('operator', token)) { | |
| 1372 token = parseOperatorName(token); | |
| 1373 } else { | |
| 1374 token = parseIdentifier(token); | |
| 1375 } | |
| 1376 } else if (optional('operator', token)) { | |
| 1377 // operator <op> (... | |
| 1307 listener.handleNoType(token); | 1378 listener.handleNoType(token); |
| 1308 listener.beginFunctionName(token); | 1379 listener.beginFunctionName(token); |
| 1309 token = parseOperatorName(token); | 1380 token = parseOperatorName(token); |
| 1310 } else { | 1381 } else { |
| 1382 // <type>? <get>? <name> | |
| 1311 token = parseReturnTypeOpt(token); | 1383 token = parseReturnTypeOpt(token); |
| 1312 if (identical(getOrSet, token)) token = token.next; | 1384 if (identical(getOrSet, token)) { |
| 1385 token = token.next; | |
| 1386 } | |
| 1313 listener.beginFunctionName(token); | 1387 listener.beginFunctionName(token); |
| 1314 if (optional('operator', token)) { | 1388 if (optional('operator', token)) { |
| 1315 token = parseOperatorName(token); | 1389 token = parseOperatorName(token); |
| 1316 } else { | 1390 } else { |
| 1317 token = parseIdentifier(token); | 1391 token = parseIdentifier(token); |
| 1318 } | 1392 } |
| 1319 } | 1393 } |
| 1320 token = parseQualifiedRestOpt(token); | 1394 token = parseQualifiedRestOpt(token); |
| 1321 listener.endFunctionName(token); | 1395 listener.endFunctionName(token); |
| 1322 token = parseFormalParametersOpt(token); | 1396 token = parseFormalParametersOpt(token); |
| (...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2598 } | 2672 } |
| 2599 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2673 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 2600 return expectSemicolon(token); | 2674 return expectSemicolon(token); |
| 2601 } | 2675 } |
| 2602 | 2676 |
| 2603 Token parseEmptyStatement(Token token) { | 2677 Token parseEmptyStatement(Token token) { |
| 2604 listener.handleEmptyStatement(token); | 2678 listener.handleEmptyStatement(token); |
| 2605 return expectSemicolon(token); | 2679 return expectSemicolon(token); |
| 2606 } | 2680 } |
| 2607 } | 2681 } |
| OLD | NEW |