Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2948383002: Remove peeking from parseTypedef and parseClassOrNamedMixinApplication. (Closed)
Patch Set: Addressed comments and then some. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 library fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' 7 import '../fasta_codes.dart'
8 show 8 show
9 FastaCode, 9 FastaCode,
10 FastaMessage, 10 FastaMessage,
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 /// 173 ///
174 /// An assertion can legally occur as a statement. However, assertions are also 174 /// An assertion can legally occur as a statement. However, assertions are also
175 /// experimentally allowed in initializers. For improved error recovery, we 175 /// experimentally allowed in initializers. For improved error recovery, we
176 /// also attempt to parse asserts as expressions. 176 /// also attempt to parse asserts as expressions.
177 enum Assert { 177 enum Assert {
178 Expression, 178 Expression,
179 Initializer, 179 Initializer,
180 Statement, 180 Statement,
181 } 181 }
182 182
183 /// Indication of how the parser should continue after (attempting) to parse a
184 /// type.
185 ///
186 /// Depending on the continuation, the parser may not parse a type at all.
187 enum TypeContinuation {
188 /// Indicates that a type is unconditionally expected.
189 Required,
190
191 /// Indicates that a type may follow. If the following matches one of these
192 /// productions, it is parsed as a type:
193 ///
194 /// - `'void'`
195 /// - `'Function' ( '(' | '<' )`
196 /// - `identifier ('.' identifier)? ('<' ... '>')? identifer`
197 ///
198 /// Otherwise, do nothing.
199 Optional,
200
201 /// Indicates that the keyword `typedef` has just been seen, and the parser
202 /// should parse the following as a type unless it is followed by `=`.
203 Typedef,
204 }
205
183 /// An event generating parser of Dart programs. This parser expects all tokens 206 /// An event generating parser of Dart programs. This parser expects all tokens
184 /// in a linked list (aka a token stream). 207 /// in a linked list (aka a token stream).
185 /// 208 ///
186 /// The class [Scanner] is used to generate a token stream. See the file 209 /// The class [Scanner] is used to generate a token stream. See the file
187 /// [scanner.dart](../scanner.dart). 210 /// [scanner.dart](../scanner.dart).
188 /// 211 ///
189 /// Subclasses of the class [Listener] are used to listen to events. 212 /// Subclasses of the class [Listener] are used to listen to events.
190 /// 213 ///
191 /// Most methods of this class belong in one of three major categories: parse 214 /// Most methods of this class belong in one of three major categories: parse
192 /// methods, peek methods, and skip methods. Parse methods all have the prefix 215 /// methods, peek methods, and skip methods. Parse methods all have the prefix
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 631
609 Token parseScript(Token token) { 632 Token parseScript(Token token) {
610 listener.handleScript(token); 633 listener.handleScript(token);
611 return token.next; 634 return token.next;
612 } 635 }
613 636
614 Token parseTypedef(Token token) { 637 Token parseTypedef(Token token) {
615 Token typedefKeyword = token; 638 Token typedefKeyword = token;
616 listener.beginFunctionTypeAlias(token); 639 listener.beginFunctionTypeAlias(token);
617 Token equals; 640 Token equals;
618 if (optional('=', peekAfterNominalType(token.next))) { 641 Token afterType = parseType(token.next, TypeContinuation.Typedef);
642 if (afterType == null) {
619 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); 643 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration);
620 token = parseTypeVariablesOpt(token); 644 token = parseTypeVariablesOpt(token);
621 equals = token; 645 equals = token;
622 token = expect('=', token); 646 token = expect('=', token);
623 token = parseType(token); 647 token = parseType(token);
624 } else { 648 } else {
625 token = parseType(token.next, isOptional: true); 649 token = afterType;
626 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); 650 token = parseIdentifier(token, IdentifierContext.typedefDeclaration);
627 token = parseTypeVariablesOpt(token); 651 token = parseTypeVariablesOpt(token);
628 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias); 652 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias);
629 } 653 }
630 listener.endFunctionTypeAlias(typedefKeyword, equals, token); 654 listener.endFunctionTypeAlias(typedefKeyword, equals, token);
631 return expect(';', token); 655 return expect(';', token);
632 } 656 }
633 657
634 Token parseMixinApplication(Token token) { 658 Token parseMixinApplication(Token token) {
635 listener.beginMixinApplication(token); 659 listener.beginMixinApplication(token);
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 count++; 985 count++;
962 } 986 }
963 } 987 }
964 Token endBrace = token; 988 Token endBrace = token;
965 token = expect('}', token); 989 token = expect('}', token);
966 listener.endEnum(enumKeyword, endBrace, count); 990 listener.endEnum(enumKeyword, endBrace, count);
967 return token; 991 return token;
968 } 992 }
969 993
970 Token parseClassOrNamedMixinApplication(Token token) { 994 Token parseClassOrNamedMixinApplication(Token token) {
995 listener.beginClassOrNamedMixinApplication(token);
971 Token begin = token; 996 Token begin = token;
972 Token abstractKeyword; 997 if (optional('abstract', token)) {
998 token = parseModifier(token);
999 listener.handleModifiers(1);
1000 } else {
1001 listener.handleModifiers(0);
1002 }
973 Token classKeyword = token; 1003 Token classKeyword = token;
974 if (optional('abstract', token)) { 1004 token = expect("class", token);
975 abstractKeyword = token; 1005 Token name = token;
976 token = token.next; 1006 token =
977 classKeyword = token; 1007 parseIdentifier(name, IdentifierContext.classOrNamedMixinDeclaration);
978 } 1008 token = parseTypeVariablesOpt(token);
979 assert(optional('class', classKeyword)); 1009 if (optional('=', token)) {
980 int modifierCount = 0;
981 if (abstractKeyword != null) {
982 parseModifier(abstractKeyword);
983 modifierCount++;
984 }
985 listener.handleModifiers(modifierCount);
986 bool isMixinApplication = optional('=', peekAfterNominalType(token));
987 Token name = token.next;
988
989 if (isMixinApplication) {
990 token = parseIdentifier(name, IdentifierContext.namedMixinDeclaration);
991 listener.beginNamedMixinApplication(begin, name); 1010 listener.beginNamedMixinApplication(begin, name);
992 } else {
993 token = parseIdentifier(name, IdentifierContext.classDeclaration);
994 listener.beginClassDeclaration(begin, name);
995 }
996
997 token = parseTypeVariablesOpt(token);
998
999 if (optional('=', token)) {
1000 Token equals = token; 1011 Token equals = token;
1001 token = token.next; 1012 token = token.next;
1002 return parseNamedMixinApplication( 1013 return parseNamedMixinApplication(
1003 token, begin, classKeyword, name, equals); 1014 token, begin, classKeyword, name, equals);
1004 } else { 1015 } else {
1016 listener.beginClassDeclaration(begin, name);
1005 return parseClass(token, begin, classKeyword, name); 1017 return parseClass(token, begin, classKeyword, name);
1006 } 1018 }
1007 } 1019 }
1008 1020
1009 Token parseNamedMixinApplication( 1021 Token parseNamedMixinApplication(
1010 Token token, Token begin, Token classKeyword, Token name, Token equals) { 1022 Token token, Token begin, Token classKeyword, Token name, Token equals) {
1011 token = parseMixinApplication(token); 1023 token = parseMixinApplication(token);
1012 Token implementsKeyword = null; 1024 Token implementsKeyword = null;
1013 if (optional('implements', token)) { 1025 if (optional('implements', token)) {
1014 implementsKeyword = token; 1026 implementsKeyword = token;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 bool notEofOrValue(String value, Token token) { 1144 bool notEofOrValue(String value, Token token) {
1133 return !identical(token.kind, EOF_TOKEN) && 1145 return !identical(token.kind, EOF_TOKEN) &&
1134 !identical(value, token.stringValue); 1146 !identical(value, token.stringValue);
1135 } 1147 }
1136 1148
1137 bool isGeneralizedFunctionType(Token token) { 1149 bool isGeneralizedFunctionType(Token token) {
1138 return optional('Function', token) && 1150 return optional('Function', token) &&
1139 (optional('<', token.next) || optional('(', token.next)); 1151 (optional('<', token.next) || optional('(', token.next));
1140 } 1152 }
1141 1153
1142 Token parseType(Token token, {bool isOptional: false}) { 1154 /// Parse a type, if it is appropriate to do so.
1143 if (isOptional) { 1155 ///
1144 do { 1156 /// If this method can parse a type, it will return the next (non-null) token
1157 /// after the type. Otherwise, it returns null.
1158 Token parseType(Token token,
1159 [TypeContinuation continuation = TypeContinuation.Required]) {
1160 switch (continuation) {
1161 case TypeContinuation.Typedef:
1162 if (optional('=', peekAfterNominalType(token))) {
1163 return null; // This isn't a type, it's a new-style typedef.
1164 }
1165 continue optional;
1166
1167 optional:
1168 case TypeContinuation.Optional:
1145 if (optional("void", token)) { 1169 if (optional("void", token)) {
1146 if (isGeneralizedFunctionType(token.next)) { 1170 if (isGeneralizedFunctionType(token.next)) {
1147 // This is a type, parse it. 1171 // This is a type, parse it.
1148 break; 1172 break;
1149 } else { 1173 } else {
1150 listener.handleVoidKeyword(token); 1174 listener.handleVoidKeyword(token);
1151 return token.next; 1175 return token.next;
1152 } 1176 }
1153 } else { 1177 } else {
1154 if (isGeneralizedFunctionType(token)) { 1178 if (isGeneralizedFunctionType(token)) {
1155 // Function type without return type, parse it. 1179 // Function type without return type, parse it.
1156 break; 1180 break;
1157 } 1181 }
1158 token = listener.injectGenericCommentTypeAssign(token); 1182 token = listener.injectGenericCommentTypeAssign(token);
1159 Token peek = peekAfterIfType(token); 1183 Token peek = peekAfterIfType(token);
1160 if (peek != null && (peek.isIdentifier || optional('this', peek))) { 1184 if (peek != null && (peek.isIdentifier || optional('this', peek))) {
1161 // This is a type followed by an identifier, parse it. 1185 // This is a type followed by an identifier, parse it.
1162 break; 1186 break;
1163 } 1187 }
1164 listener.handleNoType(token); 1188 listener.handleNoType(token);
1165 return token; 1189 return token;
1166 } 1190 }
1167 } while (false); 1191 break;
1192
1193 case TypeContinuation.Required:
1194 break;
1195
1196 default:
1197 throw "Internal error: Unhandled continuation '$continuation'.";
1168 } 1198 }
1169 Token begin = token; 1199 Token begin = token;
1170 if (isGeneralizedFunctionType(token)) { 1200 if (isGeneralizedFunctionType(token)) {
1171 // A function type without return type. 1201 // A function type without return type.
1172 // Push the non-existing return type first. The loop below will 1202 // Push the non-existing return type first. The loop below will
1173 // generate the full type. 1203 // generate the full type.
1174 listener.handleNoType(token); 1204 listener.handleNoType(token);
1175 } else if (optional("void", token) && 1205 } else if (optional("void", token) &&
1176 isGeneralizedFunctionType(token.next)) { 1206 isGeneralizedFunctionType(token.next)) {
1177 listener.handleVoidKeyword(token); 1207 listener.handleVoidKeyword(token);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 if (externalModifier != null) { 1422 if (externalModifier != null) {
1393 parseModifier(externalModifier); 1423 parseModifier(externalModifier);
1394 listener.handleModifiers(1); 1424 listener.handleModifiers(1);
1395 } else { 1425 } else {
1396 listener.handleModifiers(0); 1426 listener.handleModifiers(0);
1397 } 1427 }
1398 1428
1399 if (type == null) { 1429 if (type == null) {
1400 listener.handleNoType(name); 1430 listener.handleNoType(name);
1401 } else { 1431 } else {
1402 parseType(type, isOptional: true); 1432 parseType(type, TypeContinuation.Optional);
1403 } 1433 }
1404 Token token = 1434 Token token =
1405 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration); 1435 parseIdentifier(name, IdentifierContext.topLevelFunctionDeclaration);
1406 1436
1407 bool isGetter = false; 1437 bool isGetter = false;
1408 if (getOrSet == null) { 1438 if (getOrSet == null) {
1409 token = parseTypeVariablesOpt(token); 1439 token = parseTypeVariablesOpt(token);
1410 } else { 1440 } else {
1411 isGetter = optional("get", getOrSet); 1441 isGetter = optional("get", getOrSet);
1412 listener.handleNoTypeVariables(token); 1442 listener.handleNoTypeVariables(token);
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier); 1822 reportRecoverableErrorCodeWithToken(token, codeExtraneousModifier);
1793 token = token.next; 1823 token = token.next;
1794 } 1824 }
1795 } else { 1825 } else {
1796 break; 1826 break;
1797 } 1827 }
1798 } 1828 }
1799 listener.handleModifiers(count); 1829 listener.handleModifiers(count);
1800 1830
1801 Token beforeType = token; 1831 Token beforeType = token;
1802 token = parseType(token, isOptional: returnTypeAllowed || !typeRequired); 1832 token = parseType(
1833 token,
1834 returnTypeAllowed || !typeRequired
1835 ? TypeContinuation.Optional
1836 : TypeContinuation.Required);
1803 if (typeRequired && beforeType == token) { 1837 if (typeRequired && beforeType == token) {
1804 reportRecoverableErrorCode(token, codeTypeRequired); 1838 reportRecoverableErrorCode(token, codeTypeRequired);
1805 } 1839 }
1806 if (hasVar && beforeType != token) { 1840 if (hasVar && beforeType != token) {
1807 reportRecoverableErrorCode(beforeType, codeTypeAfterVar); 1841 reportRecoverableErrorCode(beforeType, codeTypeAfterVar);
1808 } 1842 }
1809 return token; 1843 return token;
1810 } 1844 }
1811 1845
1812 /// Returns the first token after the type starting at [token]. 1846 /// Returns the first token after the type starting at [token].
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2097 count++; 2131 count++;
2098 } 2132 }
2099 listener.handleModifiers(count); 2133 listener.handleModifiers(count);
2100 } 2134 }
2101 2135
2102 parseModifierList(modifiers); 2136 parseModifierList(modifiers);
2103 2137
2104 if (type == null) { 2138 if (type == null) {
2105 listener.handleNoType(name); 2139 listener.handleNoType(name);
2106 } else { 2140 } else {
2107 parseType(type, isOptional: true); 2141 parseType(type, TypeContinuation.Optional);
2108 } 2142 }
2109 Token token; 2143 Token token;
2110 if (optional('operator', name)) { 2144 if (optional('operator', name)) {
2111 token = parseOperatorName(name); 2145 token = parseOperatorName(name);
2112 if (staticModifier != null) { 2146 if (staticModifier != null) {
2113 reportRecoverableErrorCodeWithToken( 2147 reportRecoverableErrorCodeWithToken(
2114 staticModifier, codeExtraneousModifier); 2148 staticModifier, codeExtraneousModifier);
2115 } 2149 }
2116 } else { 2150 } else {
2117 token = parseIdentifier(name, IdentifierContext.methodDeclaration); 2151 token = parseIdentifier(name, IdentifierContext.methodDeclaration);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2231 listener.beginFunctionDeclaration(token); 2265 listener.beginFunctionDeclaration(token);
2232 token = parseFunction(token); 2266 token = parseFunction(token);
2233 listener.endFunctionDeclaration(token); 2267 listener.endFunctionDeclaration(token);
2234 return token; 2268 return token;
2235 } 2269 }
2236 2270
2237 Token parseFunctionExpression(Token token) { 2271 Token parseFunctionExpression(Token token) {
2238 Token beginToken = token; 2272 Token beginToken = token;
2239 listener.beginFunction(token); 2273 listener.beginFunction(token);
2240 listener.handleModifiers(0); 2274 listener.handleModifiers(0);
2241 token = parseType(token, isOptional: true); 2275 token = parseType(token, TypeContinuation.Optional);
2242 listener.beginFunctionName(token); 2276 listener.beginFunctionName(token);
2243 token = parseIdentifier(token, IdentifierContext.functionExpressionName); 2277 token = parseIdentifier(token, IdentifierContext.functionExpressionName);
2244 listener.endFunctionName(beginToken, token); 2278 listener.endFunctionName(beginToken, token);
2245 token = parseTypeVariablesOpt(token); 2279 token = parseTypeVariablesOpt(token);
2246 token = parseFormalParameters(token, MemberKind.Local); 2280 token = parseFormalParameters(token, MemberKind.Local);
2247 listener.handleNoInitializers(); 2281 listener.handleNoInitializers();
2248 AsyncModifier savedAsyncModifier = asyncState; 2282 AsyncModifier savedAsyncModifier = asyncState;
2249 token = parseAsyncModifier(token); 2283 token = parseAsyncModifier(token);
2250 bool isBlock = optional('{', token); 2284 bool isBlock = optional('{', token);
2251 token = parseFunctionBody(token, true, false); 2285 token = parseFunctionBody(token, true, false);
(...skipping 1773 matching lines...) Expand 10 before | Expand all | Expand 10 after
4025 return reportUnrecoverableError( 4059 return reportUnrecoverableError(
4026 token, () => code.format(uri, token.charOffset, string)); 4060 token, () => code.format(uri, token.charOffset, string));
4027 } 4061 }
4028 } 4062 }
4029 4063
4030 typedef FastaMessage NoArgument(Uri uri, int charOffset); 4064 typedef FastaMessage NoArgument(Uri uri, int charOffset);
4031 4065
4032 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 4066 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
4033 4067
4034 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 4068 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | pkg/front_end/lib/src/fasta/parser/parser.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698