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 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 Loading... | |
| 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 enum TypeContinuation { | |
|
Paul Berry
2017/06/24 14:16:26
It would be nice to have a comment explaining what
ahe
2017/06/26 10:14:00
I want to reserve that word for you :-)
| |
| 184 Typedef, | |
| 185 } | |
| 186 | |
| 183 /// An event generating parser of Dart programs. This parser expects all tokens | 187 /// An event generating parser of Dart programs. This parser expects all tokens |
| 184 /// in a linked list (aka a token stream). | 188 /// in a linked list (aka a token stream). |
| 185 /// | 189 /// |
| 186 /// The class [Scanner] is used to generate a token stream. See the file | 190 /// The class [Scanner] is used to generate a token stream. See the file |
| 187 /// [scanner.dart](../scanner.dart). | 191 /// [scanner.dart](../scanner.dart). |
| 188 /// | 192 /// |
| 189 /// Subclasses of the class [Listener] are used to listen to events. | 193 /// Subclasses of the class [Listener] are used to listen to events. |
| 190 /// | 194 /// |
| 191 /// Most methods of this class belong in one of three major categories: parse | 195 /// 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 | 196 /// methods, peek methods, and skip methods. Parse methods all have the prefix |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 | 612 |
| 609 Token parseScript(Token token) { | 613 Token parseScript(Token token) { |
| 610 listener.handleScript(token); | 614 listener.handleScript(token); |
| 611 return token.next; | 615 return token.next; |
| 612 } | 616 } |
| 613 | 617 |
| 614 Token parseTypedef(Token token) { | 618 Token parseTypedef(Token token) { |
| 615 Token typedefKeyword = token; | 619 Token typedefKeyword = token; |
| 616 listener.beginFunctionTypeAlias(token); | 620 listener.beginFunctionTypeAlias(token); |
| 617 Token equals; | 621 Token equals; |
| 618 if (optional('=', peekAfterNominalType(token.next))) { | 622 Token afterType = parseType(token.next, |
| 623 isOptional: true, continuation: TypeContinuation.Typedef); | |
| 624 if (afterType == null) { | |
| 619 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); | 625 token = parseIdentifier(token.next, IdentifierContext.typedefDeclaration); |
| 620 token = parseTypeVariablesOpt(token); | 626 token = parseTypeVariablesOpt(token); |
| 621 equals = token; | 627 equals = token; |
| 622 token = expect('=', token); | 628 token = expect('=', token); |
| 623 token = parseType(token); | 629 token = parseType(token); |
| 624 } else { | 630 } else { |
| 625 token = parseType(token.next, isOptional: true); | 631 token = afterType; |
| 626 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); | 632 token = parseIdentifier(token, IdentifierContext.typedefDeclaration); |
| 627 token = parseTypeVariablesOpt(token); | 633 token = parseTypeVariablesOpt(token); |
| 628 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias); | 634 token = parseFormalParameters(token, MemberKind.FunctionTypeAlias); |
| 629 } | 635 } |
| 630 listener.endFunctionTypeAlias(typedefKeyword, equals, token); | 636 listener.endFunctionTypeAlias(typedefKeyword, equals, token); |
| 631 return expect(';', token); | 637 return expect(';', token); |
| 632 } | 638 } |
| 633 | 639 |
| 634 Token parseMixinApplication(Token token) { | 640 Token parseMixinApplication(Token token) { |
| 635 listener.beginMixinApplication(token); | 641 listener.beginMixinApplication(token); |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 count++; | 967 count++; |
| 962 } | 968 } |
| 963 } | 969 } |
| 964 Token endBrace = token; | 970 Token endBrace = token; |
| 965 token = expect('}', token); | 971 token = expect('}', token); |
| 966 listener.endEnum(enumKeyword, endBrace, count); | 972 listener.endEnum(enumKeyword, endBrace, count); |
| 967 return token; | 973 return token; |
| 968 } | 974 } |
| 969 | 975 |
| 970 Token parseClassOrNamedMixinApplication(Token token) { | 976 Token parseClassOrNamedMixinApplication(Token token) { |
| 977 listener.beginClassOrNamedMixinApplication(token); | |
| 971 Token begin = token; | 978 Token begin = token; |
| 972 Token abstractKeyword; | 979 if (optional('abstract', token)) { |
| 980 token = parseModifier(token); | |
| 981 listener.handleModifiers(1); | |
| 982 } else { | |
| 983 listener.handleModifiers(0); | |
| 984 } | |
| 973 Token classKeyword = token; | 985 Token classKeyword = token; |
| 974 if (optional('abstract', token)) { | 986 token = expect("class", token); |
| 975 abstractKeyword = token; | 987 Token name = token; |
| 976 token = token.next; | 988 token = |
| 977 classKeyword = token; | 989 parseIdentifier(name, IdentifierContext.classOrNamedMixinDeclaration); |
| 978 } | 990 token = parseTypeVariablesOpt(token); |
| 979 assert(optional('class', classKeyword)); | 991 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); | 992 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; | 993 Token equals = token; |
| 1001 token = token.next; | 994 token = token.next; |
| 1002 return parseNamedMixinApplication( | 995 return parseNamedMixinApplication( |
| 1003 token, begin, classKeyword, name, equals); | 996 token, begin, classKeyword, name, equals); |
| 1004 } else { | 997 } else { |
| 998 listener.beginClassDeclaration(begin, name); | |
| 1005 return parseClass(token, begin, classKeyword, name); | 999 return parseClass(token, begin, classKeyword, name); |
| 1006 } | 1000 } |
| 1007 } | 1001 } |
| 1008 | 1002 |
| 1009 Token parseNamedMixinApplication( | 1003 Token parseNamedMixinApplication( |
| 1010 Token token, Token begin, Token classKeyword, Token name, Token equals) { | 1004 Token token, Token begin, Token classKeyword, Token name, Token equals) { |
| 1011 token = parseMixinApplication(token); | 1005 token = parseMixinApplication(token); |
| 1012 Token implementsKeyword = null; | 1006 Token implementsKeyword = null; |
| 1013 if (optional('implements', token)) { | 1007 if (optional('implements', token)) { |
| 1014 implementsKeyword = token; | 1008 implementsKeyword = token; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 bool notEofOrValue(String value, Token token) { | 1126 bool notEofOrValue(String value, Token token) { |
| 1133 return !identical(token.kind, EOF_TOKEN) && | 1127 return !identical(token.kind, EOF_TOKEN) && |
| 1134 !identical(value, token.stringValue); | 1128 !identical(value, token.stringValue); |
| 1135 } | 1129 } |
| 1136 | 1130 |
| 1137 bool isGeneralizedFunctionType(Token token) { | 1131 bool isGeneralizedFunctionType(Token token) { |
| 1138 return optional('Function', token) && | 1132 return optional('Function', token) && |
| 1139 (optional('<', token.next) || optional('(', token.next)); | 1133 (optional('<', token.next) || optional('(', token.next)); |
| 1140 } | 1134 } |
| 1141 | 1135 |
| 1142 Token parseType(Token token, {bool isOptional: false}) { | 1136 Token parseType(Token token, |
|
Paul Berry
2017/06/24 14:16:26
It would be nice to have a comment here explaining
ahe
2017/06/26 10:14:01
Done.
| |
| 1137 {bool isOptional: false, TypeContinuation continuation}) { | |
| 1138 if (continuation != null) { | |
|
ahe
2017/06/24 10:10:31
A little bit of context here:
My plan is to move
| |
| 1139 switch (continuation) { | |
|
Paul Berry
2017/06/24 14:16:26
Nit: It seems odd to have a null check followed by
ahe
2017/06/26 10:14:00
Done.
| |
| 1140 case TypeContinuation.Typedef: | |
| 1141 if (optional('=', peekAfterNominalType(token))) { | |
| 1142 return null; // This isn't a type, it's a new-style typedef. | |
| 1143 } | |
| 1144 break; | |
| 1145 | |
| 1146 default: | |
| 1147 throw "Internal error: Unhandled continuation '$continuation'."; | |
| 1148 } | |
| 1149 } | |
| 1143 if (isOptional) { | 1150 if (isOptional) { |
| 1144 do { | 1151 do { |
| 1145 if (optional("void", token)) { | 1152 if (optional("void", token)) { |
| 1146 if (isGeneralizedFunctionType(token.next)) { | 1153 if (isGeneralizedFunctionType(token.next)) { |
| 1147 // This is a type, parse it. | 1154 // This is a type, parse it. |
| 1148 break; | 1155 break; |
| 1149 } else { | 1156 } else { |
| 1150 listener.handleVoidKeyword(token); | 1157 listener.handleVoidKeyword(token); |
| 1151 return token.next; | 1158 return token.next; |
| 1152 } | 1159 } |
| (...skipping 2872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4025 return reportUnrecoverableError( | 4032 return reportUnrecoverableError( |
| 4026 token, () => code.format(uri, token.charOffset, string)); | 4033 token, () => code.format(uri, token.charOffset, string)); |
| 4027 } | 4034 } |
| 4028 } | 4035 } |
| 4029 | 4036 |
| 4030 typedef FastaMessage NoArgument(Uri uri, int charOffset); | 4037 typedef FastaMessage NoArgument(Uri uri, int charOffset); |
| 4031 | 4038 |
| 4032 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); | 4039 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); |
| 4033 | 4040 |
| 4034 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); | 4041 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); |
| OLD | NEW |