| 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 |