Chromium Code Reviews| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 if (_maybeEat(TokenKind.IMPLEMENTS)) { | 268 if (_maybeEat(TokenKind.IMPLEMENTS)) { |
| 269 _implements = typeList(); | 269 _implements = typeList(); |
| 270 } | 270 } |
| 271 | 271 |
| 272 var _native = null; | 272 var _native = null; |
| 273 if (_maybeEat(TokenKind.NATIVE)) { | 273 if (_maybeEat(TokenKind.NATIVE)) { |
| 274 _native = maybeStringLiteral(); | 274 _native = maybeStringLiteral(); |
| 275 if (_native != null) _native = new NativeType(_native); | 275 if (_native != null) _native = new NativeType(_native); |
| 276 } | 276 } |
| 277 | 277 |
| 278 var _factory = null; | 278 bool oldFactory = _maybeEat(TokenKind.FACTORY); |
| 279 if (_maybeEat(TokenKind.FACTORY)) { | 279 var defaultType = null; |
| 280 // Note: this can't be type(), because for some strange reason these are | 280 if (oldFactory || _maybeEat(TokenKind.DEFAULT)) { |
| 281 // type parameters, not type arguments. | 281 // TODO(jmesserly): keep old factory support for now. Remove soon. |
| 282 _factory = nameTypeReference(); | 282 if (oldFactory) { |
| 283 world.warning('factory no longer supported, use "default" instead', | |
|
sra1
2011/12/15 02:38:17
I think Frog warnings need to be consistent with q
jimhug
2011/12/15 17:05:04
SGTM. I just checked and both Python and JS use s
Jennifer Messerly
2011/12/15 19:28:18
+1 on consistency. I'm trying to be consistent wit
| |
| 284 _previousToken.span); | |
| 285 } | |
| 286 | |
| 287 // Note: this can't be type() because it has type parameters not type | |
| 288 // arguments. | |
| 289 var baseType = nameTypeReference(); | |
| 290 var typeParams = null; | |
| 283 if (_peekKind(TokenKind.LT)) { | 291 if (_peekKind(TokenKind.LT)) { |
| 284 // TODO(jmesserly): not sure what to do with these. They aren't used for | 292 typeParams = typeParameters(); |
| 285 // anything as far as I can tell. | |
| 286 typeParameters(); | |
| 287 } | 293 } |
| 294 defaultType = new DefaultTypeReference(oldFactory, | |
| 295 baseType, typeParams, _makeSpan(baseType.span.start)); | |
| 288 } | 296 } |
| 289 | 297 |
| 290 var body = []; | 298 var body = []; |
| 291 if (_maybeEat(TokenKind.LBRACE)) { | 299 if (_maybeEat(TokenKind.LBRACE)) { |
| 292 while (!_maybeEat(TokenKind.RBRACE)) { | 300 while (!_maybeEat(TokenKind.RBRACE)) { |
| 293 body.add(declaration()); | 301 body.add(declaration()); |
| 294 if (_recover) { | 302 if (_recover) { |
| 295 if (!_recoverTo(TokenKind.RBRACE, TokenKind.SEMICOLON)) break; | 303 if (!_recoverTo(TokenKind.RBRACE, TokenKind.SEMICOLON)) break; |
| 296 _maybeEat(TokenKind.SEMICOLON); | 304 _maybeEat(TokenKind.SEMICOLON); |
| 297 } | 305 } |
| 298 } | 306 } |
| 299 } else { | 307 } else { |
| 300 _errorExpected('block starting with "{" or ";"'); | 308 _errorExpected('block starting with "{" or ";"'); |
| 301 } | 309 } |
| 302 return new TypeDefinition(kind == TokenKind.CLASS, name, typeParams, | 310 return new TypeDefinition(kind == TokenKind.CLASS, name, typeParams, |
| 303 _extends, _implements, _native, _factory, body, _makeSpan(start)); | 311 _extends, _implements, _native, defaultType, body, _makeSpan(start)); |
| 304 } | 312 } |
| 305 | 313 |
| 306 functionTypeAlias() { | 314 functionTypeAlias() { |
| 307 int start = _peekToken.start; | 315 int start = _peekToken.start; |
| 308 _eat(TokenKind.TYPEDEF); | 316 _eat(TokenKind.TYPEDEF); |
| 309 | 317 |
| 310 var di = declaredIdentifier(false); | 318 var di = declaredIdentifier(false); |
| 311 var typeParams = null; | 319 var typeParams = null; |
| 312 if (_peekKind(TokenKind.LT)) { | 320 if (_peekKind(TokenKind.LT)) { |
| 313 typeParams = typeParameters(); | 321 typeParams = typeParameters(); |
| 314 } | 322 } |
| 315 var formals = formalParameterList(); | 323 var formals = formalParameterList(); |
| 316 _eatSemicolon(); | 324 _eatSemicolon(); |
| 317 | 325 |
| 318 var func = new FunctionDefinition(null, di.type, di.name, formals, | 326 var func = new FunctionDefinition(null, di.type, di.name, formals, |
| 319 null, null, null, null, _makeSpan(start)); | 327 null, null, null, _makeSpan(start)); |
| 320 | 328 |
| 321 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); | 329 return new FunctionTypeDefinition(func, typeParams, _makeSpan(start)); |
| 322 } | 330 } |
| 323 | 331 |
| 324 initializers() { | 332 initializers() { |
| 325 _inhibitLambda = true; | 333 _inhibitLambda = true; |
| 326 var ret = []; | 334 var ret = []; |
| 327 do { | 335 do { |
| 328 ret.add(expression()); | 336 ret.add(expression()); |
| 329 } while (_maybeEat(TokenKind.COMMA)); | 337 } while (_maybeEat(TokenKind.COMMA)); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 348 } | 356 } |
| 349 } else if (!inExpression) { | 357 } else if (!inExpression) { |
| 350 if (_maybeEat(TokenKind.SEMICOLON)) { | 358 if (_maybeEat(TokenKind.SEMICOLON)) { |
| 351 return null; | 359 return null; |
| 352 } | 360 } |
| 353 } | 361 } |
| 354 | 362 |
| 355 _error('Expected function body (neither { nor => found)'); | 363 _error('Expected function body (neither { nor => found)'); |
| 356 } | 364 } |
| 357 | 365 |
| 358 finishField(start, modifiers, typeParams, type, name, value) { | 366 finishField(start, modifiers, type, name, value) { |
| 359 if (typeParams != null) { | |
| 360 world.internalError('trying to create a generic field', | |
| 361 _makeSpan(start)); | |
| 362 } | |
| 363 var names = [name]; | 367 var names = [name]; |
| 364 var values = [value]; | 368 var values = [value]; |
| 365 | 369 |
| 366 while (_maybeEat(TokenKind.COMMA)) { | 370 while (_maybeEat(TokenKind.COMMA)) { |
| 367 names.add(identifier()); | 371 names.add(identifier()); |
| 368 if (_maybeEat(TokenKind.ASSIGN)) { | 372 if (_maybeEat(TokenKind.ASSIGN)) { |
| 369 values.add(expression()); | 373 values.add(expression()); |
| 370 } else { | 374 } else { |
| 371 values.add(null); | 375 values.add(null); |
| 372 } | 376 } |
| 373 } | 377 } |
| 374 | 378 |
| 375 _eatSemicolon(); | 379 _eatSemicolon(); |
| 376 return new VariableDefinition(modifiers, type, names, values, | 380 return new VariableDefinition(modifiers, type, names, values, |
| 377 _makeSpan(start)); | 381 _makeSpan(start)); |
| 378 } | 382 } |
| 379 | 383 |
| 380 finishDefinition(int start, List<Token> modifiers, di, | 384 finishDefinition(int start, List<Token> modifiers, di) { |
| 381 List<ParameterType> typeParams) { | |
| 382 switch(_peek()) { | 385 switch(_peek()) { |
| 383 case TokenKind.LPAREN: | 386 case TokenKind.LPAREN: |
| 384 var formals = formalParameterList(); | 387 var formals = formalParameterList(); |
| 385 var inits = null, native = null; | 388 var inits = null, native = null; |
| 386 if (_maybeEat(TokenKind.COLON)) { | 389 if (_maybeEat(TokenKind.COLON)) { |
| 387 inits = initializers(); | 390 inits = initializers(); |
| 388 } | 391 } |
| 389 if (_maybeEat(TokenKind.NATIVE)) { | 392 if (_maybeEat(TokenKind.NATIVE)) { |
| 390 native = maybeStringLiteral(); | 393 native = maybeStringLiteral(); |
| 391 if (native == null) native = ''; | 394 if (native == null) native = ''; |
| 392 } | 395 } |
| 393 var body = functionBody(/*inExpression:*/false); | 396 var body = functionBody(/*inExpression:*/false); |
| 394 if (di.name == null) { | 397 if (di.name == null) { |
| 395 // TODO(jimhug): Must be named constructor - verify how? | 398 // TODO(jimhug): Must be named constructor - verify how? |
| 396 di.name = di.type.name; | 399 di.name = di.type.name; |
| 397 } | 400 } |
| 398 return new FunctionDefinition(modifiers, di.type, di.name, formals, | 401 return new FunctionDefinition(modifiers, di.type, di.name, formals, |
| 399 typeParams, inits, native, body, _makeSpan(start)); | 402 inits, native, body, _makeSpan(start)); |
| 400 | 403 |
| 401 case TokenKind.ASSIGN: | 404 case TokenKind.ASSIGN: |
| 402 _eat(TokenKind.ASSIGN); | 405 _eat(TokenKind.ASSIGN); |
| 403 var value = expression(); | 406 var value = expression(); |
| 404 return finishField(start, modifiers, typeParams, di.type, di.name, value ); | 407 return finishField(start, modifiers, di.type, di.name, value); |
| 405 | 408 |
| 406 case TokenKind.COMMA: | 409 case TokenKind.COMMA: |
| 407 case TokenKind.SEMICOLON: | 410 case TokenKind.SEMICOLON: |
| 408 return finishField(start, modifiers, typeParams, di.type, di.name, null) ; | 411 return finishField(start, modifiers, di.type, di.name, null); |
| 409 | 412 |
| 410 default: | 413 default: |
| 411 // TODO(jimhug): This error message sucks. | 414 // TODO(jimhug): This error message sucks. |
| 412 _errorExpected('declaration'); | 415 _errorExpected('declaration'); |
| 413 | 416 |
| 414 return null; | 417 return null; |
| 415 } | 418 } |
| 416 } | 419 } |
| 417 | 420 |
| 418 declaration([bool includeOperators=true]) { | 421 declaration([bool includeOperators=true]) { |
| 419 int start = _peekToken.start; | 422 int start = _peekToken.start; |
| 420 if (_peekKind(TokenKind.FACTORY)) { | 423 if (_peekKind(TokenKind.FACTORY)) { |
| 421 return factoryConstructorDeclaration(); | 424 return factoryConstructorDeclaration(); |
| 422 } | 425 } |
| 423 | 426 |
| 424 var modifiers = _readModifiers(); | 427 var modifiers = _readModifiers(); |
| 425 return finishDefinition(start, modifiers, | 428 return finishDefinition(start, modifiers, |
| 426 declaredIdentifier(includeOperators), null); | 429 declaredIdentifier(includeOperators)); |
| 427 } | 430 } |
| 428 | 431 |
| 432 // TODO(jmesserly): do we still need this method? | |
| 433 // I left it here for now to support old-style factories | |
|
jimhug
2011/12/15 17:05:04
I think we need this "forever" as we still have fa
Jennifer Messerly
2011/12/15 19:28:18
Ah, I might be misremembering the history of the c
| |
| 429 factoryConstructorDeclaration() { | 434 factoryConstructorDeclaration() { |
| 430 int start = _peekToken.start; | 435 int start = _peekToken.start; |
| 431 var factoryToken = _next(); | 436 var factoryToken = _next(); |
| 432 | 437 |
| 433 var names = [identifier()]; | 438 var names = [identifier()]; |
| 434 while (_maybeEat(TokenKind.DOT)) { | 439 while (_maybeEat(TokenKind.DOT)) { |
| 435 names.add(identifier()); | 440 names.add(identifier()); |
| 436 } | 441 } |
| 437 var typeParams = null; | |
| 438 if (_peekKind(TokenKind.LT)) { | 442 if (_peekKind(TokenKind.LT)) { |
| 439 typeParams = typeParameters(); | 443 var tp = typeParameters(); |
| 444 world.warning('type parameters on factories are no longer supported, ' | |
| 445 + 'place them on the class instead', _makeSpan(tp[0].span.start)); | |
| 440 } | 446 } |
| 441 | 447 |
| 442 var name = null; | 448 var name = null; |
| 443 var type = null; | 449 var type = null; |
| 444 if (_maybeEat(TokenKind.DOT)) { | 450 if (_maybeEat(TokenKind.DOT)) { |
| 445 name = identifier(); | 451 name = identifier(); |
| 446 } else if (typeParams == null) { | 452 } else { |
| 447 if (names.length > 1) { | 453 if (names.length > 1) { |
| 448 name = names.removeLast(); | 454 name = names.removeLast(); |
| 449 } else { | 455 } else { |
| 450 name = new Identifier('', names[0].span); | 456 name = new Identifier('', names[0].span); |
| 451 } | 457 } |
| 452 } else { | |
| 453 name = new Identifier('', names[0].span); | |
| 454 } | 458 } |
| 455 | 459 |
| 456 if (names.length > 1) { | 460 if (names.length > 1) { |
| 457 // TODO(jimhug): This is nasty to support and currently unused. | 461 // TODO(jimhug): This is nasty to support and currently unused. |
| 458 _error('unsupported qualified name for factory', names[0].span); | 462 _error('unsupported qualified name for factory', names[0].span); |
| 459 } | 463 } |
| 460 type = new NameTypeReference(false, names[0], null, names[0].span); | 464 type = new NameTypeReference(false, names[0], null, names[0].span); |
| 461 var di = new DeclaredIdentifier(type, name, _makeSpan(start)); | 465 var di = new DeclaredIdentifier(type, name, _makeSpan(start)); |
| 462 return finishDefinition(start, [factoryToken], di, typeParams); | 466 return finishDefinition(start, [factoryToken], di); |
| 463 } | 467 } |
| 464 | 468 |
| 465 /////////////////////////////////////////////////////////////////// | 469 /////////////////////////////////////////////////////////////////// |
| 466 // Statement productions | 470 // Statement productions |
| 467 /////////////////////////////////////////////////////////////////// | 471 /////////////////////////////////////////////////////////////////// |
| 468 Statement statement() { | 472 Statement statement() { |
| 469 switch (_peek()) { | 473 switch (_peek()) { |
| 470 case TokenKind.BREAK: | 474 case TokenKind.BREAK: |
| 471 return breakStatement(); | 475 return breakStatement(); |
| 472 case TokenKind.CONTINUE: | 476 case TokenKind.CONTINUE: |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 522 if (expr.func.body is! BlockStatement) { | 526 if (expr.func.body is! BlockStatement) { |
| 523 _eatSemicolon(); | 527 _eatSemicolon(); |
| 524 expr.func.span = _makeSpan(start); | 528 expr.func.span = _makeSpan(start); |
| 525 } | 529 } |
| 526 return expr.func; | 530 return expr.func; |
| 527 } else if (expr is DeclaredIdentifier) { | 531 } else if (expr is DeclaredIdentifier) { |
| 528 var value = null; | 532 var value = null; |
| 529 if (_maybeEat(TokenKind.ASSIGN)) { | 533 if (_maybeEat(TokenKind.ASSIGN)) { |
| 530 value = expression(); | 534 value = expression(); |
| 531 } | 535 } |
| 532 return finishField(start, null, null, expr.type, expr.name, value); | 536 return finishField(start, null, expr.type, expr.name, value); |
| 533 } else if (_isBin(expr, TokenKind.ASSIGN) && | 537 } else if (_isBin(expr, TokenKind.ASSIGN) && |
| 534 (expr.x is DeclaredIdentifier)) { | 538 (expr.x is DeclaredIdentifier)) { |
| 535 DeclaredIdentifier di = expr.x; // TODO(jimhug): inference should handle! | 539 DeclaredIdentifier di = expr.x; // TODO(jimhug): inference should handle! |
| 536 return finishField(start, null, null, di.type, di.name, expr.y); | 540 return finishField(start, null, di.type, di.name, expr.y); |
| 537 } else if (_isBin(expr, TokenKind.LT) && _maybeEat(TokenKind.COMMA)) { | 541 } else if (_isBin(expr, TokenKind.LT) && _maybeEat(TokenKind.COMMA)) { |
| 538 var baseType = _makeType(expr.x); | 542 var baseType = _makeType(expr.x); |
| 539 var typeArgs = [_makeType(expr.y)]; | 543 var typeArgs = [_makeType(expr.y)]; |
| 540 var gt = _finishTypeArguments(baseType, 0, typeArgs); | 544 var gt = _finishTypeArguments(baseType, 0, typeArgs); |
| 541 var name = identifier(); | 545 var name = identifier(); |
| 542 var value = null; | 546 var value = null; |
| 543 if (_maybeEat(TokenKind.ASSIGN)) { | 547 if (_maybeEat(TokenKind.ASSIGN)) { |
| 544 value = expression(); | 548 value = expression(); |
| 545 } | 549 } |
| 546 return finishField(expr.span.start, null, null, gt, name, value); | 550 return finishField(expr.span.start, null, gt, name, value); |
| 547 } else { | 551 } else { |
| 548 _eatSemicolon(); | 552 _eatSemicolon(); |
| 549 return new ExpressionStatement(expr, _makeSpan(expr.span.start)); | 553 return new ExpressionStatement(expr, _makeSpan(expr.span.start)); |
| 550 } | 554 } |
| 551 } | 555 } |
| 552 | 556 |
| 553 Expression testCondition() { | 557 Expression testCondition() { |
| 554 _eatLeftParen(); | 558 _eatLeftParen(); |
| 555 var ret = expression(); | 559 var ret = expression(); |
| 556 _eat(TokenKind.RPAREN); | 560 _eat(TokenKind.RPAREN); |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1215 } | 1219 } |
| 1216 return null; | 1220 return null; |
| 1217 } | 1221 } |
| 1218 | 1222 |
| 1219 _parenOrLambda() { | 1223 _parenOrLambda() { |
| 1220 int start = _peekToken.start; | 1224 int start = _peekToken.start; |
| 1221 if (_atClosureParameters()) { | 1225 if (_atClosureParameters()) { |
| 1222 var formals = formalParameterList(); | 1226 var formals = formalParameterList(); |
| 1223 var body = functionBody(true); | 1227 var body = functionBody(true); |
| 1224 var func = new FunctionDefinition(null, null, null, formals, null, null, | 1228 var func = new FunctionDefinition(null, null, null, formals, null, null, |
| 1225 null, body, _makeSpan(start)); | 1229 body, _makeSpan(start)); |
| 1226 return new LambdaExpression(func, func.span); | 1230 return new LambdaExpression(func, func.span); |
| 1227 } else { | 1231 } else { |
| 1228 _eatLeftParen(); | 1232 _eatLeftParen(); |
| 1229 var saved = _inhibitLambda; | 1233 var saved = _inhibitLambda; |
| 1230 _inhibitLambda = false; | 1234 _inhibitLambda = false; |
| 1231 var expr = expression(); | 1235 var expr = expression(); |
| 1232 _eat(TokenKind.RPAREN); | 1236 _eat(TokenKind.RPAREN); |
| 1233 _inhibitLambda = saved; | 1237 _inhibitLambda = saved; |
| 1234 return new ParenExpression(expr, _makeSpan(start)); | 1238 return new ParenExpression(expr, _makeSpan(start)); |
| 1235 } | 1239 } |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1639 | 1643 |
| 1640 var value = null; | 1644 var value = null; |
| 1641 if (_maybeEat(TokenKind.ASSIGN)) { | 1645 if (_maybeEat(TokenKind.ASSIGN)) { |
| 1642 if (!inOptionalBlock) { | 1646 if (!inOptionalBlock) { |
| 1643 _error('default values only allowed inside [optional] section'); | 1647 _error('default values only allowed inside [optional] section'); |
| 1644 } | 1648 } |
| 1645 value = expression(); | 1649 value = expression(); |
| 1646 } else if (_peekKind(TokenKind.LPAREN)) { | 1650 } else if (_peekKind(TokenKind.LPAREN)) { |
| 1647 var formals = formalParameterList(); | 1651 var formals = formalParameterList(); |
| 1648 var func = new FunctionDefinition(null, type, name, formals, | 1652 var func = new FunctionDefinition(null, type, name, formals, |
| 1649 null, null, null, null, _makeSpan(start)); | 1653 null, null, null, _makeSpan(start)); |
| 1650 type = new FunctionTypeReference(false, func, func.span); | 1654 type = new FunctionTypeReference(false, func, func.span); |
| 1651 } | 1655 } |
| 1652 if (inOptionalBlock && value == null) { | 1656 if (inOptionalBlock && value == null) { |
| 1653 value = new NullExpression(_makeSpan(start)); | 1657 value = new NullExpression(_makeSpan(start)); |
| 1654 } | 1658 } |
| 1655 | 1659 |
| 1656 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start)); | 1660 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start)); |
| 1657 } | 1661 } |
| 1658 | 1662 |
| 1659 formalParameterList() { | 1663 formalParameterList() { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1706 name = expr.name; | 1710 name = expr.name; |
| 1707 type = null; | 1711 type = null; |
| 1708 } else if (expr is DeclaredIdentifier) { | 1712 } else if (expr is DeclaredIdentifier) { |
| 1709 name = expr.name; | 1713 name = expr.name; |
| 1710 type = expr.type; | 1714 type = expr.type; |
| 1711 } else { | 1715 } else { |
| 1712 _error('bad function body', expr.span); | 1716 _error('bad function body', expr.span); |
| 1713 } | 1717 } |
| 1714 var span = new SourceSpan(expr.span.file, expr.span.start, body.span.end); | 1718 var span = new SourceSpan(expr.span.file, expr.span.start, body.span.end); |
| 1715 var func = new FunctionDefinition(null, type, name, formals, null, null, | 1719 var func = new FunctionDefinition(null, type, name, formals, null, null, |
| 1716 null, body, span); | 1720 body, span); |
| 1717 return new LambdaExpression(func, func.span); | 1721 return new LambdaExpression(func, func.span); |
| 1718 } | 1722 } |
| 1719 | 1723 |
| 1720 /** Converts an expression to a [DeclaredIdentifier]. */ | 1724 /** Converts an expression to a [DeclaredIdentifier]. */ |
| 1721 _makeDeclaredIdentifier(e) { | 1725 _makeDeclaredIdentifier(e) { |
| 1722 if (e is VarExpression) { | 1726 if (e is VarExpression) { |
| 1723 return new DeclaredIdentifier(null, e.name, e.span); | 1727 return new DeclaredIdentifier(null, e.name, e.span); |
| 1724 } else if (e is DeclaredIdentifier) { | 1728 } else if (e is DeclaredIdentifier) { |
| 1725 return e; | 1729 return e; |
| 1726 } else { | 1730 } else { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1765 int _pos = 0; | 1769 int _pos = 0; |
| 1766 next() { | 1770 next() { |
| 1767 var token = tokens[_pos]; | 1771 var token = tokens[_pos]; |
| 1768 ++_pos; | 1772 ++_pos; |
| 1769 if (_pos == tokens.length) { | 1773 if (_pos == tokens.length) { |
| 1770 parser.tokenizer = previousTokenizer; | 1774 parser.tokenizer = previousTokenizer; |
| 1771 } | 1775 } |
| 1772 return token; | 1776 return token; |
| 1773 } | 1777 } |
| 1774 } | 1778 } |
| OLD | NEW |