| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 // TODO(jimhug): Error recovery needs major work! | 5 // TODO(jimhug): Error recovery needs major work! |
| 6 /** | 6 /** |
| 7 * A simple recursive descent parser for the dart language. | 7 * A simple recursive descent parser for the dart language. |
| 8 * | 8 * |
| 9 * This parser is designed to be more permissive than the official | 9 * This parser is designed to be more permissive than the official |
| 10 * Dart grammar. It is expected that many grammar errors would be | 10 * Dart grammar. It is expected that many grammar errors would be |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 | 260 |
| 261 var di = declaredIdentifier(false); | 261 var di = declaredIdentifier(false); |
| 262 var typeParams = null; | 262 var typeParams = null; |
| 263 if (_peekKind(TokenKind.LT)) { | 263 if (_peekKind(TokenKind.LT)) { |
| 264 typeParams = typeParameters(); | 264 typeParams = typeParameters(); |
| 265 } | 265 } |
| 266 var formals = formalParameterList(); | 266 var formals = formalParameterList(); |
| 267 _eatSemicolon(); | 267 _eatSemicolon(); |
| 268 | 268 |
| 269 var func = new FunctionDefinition(null, di.type, di.name, formals, | 269 var func = new FunctionDefinition(null, di.type, di.name, formals, |
| 270 null, null, _makeSpan(start)); | 270 null, null, null, _makeSpan(start)); |
| 271 | 271 |
| 272 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); | 272 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); |
| 273 } | 273 } |
| 274 | 274 |
| 275 initializers() { | 275 initializers() { |
| 276 _inInitializers = true; | 276 _inInitializers = true; |
| 277 var ret = []; | 277 var ret = []; |
| 278 do { | 278 do { |
| 279 ret.add(expression()); | 279 ret.add(expression()); |
| 280 } while (_maybeEat(TokenKind.COMMA)); | 280 } while (_maybeEat(TokenKind.COMMA)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 309 // TODO(jimhug): This is just to get isolate.dart to parse - while | 309 // TODO(jimhug): This is just to get isolate.dart to parse - while |
| 310 // we figure out what's really going on in there. | 310 // we figure out what's really going on in there. |
| 311 return functionBody(inExpression); | 311 return functionBody(inExpression); |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 } | 314 } |
| 315 | 315 |
| 316 _error('Expected function body (neither { nor => found)'); | 316 _error('Expected function body (neither { nor => found)'); |
| 317 } | 317 } |
| 318 | 318 |
| 319 finishField(start, modifiers, type, name, value) { | 319 finishField(start, modifiers, typeParams, type, name, value) { |
| 320 if (typeParams !== null) { |
| 321 world.internalError('trying to create a generic field', |
| 322 _makeSpan(start)); |
| 323 } |
| 320 var names = [name]; | 324 var names = [name]; |
| 321 var values = [value]; | 325 var values = [value]; |
| 322 | 326 |
| 323 while (_maybeEat(TokenKind.COMMA)) { | 327 while (_maybeEat(TokenKind.COMMA)) { |
| 324 names.add(identifier()); | 328 names.add(identifier()); |
| 325 if (_maybeEat(TokenKind.ASSIGN)) { | 329 if (_maybeEat(TokenKind.ASSIGN)) { |
| 326 values.add(expression()); | 330 values.add(expression()); |
| 327 } else { | 331 } else { |
| 328 values.add(null); | 332 values.add(null); |
| 329 } | 333 } |
| 330 } | 334 } |
| 331 | 335 |
| 332 _eatSemicolon(); | 336 _eatSemicolon(); |
| 333 return new VariableDefinition(modifiers, type, names, values, | 337 return new VariableDefinition(modifiers, type, names, values, |
| 334 _makeSpan(start)); | 338 _makeSpan(start)); |
| 335 } | 339 } |
| 336 | 340 |
| 337 finishDefinition(start, modifiers, di) { | 341 finishDefinition(int start, List<Token> modifiers, di, |
| 342 List<ParameterType> typeParams) { |
| 338 switch(_peek()) { | 343 switch(_peek()) { |
| 339 case TokenKind.LPAREN: | 344 case TokenKind.LPAREN: |
| 340 var formals = formalParameterList(); | 345 var formals = formalParameterList(); |
| 341 var inits = null; | 346 var inits = null; |
| 342 if (_maybeEat(TokenKind.COLON)) { | 347 if (_maybeEat(TokenKind.COLON)) { |
| 343 inits = initializers(); | 348 inits = initializers(); |
| 344 } | 349 } |
| 345 var body = functionBody(/*inExpression:*/false); | 350 var body = functionBody(/*inExpression:*/false); |
| 346 if (di.name == null) { | 351 if (di.name == null) { |
| 347 // TODO(jimhug): Must be named constructor - verify how? | 352 // TODO(jimhug): Must be named constructor - verify how? |
| 348 di.name = di.type.name; | 353 di.name = di.type.name; |
| 349 } | 354 } |
| 350 return new FunctionDefinition(modifiers, di.type, di.name, formals, | 355 return new FunctionDefinition(modifiers, di.type, di.name, formals, |
| 351 inits, body, _makeSpan(start)); | 356 typeParams, inits, body, _makeSpan(start)); |
| 352 | 357 |
| 353 case TokenKind.ASSIGN: | 358 case TokenKind.ASSIGN: |
| 354 _eat(TokenKind.ASSIGN); | 359 _eat(TokenKind.ASSIGN); |
| 355 var value = expression(); | 360 var value = expression(); |
| 356 return finishField(start, modifiers, di.type, di.name, value); | 361 return finishField(start, modifiers, typeParams, di.type, di.name, value
); |
| 357 | 362 |
| 358 case TokenKind.COMMA: | 363 case TokenKind.COMMA: |
| 359 case TokenKind.SEMICOLON: | 364 case TokenKind.SEMICOLON: |
| 360 return finishField(start, modifiers, di.type, di.name, null); | 365 return finishField(start, modifiers, typeParams, di.type, di.name, null)
; |
| 361 | 366 |
| 362 default: | 367 default: |
| 363 // TODO(jimhug): This error message sucks. | 368 // TODO(jimhug): This error message sucks. |
| 364 _errorExpected('declaration'); | 369 _errorExpected('declaration'); |
| 365 | 370 |
| 366 return null; | 371 return null; |
| 367 } | 372 } |
| 368 } | 373 } |
| 369 | 374 |
| 370 declaration([bool includeOperators=true]) { | 375 declaration([bool includeOperators=true]) { |
| 371 int start = _peekToken.start; | 376 int start = _peekToken.start; |
| 372 if (_peekKind(TokenKind.FACTORY)) { | 377 if (_peekKind(TokenKind.FACTORY)) { |
| 373 return factoryConstructorDeclaration(); | 378 return factoryConstructorDeclaration(); |
| 374 } | 379 } |
| 375 | 380 |
| 376 var modifiers = _readModifiers(); | 381 var modifiers = _readModifiers(); |
| 377 return finishDefinition(start, modifiers, | 382 return finishDefinition(start, modifiers, |
| 378 declaredIdentifier(includeOperators)); | 383 declaredIdentifier(includeOperators), null); |
| 379 } | 384 } |
| 380 | 385 |
| 381 factoryConstructorDeclaration() { | 386 factoryConstructorDeclaration() { |
| 382 int start = _peekToken.start; | 387 int start = _peekToken.start; |
| 383 var factoryToken = _next(); | 388 var factoryToken = _next(); |
| 384 | 389 |
| 385 var names = [identifier()]; | 390 var names = [identifier()]; |
| 386 while (_maybeEat(TokenKind.DOT)) { | 391 while (_maybeEat(TokenKind.DOT)) { |
| 387 names.add(identifier()); | 392 names.add(identifier()); |
| 388 } | 393 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 404 } else { | 409 } else { |
| 405 name = new Identifier('', names[0].span); | 410 name = new Identifier('', names[0].span); |
| 406 } | 411 } |
| 407 | 412 |
| 408 if (names.length > 1) { | 413 if (names.length > 1) { |
| 409 // TODO(jimhug): This is nasty to support and currently unused. | 414 // TODO(jimhug): This is nasty to support and currently unused. |
| 410 _error('unsupported qualified name for factory', names[0].span); | 415 _error('unsupported qualified name for factory', names[0].span); |
| 411 } | 416 } |
| 412 type = new NameTypeReference(false, names[0], null, names[0].span); | 417 type = new NameTypeReference(false, names[0], null, names[0].span); |
| 413 var di = new DeclaredIdentifier(type, name, _makeSpan(start)); | 418 var di = new DeclaredIdentifier(type, name, _makeSpan(start)); |
| 414 return finishDefinition(start, [factoryToken], di); | 419 return finishDefinition(start, [factoryToken], di, typeParams); |
| 415 } | 420 } |
| 416 | 421 |
| 417 /////////////////////////////////////////////////////////////////// | 422 /////////////////////////////////////////////////////////////////// |
| 418 // Statement productions | 423 // Statement productions |
| 419 /////////////////////////////////////////////////////////////////// | 424 /////////////////////////////////////////////////////////////////// |
| 420 Statement statement() { | 425 Statement statement() { |
| 421 switch (_peek()) { | 426 switch (_peek()) { |
| 422 case TokenKind.BREAK: | 427 case TokenKind.BREAK: |
| 423 return breakStatement(); | 428 return breakStatement(); |
| 424 case TokenKind.CONTINUE: | 429 case TokenKind.CONTINUE: |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 if (expr.func.body is! BlockStatement) { | 479 if (expr.func.body is! BlockStatement) { |
| 475 _eatSemicolon(); | 480 _eatSemicolon(); |
| 476 expr.func.span = _makeSpan(start); | 481 expr.func.span = _makeSpan(start); |
| 477 } | 482 } |
| 478 return expr.func; | 483 return expr.func; |
| 479 } else if (expr is DeclaredIdentifier) { | 484 } else if (expr is DeclaredIdentifier) { |
| 480 var value = null; | 485 var value = null; |
| 481 if (_maybeEat(TokenKind.ASSIGN)) { | 486 if (_maybeEat(TokenKind.ASSIGN)) { |
| 482 value = expression(); | 487 value = expression(); |
| 483 } | 488 } |
| 484 return finishField(start, null, expr.type, expr.name, value); | 489 return finishField(start, null, null, expr.type, expr.name, value); |
| 485 } else if (_isBin(expr, TokenKind.ASSIGN) && | 490 } else if (_isBin(expr, TokenKind.ASSIGN) && |
| 486 (expr.x is DeclaredIdentifier)) { | 491 (expr.x is DeclaredIdentifier)) { |
| 487 DeclaredIdentifier di = expr.x; // TODO(jimhug): inference should handle! | 492 DeclaredIdentifier di = expr.x; // TODO(jimhug): inference should handle! |
| 488 return finishField(start, null, di.type, di.name, expr.y); | 493 return finishField(start, null, null, di.type, di.name, expr.y); |
| 489 } else if (_isBin(expr, TokenKind.LT) && _maybeEat(TokenKind.COMMA)) { | 494 } else if (_isBin(expr, TokenKind.LT) && _maybeEat(TokenKind.COMMA)) { |
| 490 var baseType = _makeType(expr.x); | 495 var baseType = _makeType(expr.x); |
| 491 var typeArgs = [_makeType(expr.y)]; | 496 var typeArgs = [_makeType(expr.y)]; |
| 492 var gt = _finishTypeArguments(baseType, 0, typeArgs); | 497 var gt = _finishTypeArguments(baseType, 0, typeArgs); |
| 493 var name = identifier(); | 498 var name = identifier(); |
| 494 var value = null; | 499 var value = null; |
| 495 if (_maybeEat(TokenKind.ASSIGN)) { | 500 if (_maybeEat(TokenKind.ASSIGN)) { |
| 496 value = expression(); | 501 value = expression(); |
| 497 } | 502 } |
| 498 return finishField(expr.span.start, null, gt, name, value); | 503 return finishField(expr.span.start, null, null, gt, name, value); |
| 499 } else { | 504 } else { |
| 500 _eatSemicolon(); | 505 _eatSemicolon(); |
| 501 return new ExpressionStatement(expr, _makeSpan(expr.span.start)); | 506 return new ExpressionStatement(expr, _makeSpan(expr.span.start)); |
| 502 } | 507 } |
| 503 } | 508 } |
| 504 | 509 |
| 505 Expression testCondition() { | 510 Expression testCondition() { |
| 506 _eatLeftParen(); | 511 _eatLeftParen(); |
| 507 var ret = expression(); | 512 var ret = expression(); |
| 508 _eat(TokenKind.RPAREN); | 513 _eat(TokenKind.RPAREN); |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 _errorExpected('string literal, but found incomplete string'); | 1160 _errorExpected('string literal, but found incomplete string'); |
| 1156 } | 1161 } |
| 1157 return null; | 1162 return null; |
| 1158 } | 1163 } |
| 1159 | 1164 |
| 1160 _parenOrLambda() { | 1165 _parenOrLambda() { |
| 1161 int start = _peekToken.start; | 1166 int start = _peekToken.start; |
| 1162 if (_atClosureParameters()) { | 1167 if (_atClosureParameters()) { |
| 1163 var formals = formalParameterList(); | 1168 var formals = formalParameterList(); |
| 1164 var body = functionBody(true); | 1169 var body = functionBody(true); |
| 1165 var func = new FunctionDefinition(null, null, null, formals, null, | 1170 var func = new FunctionDefinition(null, null, null, formals, null, null, |
| 1166 body, _makeSpan(start)); | 1171 body, _makeSpan(start)); |
| 1167 return new LambdaExpression(func, func.span); | 1172 return new LambdaExpression(func, func.span); |
| 1168 } else { | 1173 } else { |
| 1169 var saved = _inInitializers; | 1174 var saved = _inInitializers; |
| 1170 _inInitializers = false; | 1175 _inInitializers = false; |
| 1171 var args = arguments(); | 1176 var args = arguments(); |
| 1172 _inInitializers = saved; | 1177 _inInitializers = saved; |
| 1173 if (args.length == 1) { | 1178 if (args.length == 1) { |
| 1174 return new ParenExpression(args[0].value, _makeSpan(start)); | 1179 return new ParenExpression(args[0].value, _makeSpan(start)); |
| 1175 } else { | 1180 } else { |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 modifiers.add(_next()); | 1426 modifiers.add(_next()); |
| 1422 break; | 1427 break; |
| 1423 default: | 1428 default: |
| 1424 return modifiers; | 1429 return modifiers; |
| 1425 } | 1430 } |
| 1426 } | 1431 } |
| 1427 | 1432 |
| 1428 return null; | 1433 return null; |
| 1429 } | 1434 } |
| 1430 | 1435 |
| 1431 typeParameter() { | 1436 ParameterType typeParameter() { |
| 1432 // non-recursive - so always starts from zero depth | 1437 // non-recursive - so always starts from zero depth |
| 1433 int start = _peekToken.start; | 1438 int start = _peekToken.start; |
| 1434 var name = identifier(); | 1439 var name = identifier(); |
| 1435 var myType = null; | 1440 var myType = null; |
| 1436 if (_maybeEat(TokenKind.EXTENDS)) { | 1441 if (_maybeEat(TokenKind.EXTENDS)) { |
| 1437 myType = type(1); | 1442 myType = type(1); |
| 1438 } | 1443 } |
| 1439 return new TypeParameter(name, myType, _makeSpan(start)); | 1444 |
| 1445 var tp = new TypeParameter(name, myType, _makeSpan(start)); |
| 1446 return new ParameterType(name.name, tp); |
| 1440 } | 1447 } |
| 1441 | 1448 |
| 1442 typeParameters() { | 1449 List<ParameterType> typeParameters() { |
| 1443 // always starts from zero depth | 1450 // always starts from zero depth |
| 1444 _eat(TokenKind.LT); | 1451 _eat(TokenKind.LT); |
| 1445 | 1452 |
| 1446 bool closed = false; | 1453 bool closed = false; |
| 1447 var ret = []; | 1454 var ret = []; |
| 1448 do { | 1455 do { |
| 1449 // inlining typeParameter to handle scope issues? | |
| 1450 var tp = typeParameter(); | 1456 var tp = typeParameter(); |
| 1451 ret.add(tp); | 1457 ret.add(tp); |
| 1452 if (tp.extendsType is GenericTypeReference && tp.extendsType.depth == 0) { | 1458 if (tp.typeParameter.extendsType is GenericTypeReference && |
| 1459 tp.typeParameter.extendsType.depth == 0) { |
| 1453 closed = true; | 1460 closed = true; |
| 1454 break; | 1461 break; |
| 1455 } | 1462 } |
| 1456 } while (_maybeEat(TokenKind.COMMA)); | 1463 } while (_maybeEat(TokenKind.COMMA)); |
| 1457 if (!closed) { | 1464 if (!closed) { |
| 1458 _eat(TokenKind.GT); | 1465 _eat(TokenKind.GT); |
| 1459 } | 1466 } |
| 1460 return ret; | 1467 return ret; |
| 1461 } | 1468 } |
| 1462 | 1469 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1555 | 1562 |
| 1556 var value = null; | 1563 var value = null; |
| 1557 if (_maybeEat(TokenKind.ASSIGN)) { | 1564 if (_maybeEat(TokenKind.ASSIGN)) { |
| 1558 if (!inOptionalBlock) { | 1565 if (!inOptionalBlock) { |
| 1559 _error('default values only allowed inside [optional] section'); | 1566 _error('default values only allowed inside [optional] section'); |
| 1560 } | 1567 } |
| 1561 value = expression(); | 1568 value = expression(); |
| 1562 } else if (_peekKind(TokenKind.LPAREN)) { | 1569 } else if (_peekKind(TokenKind.LPAREN)) { |
| 1563 var formals = formalParameterList(); | 1570 var formals = formalParameterList(); |
| 1564 var func = new FunctionDefinition(null, type, name, formals, | 1571 var func = new FunctionDefinition(null, type, name, formals, |
| 1565 null, null, _makeSpan(start)); | 1572 null, null, null, _makeSpan(start)); |
| 1566 type = new FunctionTypeReference(false, func, func.span); | 1573 type = new FunctionTypeReference(false, func, func.span); |
| 1567 } | 1574 } |
| 1568 if (inOptionalBlock && value == null) { | 1575 if (inOptionalBlock && value == null) { |
| 1569 value = new NullExpression(_makeSpan(start)); | 1576 value = new NullExpression(_makeSpan(start)); |
| 1570 } | 1577 } |
| 1571 | 1578 |
| 1572 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start)); | 1579 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start)); |
| 1573 } | 1580 } |
| 1574 | 1581 |
| 1575 formalParameterList() { | 1582 formalParameterList() { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 name = expr.name; | 1629 name = expr.name; |
| 1623 type = null; | 1630 type = null; |
| 1624 } else if (expr is DeclaredIdentifier) { | 1631 } else if (expr is DeclaredIdentifier) { |
| 1625 name = expr.name; | 1632 name = expr.name; |
| 1626 type = expr.type; | 1633 type = expr.type; |
| 1627 } else { | 1634 } else { |
| 1628 _error('bad function body', expr.span); | 1635 _error('bad function body', expr.span); |
| 1629 } | 1636 } |
| 1630 var span = new SourceSpan(expr.span.file, expr.span.start, body.span.end); | 1637 var span = new SourceSpan(expr.span.file, expr.span.start, body.span.end); |
| 1631 var func = | 1638 var func = |
| 1632 new FunctionDefinition(null, type, name, formals, null, body, span); | 1639 new FunctionDefinition(null, type, name, formals, null, null, body, span
); |
| 1633 return new LambdaExpression(func, func.span); | 1640 return new LambdaExpression(func, func.span); |
| 1634 } | 1641 } |
| 1635 | 1642 |
| 1636 /** Converts an expression to a [DeclaredIdentifier]. */ | 1643 /** Converts an expression to a [DeclaredIdentifier]. */ |
| 1637 _makeDeclaredIdentifier(e) { | 1644 _makeDeclaredIdentifier(e) { |
| 1638 if (e is VarExpression) { | 1645 if (e is VarExpression) { |
| 1639 return new DeclaredIdentifier(null, e.name, e.span); | 1646 return new DeclaredIdentifier(null, e.name, e.span); |
| 1640 } else if (e is DeclaredIdentifier) { | 1647 } else if (e is DeclaredIdentifier) { |
| 1641 return e; | 1648 return e; |
| 1642 } else { | 1649 } else { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 int _pos = 0; | 1688 int _pos = 0; |
| 1682 next() { | 1689 next() { |
| 1683 var token = tokens[_pos]; | 1690 var token = tokens[_pos]; |
| 1684 ++_pos; | 1691 ++_pos; |
| 1685 if (_pos == tokens.length) { | 1692 if (_pos == tokens.length) { |
| 1686 parser.tokenizer = previousTokenizer; | 1693 parser.tokenizer = previousTokenizer; |
| 1687 } | 1694 } |
| 1688 return token; | 1695 return token; |
| 1689 } | 1696 } |
| 1690 } | 1697 } |
| OLD | NEW |