Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Side by Side Diff: tools/gn/parser.cc

Issue 2290713002: gn: Reduce stack memory use while parsing. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/parser.h" 5 #include "tools/gn/parser.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 {nullptr, nullptr, -1}, // ELSE 274 {nullptr, nullptr, -1}, // ELSE
275 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER 275 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER
276 {nullptr, nullptr, -1}, // COMMA 276 {nullptr, nullptr, -1}, // COMMA
277 {nullptr, nullptr, -1}, // UNCLASSIFIED_COMMENT 277 {nullptr, nullptr, -1}, // UNCLASSIFIED_COMMENT
278 {nullptr, nullptr, -1}, // LINE_COMMENT 278 {nullptr, nullptr, -1}, // LINE_COMMENT
279 {nullptr, nullptr, -1}, // SUFFIX_COMMENT 279 {nullptr, nullptr, -1}, // SUFFIX_COMMENT
280 {&Parser::BlockComment, nullptr, -1}, // BLOCK_COMMENT 280 {&Parser::BlockComment, nullptr, -1}, // BLOCK_COMMENT
281 }; 281 };
282 282
283 Parser::Parser(const std::vector<Token>& tokens, Err* err) 283 Parser::Parser(const std::vector<Token>& tokens, Err* err)
284 : err_(err), cur_(0) { 284 : invalid_token_(Location(), Token::INVALID, base::StringPiece()),
285 err_(err),
286 cur_(0) {
285 for (const auto& token : tokens) { 287 for (const auto& token : tokens) {
286 switch (token.type()) { 288 switch (token.type()) {
287 case Token::LINE_COMMENT: 289 case Token::LINE_COMMENT:
288 line_comment_tokens_.push_back(token); 290 line_comment_tokens_.push_back(token);
289 break; 291 break;
290 case Token::SUFFIX_COMMENT: 292 case Token::SUFFIX_COMMENT:
291 suffix_comment_tokens_.push_back(token); 293 suffix_comment_tokens_.push_back(token);
292 break; 294 break;
293 default: 295 default:
294 // Note that BLOCK_COMMENTs (top-level standalone comments) are passed 296 // Note that BLOCK_COMMENTs (top-level standalone comments) are passed
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 return cur_token().type() == type; 372 return cur_token().type() == type;
371 } 373 }
372 374
373 bool Parser::Match(Token::Type type) { 375 bool Parser::Match(Token::Type type) {
374 if (!LookAhead(type)) 376 if (!LookAhead(type))
375 return false; 377 return false;
376 Consume(); 378 Consume();
377 return true; 379 return true;
378 } 380 }
379 381
380 Token Parser::Consume(Token::Type type, const char* error_message) { 382 const Token& Parser::Consume(Token::Type type, const char* error_message) {
381 Token::Type types[1] = { type }; 383 Token::Type types[1] = { type };
382 return Consume(types, 1, error_message); 384 return Consume(types, 1, error_message);
383 } 385 }
384 386
385 Token Parser::Consume(Token::Type* types, 387 const Token& Parser::Consume(Token::Type* types,
386 size_t num_types, 388 size_t num_types,
387 const char* error_message) { 389 const char* error_message) {
388 if (has_error()) { 390 if (has_error()) {
389 // Don't overwrite current error, but make progress through tokens so that 391 // Don't overwrite current error, but make progress through tokens so that
390 // a loop that's expecting a particular token will still terminate. 392 // a loop that's expecting a particular token will still terminate.
391 if (!at_end()) 393 if (!at_end())
392 cur_++; 394 cur_++;
393 return Token(Location(), Token::INVALID, base::StringPiece()); 395 return invalid_token_;
394 } 396 }
395 if (at_end()) { 397 if (at_end()) {
396 const char kEOFMsg[] = "I hit EOF instead."; 398 const char kEOFMsg[] = "I hit EOF instead.";
397 if (tokens_.empty()) 399 if (tokens_.empty())
398 *err_ = Err(Location(), error_message, kEOFMsg); 400 *err_ = Err(Location(), error_message, kEOFMsg);
399 else 401 else
400 *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg); 402 *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg);
401 return Token(Location(), Token::INVALID, base::StringPiece()); 403 return invalid_token_;
402 } 404 }
403 405
404 for (size_t i = 0; i < num_types; ++i) { 406 for (size_t i = 0; i < num_types; ++i) {
405 if (cur_token().type() == types[i]) 407 if (cur_token().type() == types[i])
406 return Consume(); 408 return Consume();
407 } 409 }
408 *err_ = Err(cur_token(), error_message); 410 *err_ = Err(cur_token(), error_message);
409 return Token(Location(), Token::INVALID, base::StringPiece()); 411 return invalid_token_;
410 } 412 }
411 413
412 Token Parser::Consume() { 414 const Token& Parser::Consume() {
413 return tokens_[cur_++]; 415 return tokens_[cur_++];
414 } 416 }
415 417
416 std::unique_ptr<ParseNode> Parser::ParseExpression() { 418 std::unique_ptr<ParseNode> Parser::ParseExpression() {
417 return ParseExpression(0); 419 return ParseExpression(0);
418 } 420 }
419 421
420 std::unique_ptr<ParseNode> Parser::ParseExpression(int precedence) { 422 std::unique_ptr<ParseNode> Parser::ParseExpression(int precedence) {
421 if (at_end()) 423 if (at_end())
422 return std::unique_ptr<ParseNode>(); 424 return std::unique_ptr<ParseNode>();
423 425
424 Token token = Consume(); 426 const Token& token = Consume();
425 PrefixFunc prefix = expressions_[token.type()].prefix; 427 PrefixFunc prefix = expressions_[token.type()].prefix;
426 428
427 if (prefix == nullptr) { 429 if (prefix == nullptr) {
428 *err_ = Err(token, 430 *err_ = Err(token,
429 std::string("Unexpected token '") + token.value().as_string() + 431 std::string("Unexpected token '") + token.value().as_string() +
430 std::string("'")); 432 std::string("'"));
431 return std::unique_ptr<ParseNode>(); 433 return std::unique_ptr<ParseNode>();
432 } 434 }
433 435
434 std::unique_ptr<ParseNode> left = (this->*prefix)(token); 436 std::unique_ptr<ParseNode> left = (this->*prefix)(token);
435 if (has_error()) 437 if (has_error())
436 return left; 438 return left;
437 439
438 while (!at_end() && !IsStatementBreak(cur_token().type()) && 440 while (!at_end() && !IsStatementBreak(cur_token().type()) &&
439 precedence <= expressions_[cur_token().type()].precedence) { 441 precedence <= expressions_[cur_token().type()].precedence) {
440 token = Consume(); 442 const Token& next_token = Consume();
441 InfixFunc infix = expressions_[token.type()].infix; 443 InfixFunc infix = expressions_[next_token.type()].infix;
442 if (infix == nullptr) { 444 if (infix == nullptr) {
443 *err_ = Err(token, 445 *err_ = Err(next_token, std::string("Unexpected token '") +
444 std::string("Unexpected token '") + 446 next_token.value().as_string() +
445 token.value().as_string() + std::string("'")); 447 std::string("'"));
446 return std::unique_ptr<ParseNode>(); 448 return std::unique_ptr<ParseNode>();
447 } 449 }
448 left = (this->*infix)(std::move(left), token); 450 left = (this->*infix)(std::move(left), next_token);
449 if (has_error()) 451 if (has_error())
450 return std::unique_ptr<ParseNode>(); 452 return std::unique_ptr<ParseNode>();
451 } 453 }
452 454
453 return left; 455 return left;
454 } 456 }
455 457
456 std::unique_ptr<ParseNode> Parser::Block(Token token) { 458 std::unique_ptr<ParseNode> Parser::Block(const Token& token) {
457 // This entrypoint into ParseBlock means it's part of an expression and we 459 // This entrypoint into ParseBlock means it's part of an expression and we
458 // always want the result. 460 // always want the result.
459 return ParseBlock(token, BlockNode::RETURNS_SCOPE); 461 return ParseBlock(token, BlockNode::RETURNS_SCOPE);
460 } 462 }
461 463
462 std::unique_ptr<ParseNode> Parser::Literal(Token token) { 464 std::unique_ptr<ParseNode> Parser::Literal(const Token& token) {
463 return base::WrapUnique(new LiteralNode(token)); 465 return base::WrapUnique(new LiteralNode(token));
464 } 466 }
465 467
466 std::unique_ptr<ParseNode> Parser::Name(Token token) { 468 std::unique_ptr<ParseNode> Parser::Name(const Token& token) {
467 return IdentifierOrCall(std::unique_ptr<ParseNode>(), token); 469 return IdentifierOrCall(std::unique_ptr<ParseNode>(), token);
468 } 470 }
469 471
470 std::unique_ptr<ParseNode> Parser::BlockComment(Token token) { 472 std::unique_ptr<ParseNode> Parser::BlockComment(const Token& token) {
471 std::unique_ptr<BlockCommentNode> comment(new BlockCommentNode()); 473 std::unique_ptr<BlockCommentNode> comment(new BlockCommentNode());
472 comment->set_comment(token); 474 comment->set_comment(token);
473 return std::move(comment); 475 return std::move(comment);
474 } 476 }
475 477
476 std::unique_ptr<ParseNode> Parser::Group(Token token) { 478 std::unique_ptr<ParseNode> Parser::Group(const Token& token) {
477 std::unique_ptr<ParseNode> expr = ParseExpression(); 479 std::unique_ptr<ParseNode> expr = ParseExpression();
478 if (has_error()) 480 if (has_error())
479 return std::unique_ptr<ParseNode>(); 481 return std::unique_ptr<ParseNode>();
480 Consume(Token::RIGHT_PAREN, "Expected ')'"); 482 Consume(Token::RIGHT_PAREN, "Expected ')'");
481 return expr; 483 return expr;
482 } 484 }
483 485
484 std::unique_ptr<ParseNode> Parser::Not(Token token) { 486 std::unique_ptr<ParseNode> Parser::Not(const Token& token) {
485 std::unique_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); 487 std::unique_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1);
486 if (has_error()) 488 if (has_error())
487 return std::unique_ptr<ParseNode>(); 489 return std::unique_ptr<ParseNode>();
488 if (!expr) { 490 if (!expr) {
489 if (!has_error()) 491 if (!has_error())
490 *err_ = Err(token, "Expected right-hand side for '!'."); 492 *err_ = Err(token, "Expected right-hand side for '!'.");
491 return std::unique_ptr<ParseNode>(); 493 return std::unique_ptr<ParseNode>();
492 } 494 }
493 std::unique_ptr<UnaryOpNode> unary_op(new UnaryOpNode); 495 std::unique_ptr<UnaryOpNode> unary_op(new UnaryOpNode);
494 unary_op->set_op(token); 496 unary_op->set_op(token);
495 unary_op->set_operand(std::move(expr)); 497 unary_op->set_operand(std::move(expr));
496 return std::move(unary_op); 498 return std::move(unary_op);
497 } 499 }
498 500
499 std::unique_ptr<ParseNode> Parser::List(Token node) { 501 std::unique_ptr<ParseNode> Parser::List(const Token& node) {
500 std::unique_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); 502 std::unique_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true));
501 if (!has_error() && !at_end()) 503 if (!has_error() && !at_end())
502 Consume(Token::RIGHT_BRACKET, "Expected ']'"); 504 Consume(Token::RIGHT_BRACKET, "Expected ']'");
503 return list; 505 return list;
504 } 506 }
505 507
506 std::unique_ptr<ParseNode> Parser::BinaryOperator( 508 std::unique_ptr<ParseNode> Parser::BinaryOperator(
507 std::unique_ptr<ParseNode> left, 509 std::unique_ptr<ParseNode> left,
508 Token token) { 510 const Token& token) {
509 std::unique_ptr<ParseNode> right = 511 std::unique_ptr<ParseNode> right =
510 ParseExpression(expressions_[token.type()].precedence + 1); 512 ParseExpression(expressions_[token.type()].precedence + 1);
511 if (!right) { 513 if (!right) {
512 if (!has_error()) { 514 if (!has_error()) {
513 *err_ = Err(token, "Expected right-hand side for '" + 515 *err_ = Err(token, "Expected right-hand side for '" +
514 token.value().as_string() + "'"); 516 token.value().as_string() + "'");
515 } 517 }
516 return std::unique_ptr<ParseNode>(); 518 return std::unique_ptr<ParseNode>();
517 } 519 }
518 std::unique_ptr<BinaryOpNode> binary_op(new BinaryOpNode); 520 std::unique_ptr<BinaryOpNode> binary_op(new BinaryOpNode);
519 binary_op->set_op(token); 521 binary_op->set_op(token);
520 binary_op->set_left(std::move(left)); 522 binary_op->set_left(std::move(left));
521 binary_op->set_right(std::move(right)); 523 binary_op->set_right(std::move(right));
522 return std::move(binary_op); 524 return std::move(binary_op);
523 } 525 }
524 526
525 std::unique_ptr<ParseNode> Parser::IdentifierOrCall( 527 std::unique_ptr<ParseNode> Parser::IdentifierOrCall(
526 std::unique_ptr<ParseNode> left, 528 std::unique_ptr<ParseNode> left,
527 Token token) { 529 const Token& token) {
528 std::unique_ptr<ListNode> list(new ListNode); 530 std::unique_ptr<ListNode> list(new ListNode);
529 list->set_begin_token(token); 531 list->set_begin_token(token);
530 list->set_end(base::WrapUnique(new EndNode(token))); 532 list->set_end(base::WrapUnique(new EndNode(token)));
531 std::unique_ptr<BlockNode> block; 533 std::unique_ptr<BlockNode> block;
532 bool has_arg = false; 534 bool has_arg = false;
533 if (LookAhead(Token::LEFT_PAREN)) { 535 if (LookAhead(Token::LEFT_PAREN)) {
534 Token start_token = Consume(); 536 const Token& start_token = Consume();
535 // Parsing a function call. 537 // Parsing a function call.
536 has_arg = true; 538 has_arg = true;
537 if (Match(Token::RIGHT_PAREN)) { 539 if (Match(Token::RIGHT_PAREN)) {
538 // Nothing, just an empty call. 540 // Nothing, just an empty call.
539 } else { 541 } else {
540 list = ParseList(start_token, Token::RIGHT_PAREN, false); 542 list = ParseList(start_token, Token::RIGHT_PAREN, false);
541 if (has_error()) 543 if (has_error())
542 return std::unique_ptr<ParseNode>(); 544 return std::unique_ptr<ParseNode>();
543 Consume(Token::RIGHT_PAREN, "Expected ')' after call"); 545 Consume(Token::RIGHT_PAREN, "Expected ')' after call");
544 } 546 }
(...skipping 11 matching lines...) Expand all
556 } 558 }
557 std::unique_ptr<FunctionCallNode> func_call(new FunctionCallNode); 559 std::unique_ptr<FunctionCallNode> func_call(new FunctionCallNode);
558 func_call->set_function(token); 560 func_call->set_function(token);
559 func_call->set_args(std::move(list)); 561 func_call->set_args(std::move(list));
560 if (block) 562 if (block)
561 func_call->set_block(std::move(block)); 563 func_call->set_block(std::move(block));
562 return std::move(func_call); 564 return std::move(func_call);
563 } 565 }
564 566
565 std::unique_ptr<ParseNode> Parser::Assignment(std::unique_ptr<ParseNode> left, 567 std::unique_ptr<ParseNode> Parser::Assignment(std::unique_ptr<ParseNode> left,
566 Token token) { 568 const Token& token) {
567 if (left->AsIdentifier() == nullptr && left->AsAccessor() == nullptr) { 569 if (left->AsIdentifier() == nullptr && left->AsAccessor() == nullptr) {
568 *err_ = Err(left.get(), 570 *err_ = Err(left.get(),
569 "The left-hand side of an assignment must be an identifier, " 571 "The left-hand side of an assignment must be an identifier, "
570 "scope access, or array access."); 572 "scope access, or array access.");
571 return std::unique_ptr<ParseNode>(); 573 return std::unique_ptr<ParseNode>();
572 } 574 }
573 std::unique_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); 575 std::unique_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT);
574 if (!value) { 576 if (!value) {
575 if (!has_error()) 577 if (!has_error())
576 *err_ = Err(token, "Expected right-hand side for assignment."); 578 *err_ = Err(token, "Expected right-hand side for assignment.");
577 return std::unique_ptr<ParseNode>(); 579 return std::unique_ptr<ParseNode>();
578 } 580 }
579 std::unique_ptr<BinaryOpNode> assign(new BinaryOpNode); 581 std::unique_ptr<BinaryOpNode> assign(new BinaryOpNode);
580 assign->set_op(token); 582 assign->set_op(token);
581 assign->set_left(std::move(left)); 583 assign->set_left(std::move(left));
582 assign->set_right(std::move(value)); 584 assign->set_right(std::move(value));
583 return std::move(assign); 585 return std::move(assign);
584 } 586 }
585 587
586 std::unique_ptr<ParseNode> Parser::Subscript(std::unique_ptr<ParseNode> left, 588 std::unique_ptr<ParseNode> Parser::Subscript(std::unique_ptr<ParseNode> left,
587 Token token) { 589 const Token& token) {
588 // TODO: Maybe support more complex expressions like a[0][0]. This would 590 // TODO: Maybe support more complex expressions like a[0][0]. This would
589 // require work on the evaluator too. 591 // require work on the evaluator too.
590 if (left->AsIdentifier() == nullptr) { 592 if (left->AsIdentifier() == nullptr) {
591 *err_ = Err(left.get(), "May only subscript identifiers.", 593 *err_ = Err(left.get(), "May only subscript identifiers.",
592 "The thing on the left hand side of the [] must be an identifier\n" 594 "The thing on the left hand side of the [] must be an identifier\n"
593 "and not an expression. If you need this, you'll have to assign the\n" 595 "and not an expression. If you need this, you'll have to assign the\n"
594 "value to a temporary before subscripting. Sorry."); 596 "value to a temporary before subscripting. Sorry.");
595 return std::unique_ptr<ParseNode>(); 597 return std::unique_ptr<ParseNode>();
596 } 598 }
597 std::unique_ptr<ParseNode> value = ParseExpression(); 599 std::unique_ptr<ParseNode> value = ParseExpression();
598 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); 600 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript.");
599 std::unique_ptr<AccessorNode> accessor(new AccessorNode); 601 std::unique_ptr<AccessorNode> accessor(new AccessorNode);
600 accessor->set_base(left->AsIdentifier()->value()); 602 accessor->set_base(left->AsIdentifier()->value());
601 accessor->set_index(std::move(value)); 603 accessor->set_index(std::move(value));
602 return std::move(accessor); 604 return std::move(accessor);
603 } 605 }
604 606
605 std::unique_ptr<ParseNode> Parser::DotOperator(std::unique_ptr<ParseNode> left, 607 std::unique_ptr<ParseNode> Parser::DotOperator(std::unique_ptr<ParseNode> left,
606 Token token) { 608 const Token& token) {
607 if (left->AsIdentifier() == nullptr) { 609 if (left->AsIdentifier() == nullptr) {
608 *err_ = Err(left.get(), "May only use \".\" for identifiers.", 610 *err_ = Err(left.get(), "May only use \".\" for identifiers.",
609 "The thing on the left hand side of the dot must be an identifier\n" 611 "The thing on the left hand side of the dot must be an identifier\n"
610 "and not an expression. If you need this, you'll have to assign the\n" 612 "and not an expression. If you need this, you'll have to assign the\n"
611 "value to a temporary first. Sorry."); 613 "value to a temporary first. Sorry.");
612 return std::unique_ptr<ParseNode>(); 614 return std::unique_ptr<ParseNode>();
613 } 615 }
614 616
615 std::unique_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); 617 std::unique_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT);
616 if (!right || !right->AsIdentifier()) { 618 if (!right || !right->AsIdentifier()) {
617 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", 619 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"",
618 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); 620 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()");
619 return std::unique_ptr<ParseNode>(); 621 return std::unique_ptr<ParseNode>();
620 } 622 }
621 623
622 std::unique_ptr<AccessorNode> accessor(new AccessorNode); 624 std::unique_ptr<AccessorNode> accessor(new AccessorNode);
623 accessor->set_base(left->AsIdentifier()->value()); 625 accessor->set_base(left->AsIdentifier()->value());
624 accessor->set_member(std::unique_ptr<IdentifierNode>( 626 accessor->set_member(std::unique_ptr<IdentifierNode>(
625 static_cast<IdentifierNode*>(right.release()))); 627 static_cast<IdentifierNode*>(right.release())));
626 return std::move(accessor); 628 return std::move(accessor);
627 } 629 }
628 630
629 // Does not Consume the start or end token. 631 // Does not Consume the start or end token.
630 std::unique_ptr<ListNode> Parser::ParseList(Token start_token, 632 std::unique_ptr<ListNode> Parser::ParseList(const Token& start_token,
631 Token::Type stop_before, 633 Token::Type stop_before,
632 bool allow_trailing_comma) { 634 bool allow_trailing_comma) {
633 std::unique_ptr<ListNode> list(new ListNode); 635 std::unique_ptr<ListNode> list(new ListNode);
634 list->set_begin_token(start_token); 636 list->set_begin_token(start_token);
635 bool just_got_comma = false; 637 bool just_got_comma = false;
636 bool first_time = true; 638 bool first_time = true;
637 while (!LookAhead(stop_before)) { 639 while (!LookAhead(stop_before)) {
638 if (!first_time) { 640 if (!first_time) {
639 if (!just_got_comma) { 641 if (!just_got_comma) {
640 // Require commas separate things in lists. 642 // Require commas separate things in lists.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 return BlockComment(Consume()); 704 return BlockComment(Consume());
703 } else { 705 } else {
704 // TODO(scottmg): Is this too strict? Just drop all the testing if we want 706 // TODO(scottmg): Is this too strict? Just drop all the testing if we want
705 // to allow "pointless" expressions and return ParseExpression() directly. 707 // to allow "pointless" expressions and return ParseExpression() directly.
706 std::unique_ptr<ParseNode> stmt = ParseExpression(); 708 std::unique_ptr<ParseNode> stmt = ParseExpression();
707 if (stmt) { 709 if (stmt) {
708 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) 710 if (stmt->AsFunctionCall() || IsAssignment(stmt.get()))
709 return stmt; 711 return stmt;
710 } 712 }
711 if (!has_error()) { 713 if (!has_error()) {
712 Token token = cur_or_last_token(); 714 const Token& token = cur_or_last_token();
713 *err_ = Err(token, "Expecting assignment or function call."); 715 *err_ = Err(token, "Expecting assignment or function call.");
714 } 716 }
715 return std::unique_ptr<ParseNode>(); 717 return std::unique_ptr<ParseNode>();
716 } 718 }
717 } 719 }
718 720
719 std::unique_ptr<BlockNode> Parser::ParseBlock( 721 std::unique_ptr<BlockNode> Parser::ParseBlock(
720 Token begin_brace, 722 const Token& begin_brace,
721 BlockNode::ResultMode result_mode) { 723 BlockNode::ResultMode result_mode) {
722 if (has_error()) 724 if (has_error())
723 return std::unique_ptr<BlockNode>(); 725 return std::unique_ptr<BlockNode>();
724 std::unique_ptr<BlockNode> block(new BlockNode(result_mode)); 726 std::unique_ptr<BlockNode> block(new BlockNode(result_mode));
725 block->set_begin_token(begin_brace); 727 block->set_begin_token(begin_brace);
726 728
727 for (;;) { 729 for (;;) {
728 if (LookAhead(Token::RIGHT_BRACE)) { 730 if (LookAhead(Token::RIGHT_BRACE)) {
729 block->set_end(base::WrapUnique(new EndNode(Consume()))); 731 block->set_end(base::WrapUnique(new EndNode(Consume())));
730 break; 732 break;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 break; 875 break;
874 } 876 }
875 } 877 }
876 878
877 // Suffix comments were assigned in reverse, so if there were multiple on 879 // Suffix comments were assigned in reverse, so if there were multiple on
878 // the same node, they need to be reversed. 880 // the same node, they need to be reversed.
879 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) 881 if ((*i)->comments() && !(*i)->comments()->suffix().empty())
880 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); 882 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix();
881 } 883 }
882 } 884 }
OLDNEW
« no previous file with comments | « tools/gn/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698