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 { |
| 8 final String type; |
| 9 const FormalParameterType(this.type); |
| 10 bool get isRequired => this == REQUIRED; |
| 11 bool get isPositional => this == POSITIONAL; |
| 12 bool get isNamed => this == NAMED; |
| 13 static final REQUIRED = const FormalParameterType('required'); |
| 14 static final POSITIONAL = const FormalParameterType('positional'); |
| 15 static final NAMED = const FormalParameterType('named'); |
| 16 } |
| 17 |
7 /** | 18 /** |
8 * An event generating parser of Dart programs. This parser expects | 19 * An event generating parser of Dart programs. This parser expects |
9 * all tokens in a linked list (aka a token stream). | 20 * all tokens in a linked list (aka a token stream). |
10 * | 21 * |
11 * The class [Scanner] is used to generate a token stream. See the | 22 * The class [Scanner] is used to generate a token stream. See the |
12 * file scanner.dart. | 23 * file scanner.dart. |
13 * | 24 * |
14 * Subclasses of the class [Listener] are used to listen to events. | 25 * Subclasses of the class [Listener] are used to listen to events. |
15 * | 26 * |
16 * Most methods of this class belong in one of two major categories: | 27 * Most methods of this class belong in one of two major categories: |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 ++parameterCount; | 310 ++parameterCount; |
300 token = token.next; | 311 token = token.next; |
301 String value = token.stringValue; | 312 String value = token.stringValue; |
302 if (identical(value, '[')) { | 313 if (identical(value, '[')) { |
303 token = parseOptionalFormalParameters(token, false); | 314 token = parseOptionalFormalParameters(token, false); |
304 break; | 315 break; |
305 } else if (identical(value, '{')) { | 316 } else if (identical(value, '{')) { |
306 token = parseOptionalFormalParameters(token, true); | 317 token = parseOptionalFormalParameters(token, true); |
307 break; | 318 break; |
308 } | 319 } |
309 token = parseFormalParameter(token); | 320 token = parseFormalParameter(token, FormalParameterType.REQUIRED); |
310 } while (optional(',', token)); | 321 } while (optional(',', token)); |
311 listener.endFormalParameters(parameterCount, begin, token); | 322 listener.endFormalParameters(parameterCount, begin, token); |
312 return expect(')', token); | 323 return expect(')', token); |
313 } | 324 } |
314 | 325 |
315 Token parseFormalParameter(Token token) { | 326 Token parseFormalParameter(Token token, FormalParameterType type) { |
316 listener.beginFormalParameter(token); | 327 listener.beginFormalParameter(token); |
317 token = parseModifiers(token); | 328 token = parseModifiers(token); |
318 // TODO(ahe): Validate that there are formal parameters if void. | 329 // TODO(ahe): Validate that there are formal parameters if void. |
319 token = parseReturnTypeOpt(token); | 330 token = parseReturnTypeOpt(token); |
320 Token thisKeyword = null; | 331 Token thisKeyword = null; |
321 if (optional('this', token)) { | 332 if (optional('this', token)) { |
322 thisKeyword = token; | 333 thisKeyword = token; |
323 // TODO(ahe): Validate field initializers are only used in | 334 // TODO(ahe): Validate field initializers are only used in |
324 // constructors, and not for function-typed arguments. | 335 // constructors, and not for function-typed arguments. |
325 token = expect('.', token.next); | 336 token = expect('.', token.next); |
326 } | 337 } |
327 token = parseIdentifier(token); | 338 token = parseIdentifier(token); |
328 if (optional('(', token)) { | 339 if (optional('(', token)) { |
329 token = parseFormalParameters(token); | 340 token = parseFormalParameters(token); |
330 listener.handleFunctionTypedFormalParameter(token); | 341 listener.handleFunctionTypedFormalParameter(token); |
331 } | 342 } |
332 String value = token.stringValue; | 343 String value = token.stringValue; |
333 if ((identical('=', value)) || (identical(':', value))) { | 344 if ((identical('=', value)) || (identical(':', value))) { |
334 // TODO(ahe): Validate that these are only used for optional parameters. | 345 // TODO(ahe): Validate that these are only used for optional parameters. |
335 Token equal = token; | 346 Token equal = token; |
336 token = parseExpression(token.next); | 347 token = parseExpression(token.next); |
337 listener.handleValuedFormalParameter(equal, token); | 348 listener.handleValuedFormalParameter(equal, token); |
| 349 if (type.isRequired) { |
| 350 listener.reportError(equal, |
| 351 MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT); |
| 352 } else if (type.isNamed && identical('=', value)) { |
| 353 listener.reportError(equal, MessageKind.NAMED_PARAMETER_WITH_EQUALS); |
| 354 } else if (type.isPositional && identical(':', value)) { |
| 355 listener.reportError(equal, |
| 356 MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS); |
| 357 } |
338 } | 358 } |
339 listener.endFormalParameter(thisKeyword); | 359 listener.endFormalParameter(thisKeyword); |
340 return token; | 360 return token; |
341 } | 361 } |
342 | 362 |
343 Token parseOptionalFormalParameters(Token token, bool isNamed) { | 363 Token parseOptionalFormalParameters(Token token, bool isNamed) { |
344 Token begin = token; | 364 Token begin = token; |
345 listener.beginOptionalFormalParameters(begin); | 365 listener.beginOptionalFormalParameters(begin); |
346 assert((isNamed && optional('{', token)) || optional('[', token)); | 366 assert((isNamed && optional('{', token)) || optional('[', token)); |
347 int parameterCount = 0; | 367 int parameterCount = 0; |
348 do { | 368 do { |
349 token = token.next; | 369 token = token.next; |
350 token = parseFormalParameter(token); | 370 var type = isNamed ? FormalParameterType.NAMED |
| 371 : FormalParameterType.POSITIONAL; |
| 372 token = parseFormalParameter(token, type); |
351 ++parameterCount; | 373 ++parameterCount; |
352 } while (optional(',', token)); | 374 } while (optional(',', token)); |
353 listener.endOptionalFormalParameters(parameterCount, begin, token); | 375 listener.endOptionalFormalParameters(parameterCount, begin, token); |
354 if (isNamed) { | 376 if (isNamed) { |
355 return expect('}', token); | 377 return expect('}', token); |
356 } else { | 378 } else { |
357 return expect(']', token); | 379 return expect(']', token); |
358 } | 380 } |
359 } | 381 } |
360 | 382 |
(...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 } | 2401 } |
2380 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 2402 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
2381 return expectSemicolon(token); | 2403 return expectSemicolon(token); |
2382 } | 2404 } |
2383 | 2405 |
2384 Token parseEmptyStatement(Token token) { | 2406 Token parseEmptyStatement(Token token) { |
2385 listener.handleEmptyStatement(token); | 2407 listener.handleEmptyStatement(token); |
2386 return expectSemicolon(token); | 2408 return expectSemicolon(token); |
2387 } | 2409 } |
2388 } | 2410 } |
OLD | NEW |