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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 /// [keyword.dart](../scanner/keyword.dart) and ensure the identifier is added | 175 /// [keyword.dart](../scanner/keyword.dart) and ensure the identifier is added |
176 /// to the keyword table. | 176 /// to the keyword table. |
177 /// | 177 /// |
178 /// As a consequence of this, one should not use `==` to compare strings in the | 178 /// As a consequence of this, one should not use `==` to compare strings in the |
179 /// parser. One should favor the methods [optional] and [expected] to recognize | 179 /// parser. One should favor the methods [optional] and [expected] to recognize |
180 /// keywords or identifiers. In some cases, it's possible to compare a token's | 180 /// keywords or identifiers. In some cases, it's possible to compare a token's |
181 /// `stringValue` using [identical], but normally [optional] will suffice. | 181 /// `stringValue` using [identical], but normally [optional] will suffice. |
182 /// | 182 /// |
183 /// Historically, we over-used identical, and when identical is used on other | 183 /// Historically, we over-used identical, and when identical is used on other |
184 /// objects than strings, it can often be replaced by `==`. | 184 /// objects than strings, it can often be replaced by `==`. |
185 /// | |
186 /// ## Flexibility, Extensibility, and Specification | |
187 /// | |
188 /// The parser is designed to be flexible and extensible. It's methods are | |
scheglov
2017/04/06 15:35:35
"Its"
ahe
2017/04/06 15:52:30
Done.
| |
189 /// designed to be overridden in subclasses, so it can be extended to handle | |
190 /// unspecified language extension or experiments while everything in this file | |
191 /// attempts to follow the specification (unless when it interferes with error | |
192 /// recovery). | |
193 /// | |
194 /// We achieve flexibily, extensible, and specification compliance by following | |
195 /// a few rules-of-thumb: | |
196 /// | |
197 /// 1. All methods in the parser should be public. | |
198 /// | |
199 /// 2. The methods follow the specified grammar, and do not implement custom | |
200 /// extensions, for example, `native`. | |
201 /// | |
202 /// 3. The parser doesn't rewrite the token stream (when dealing with `>>`). | |
203 /// | |
204 /// ### Implementing Extensions | |
205 /// | |
206 /// For various reasons, some Dart language implementations have used | |
207 /// custom/unspecified extensions to the Dart grammar. Examples of this | |
208 /// includes diet parsing, patch files, `native` keyword, and generic | |
209 /// comments. This class isn't supposed to implement any of these | |
210 /// features. Instead it provides hooks for those extensions to be implemented | |
211 /// in subclasses or listeners. Let's examine how diet parsing and `native` | |
212 /// keyword is currently supported by Fasta. | |
213 /// | |
214 /// #### Implementation of `native` Keyword | |
215 /// | |
216 /// Both dart2js and the Dart VM have used the `native` keyword to mark methods | |
217 /// that couldn't be implemented in the Dart language and needed to be | |
218 /// implemented in JavaScript or C++, respectively. An example of the syntax | |
219 /// extension used by the Dart VM is: | |
220 /// | |
221 /// nativeFunction() native "NativeFunction"; | |
222 /// | |
223 /// When attempting to parse this function, the parser eventually calls | |
224 /// [parseFunctionBody]. This method will report an unrecoverable error to the | |
225 /// listener with the code [codeExpectedFunctionBody]. The listener can then | |
226 /// look at the error code and the token and use the methods in | |
227 /// [dart_vm_native.dart](dart_vm_native.dart) to parse the native syntax. | |
228 /// | |
229 /// #### Implementation of Diet Parsing | |
230 /// | |
231 /// We say diet parsing when skipping parts of a file. Both dart2js and the | |
Johnni Winther
2017/04/06 13:36:22
"We say diet parsing when skipping" -> "We call it
ahe
2017/04/06 15:52:30
Done.
| |
232 /// Dart VM has been relying on this from early on as it allows them to more | |
scheglov
2017/04/06 15:35:35
"have been"?
ahe
2017/04/06 15:52:30
Done.
| |
233 /// quickly compile small programs that use small parts of big libraries. It's | |
234 /// also become an integrated part of how Fasta builds up outlines before | |
235 /// starting to parse method bodies. | |
236 /// | |
237 /// When looking through this parser, you'll find a number of unused methods | |
238 /// starting with `skip`. These methods are only used by subclasses, such as | |
239 /// [ClassMemberParser](class_member_parser.dart) and | |
240 /// [TopLevelParser](top_level_parser.dart). These methods violate the | |
241 /// principle above about following the specified grammar, and originally lived | |
242 /// in subclasses. However, we realized that these methods were so widely used | |
243 /// and hard to maintain in subclasses, that it made sense to move them here. | |
244 /// | |
245 /// ### Specification and Error Recovery | |
246 /// | |
247 /// To improve error recovery, the parser will inform the listener of | |
248 /// recoverable errors and continue to parse. An example of a recoverable | |
249 /// error is: | |
250 /// | |
251 /// Error: Asynchronous for-loop can only be used in 'async' or 'async*' met hods. | |
Johnni Winther
2017/04/06 13:36:22
Long line.
| |
252 /// main() { await for (var x in []) {} } | |
253 /// ^^^^^ | |
254 /// | |
255 /// For unrecoverable errors, the parser will ask the listener for help to | |
256 /// recover from the error. We haven't made much progress on these kinds of | |
257 /// errors, so in most cases, the parser aborts by skipping to the end of file. | |
258 /// | |
259 /// Historically, this parser has been rather lax in what it allows, and | |
260 /// deferred the enforcement of some syntactical rules to subsequent phases. It | |
261 /// doesn't matter how we got there, only that we've identified that it's | |
262 /// easier if the parser reports as many errors it can, but informs the | |
263 /// listener if the error is recoverable or not. | |
264 /// | |
265 /// Currently, the parser is particularly lax when it comes to the order of | |
266 /// modifiers such as `abstract`, `final`, `static`, etc. Historically, dart2js | |
267 /// would handle such errors in later phases. We hope that these cases will go | |
268 /// away as Fasta matures. | |
185 class Parser { | 269 class Parser { |
186 final Listener listener; | 270 final Listener listener; |
187 | 271 |
188 Uri get uri => listener.uri; | 272 Uri get uri => listener.uri; |
189 | 273 |
190 bool mayParseFunctionExpressions = true; | 274 bool mayParseFunctionExpressions = true; |
191 | 275 |
192 bool parseGenericMethodComments = false; | 276 bool parseGenericMethodComments = false; |
193 | 277 |
194 /// Represents parser state: what asynchronous syntax is allowed in the | 278 /// Represents parser state: what asynchronous syntax is allowed in the |
(...skipping 3660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3855 previous.setNext(firstToken); | 3939 previous.setNext(firstToken); |
3856 beforeToken = firstToken; | 3940 beforeToken = firstToken; |
3857 } | 3941 } |
3858 } | 3942 } |
3859 | 3943 |
3860 typedef FastaMessage NoArgument(Uri uri, int charOffset); | 3944 typedef FastaMessage NoArgument(Uri uri, int charOffset); |
3861 | 3945 |
3862 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); | 3946 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); |
3863 | 3947 |
3864 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); | 3948 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); |
OLD | NEW |