| OLD | NEW |
| 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "tools/gn/functions.h" | 8 #include "tools/gn/functions.h" |
| 9 #include "tools/gn/operators.h" | 9 #include "tools/gn/operators.h" |
| 10 #include "tools/gn/token.h" | 10 #include "tools/gn/token.h" |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 binary_op->set_op(token); | 278 binary_op->set_op(token); |
| 279 binary_op->set_left(left.Pass()); | 279 binary_op->set_left(left.Pass()); |
| 280 binary_op->set_right(right.Pass()); | 280 binary_op->set_right(right.Pass()); |
| 281 return binary_op.PassAs<ParseNode>(); | 281 return binary_op.PassAs<ParseNode>(); |
| 282 } | 282 } |
| 283 | 283 |
| 284 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, | 284 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, |
| 285 Token token) { | 285 Token token) { |
| 286 scoped_ptr<ListNode> list(new ListNode); | 286 scoped_ptr<ListNode> list(new ListNode); |
| 287 list->set_begin_token(token); | 287 list->set_begin_token(token); |
| 288 list->set_end_token(token); | 288 list->set_end(make_scoped_ptr(new EndNode(token))); |
| 289 scoped_ptr<BlockNode> block; | 289 scoped_ptr<BlockNode> block; |
| 290 bool has_arg = false; | 290 bool has_arg = false; |
| 291 if (LookAhead(Token::LEFT_PAREN)) { | 291 if (LookAhead(Token::LEFT_PAREN)) { |
| 292 Token start_token = Consume(); | 292 Token start_token = Consume(); |
| 293 // Parsing a function call. | 293 // Parsing a function call. |
| 294 has_arg = true; | 294 has_arg = true; |
| 295 if (Match(Token::RIGHT_PAREN)) { | 295 if (Match(Token::RIGHT_PAREN)) { |
| 296 // Nothing, just an empty call. | 296 // Nothing, just an empty call. |
| 297 } else { | 297 } else { |
| 298 list = ParseList(start_token, Token::RIGHT_PAREN, false); | 298 list = ParseList(start_token, Token::RIGHT_PAREN, false); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 // next item, so pretend we got one, if we're expecting one. | 411 // next item, so pretend we got one, if we're expecting one. |
| 412 just_got_comma = allow_trailing_comma; | 412 just_got_comma = allow_trailing_comma; |
| 413 } else { | 413 } else { |
| 414 just_got_comma = Match(Token::COMMA); | 414 just_got_comma = Match(Token::COMMA); |
| 415 } | 415 } |
| 416 } | 416 } |
| 417 if (just_got_comma && !allow_trailing_comma) { | 417 if (just_got_comma && !allow_trailing_comma) { |
| 418 *err_ = Err(cur_token(), "Trailing comma"); | 418 *err_ = Err(cur_token(), "Trailing comma"); |
| 419 return scoped_ptr<ListNode>(); | 419 return scoped_ptr<ListNode>(); |
| 420 } | 420 } |
| 421 list->set_end_token(cur_token()); | 421 list->set_end(make_scoped_ptr(new EndNode(cur_token()))); |
| 422 return list.Pass(); | 422 return list.Pass(); |
| 423 } | 423 } |
| 424 | 424 |
| 425 scoped_ptr<ParseNode> Parser::ParseFile() { | 425 scoped_ptr<ParseNode> Parser::ParseFile() { |
| 426 scoped_ptr<BlockNode> file(new BlockNode(false)); | 426 scoped_ptr<BlockNode> file(new BlockNode(false)); |
| 427 for (;;) { | 427 for (;;) { |
| 428 if (at_end()) | 428 if (at_end()) |
| 429 break; | 429 break; |
| 430 scoped_ptr<ParseNode> statement = ParseStatement(); | 430 scoped_ptr<ParseNode> statement = ParseStatement(); |
| 431 if (!statement) | 431 if (!statement) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 scoped_ptr<BlockNode> Parser::ParseBlock() { | 472 scoped_ptr<BlockNode> Parser::ParseBlock() { |
| 473 Token begin_token = | 473 Token begin_token = |
| 474 Consume(Token::LEFT_BRACE, "Expected '{' to start a block."); | 474 Consume(Token::LEFT_BRACE, "Expected '{' to start a block."); |
| 475 if (has_error()) | 475 if (has_error()) |
| 476 return scoped_ptr<BlockNode>(); | 476 return scoped_ptr<BlockNode>(); |
| 477 scoped_ptr<BlockNode> block(new BlockNode(true)); | 477 scoped_ptr<BlockNode> block(new BlockNode(true)); |
| 478 block->set_begin_token(begin_token); | 478 block->set_begin_token(begin_token); |
| 479 | 479 |
| 480 for (;;) { | 480 for (;;) { |
| 481 if (LookAhead(Token::RIGHT_BRACE)) { | 481 if (LookAhead(Token::RIGHT_BRACE)) { |
| 482 block->set_end_token(Consume()); | 482 block->set_end(make_scoped_ptr(new EndNode(Consume()))); |
| 483 break; | 483 break; |
| 484 } | 484 } |
| 485 | 485 |
| 486 scoped_ptr<ParseNode> statement = ParseStatement(); | 486 scoped_ptr<ParseNode> statement = ParseStatement(); |
| 487 if (!statement) | 487 if (!statement) |
| 488 return scoped_ptr<BlockNode>(); | 488 return scoped_ptr<BlockNode>(); |
| 489 block->append_statement(statement.Pass()); | 489 block->append_statement(statement.Pass()); |
| 490 } | 490 } |
| 491 return block.Pass(); | 491 return block.Pass(); |
| 492 } | 492 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 519 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { | 519 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { |
| 520 TraverseOrder(binop->left(), pre, post); | 520 TraverseOrder(binop->left(), pre, post); |
| 521 TraverseOrder(binop->right(), pre, post); | 521 TraverseOrder(binop->right(), pre, post); |
| 522 } else if (const BlockNode* block = root->AsBlock()) { | 522 } else if (const BlockNode* block = root->AsBlock()) { |
| 523 const std::vector<ParseNode*>& statements = block->statements(); | 523 const std::vector<ParseNode*>& statements = block->statements(); |
| 524 for (std::vector<ParseNode*>::const_iterator i(statements.begin()); | 524 for (std::vector<ParseNode*>::const_iterator i(statements.begin()); |
| 525 i != statements.end(); | 525 i != statements.end(); |
| 526 ++i) { | 526 ++i) { |
| 527 TraverseOrder(*i, pre, post); | 527 TraverseOrder(*i, pre, post); |
| 528 } | 528 } |
| 529 TraverseOrder(block->End(), pre, post); |
| 529 } else if (const ConditionNode* condition = root->AsConditionNode()) { | 530 } else if (const ConditionNode* condition = root->AsConditionNode()) { |
| 530 TraverseOrder(condition->condition(), pre, post); | 531 TraverseOrder(condition->condition(), pre, post); |
| 531 TraverseOrder(condition->if_true(), pre, post); | 532 TraverseOrder(condition->if_true(), pre, post); |
| 532 TraverseOrder(condition->if_false(), pre, post); | 533 TraverseOrder(condition->if_false(), pre, post); |
| 533 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { | 534 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { |
| 534 TraverseOrder(func_call->args(), pre, post); | 535 TraverseOrder(func_call->args(), pre, post); |
| 535 TraverseOrder(func_call->block(), pre, post); | 536 TraverseOrder(func_call->block(), pre, post); |
| 536 } else if (root->AsIdentifier()) { | 537 } else if (root->AsIdentifier()) { |
| 537 // Nothing. | 538 // Nothing. |
| 538 } else if (const ListNode* list = root->AsList()) { | 539 } else if (const ListNode* list = root->AsList()) { |
| 539 const std::vector<const ParseNode*>& contents = list->contents(); | 540 const std::vector<const ParseNode*>& contents = list->contents(); |
| 540 for (std::vector<const ParseNode*>::const_iterator i(contents.begin()); | 541 for (std::vector<const ParseNode*>::const_iterator i(contents.begin()); |
| 541 i != contents.end(); | 542 i != contents.end(); |
| 542 ++i) { | 543 ++i) { |
| 543 TraverseOrder(*i, pre, post); | 544 TraverseOrder(*i, pre, post); |
| 544 } | 545 } |
| 546 TraverseOrder(list->End(), pre, post); |
| 545 } else if (root->AsLiteral()) { | 547 } else if (root->AsLiteral()) { |
| 546 // Nothing. | 548 // Nothing. |
| 547 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { | 549 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { |
| 548 TraverseOrder(unaryop->operand(), pre, post); | 550 TraverseOrder(unaryop->operand(), pre, post); |
| 549 } else if (root->AsBlockComment()) { | 551 } else if (root->AsBlockComment()) { |
| 550 // Nothing. | 552 // Nothing. |
| 553 } else if (root->AsEnd()) { |
| 554 // Nothing. |
| 551 } else { | 555 } else { |
| 552 CHECK(false) << "Unhandled case in TraverseOrder."; | 556 CHECK(false) << "Unhandled case in TraverseOrder."; |
| 553 } | 557 } |
| 554 | 558 |
| 555 post->push_back(root); | 559 post->push_back(root); |
| 556 } | 560 } |
| 557 } | 561 } |
| 558 | 562 |
| 559 void Parser::AssignComments(ParseNode* file) { | 563 void Parser::AssignComments(ParseNode* file) { |
| 560 // Start by generating a pre- and post- order traversal of the tree so we | 564 // Start by generating a pre- and post- order traversal of the tree so we |
| (...skipping 24 matching lines...) Expand all Loading... |
| 585 ++cur_comment) | 589 ++cur_comment) |
| 586 file->comments_mutable()->append_after(line_comment_tokens_[cur_comment]); | 590 file->comments_mutable()->append_after(line_comment_tokens_[cur_comment]); |
| 587 | 591 |
| 588 // Assign suffix to syntax immediately before. | 592 // Assign suffix to syntax immediately before. |
| 589 cur_comment = static_cast<int>(suffix_comment_tokens_.size() - 1); | 593 cur_comment = static_cast<int>(suffix_comment_tokens_.size() - 1); |
| 590 for (std::vector<const ParseNode*>::const_reverse_iterator i = post.rbegin(); | 594 for (std::vector<const ParseNode*>::const_reverse_iterator i = post.rbegin(); |
| 591 i != post.rend(); | 595 i != post.rend(); |
| 592 ++i) { | 596 ++i) { |
| 593 // Don't assign suffix comments to the function call or list, but instead | 597 // Don't assign suffix comments to the function call or list, but instead |
| 594 // to the last thing inside. | 598 // to the last thing inside. |
| 595 if ((*i)->AsFunctionCall() || (*i)->AsList()) | 599 if ((*i)->AsFunctionCall() || (*i)->AsList() || (*i)->AsEnd()) |
| 596 continue; | 600 continue; |
| 597 | 601 |
| 598 const Location& start = (*i)->GetRange().begin(); | 602 const Location& start = (*i)->GetRange().begin(); |
| 599 const Location& end = (*i)->GetRange().end(); | 603 const Location& end = (*i)->GetRange().end(); |
| 600 | 604 |
| 601 // Don't assign suffix comments to something that starts on an earlier | 605 // Don't assign suffix comments to something that starts on an earlier |
| 602 // line, so that in: | 606 // line, so that in: |
| 603 // | 607 // |
| 604 // sources = [ "a", | 608 // sources = [ "a", |
| 605 // "b" ] # comment | 609 // "b" ] # comment |
| 606 // | 610 // |
| 607 // it's attached to "b", not sources = [ ... ]. | 611 // it's attached to "b", not sources = [ ... ]. |
| 608 if (start.line_number() != end.line_number()) | 612 if (start.line_number() != end.line_number()) |
| 609 continue; | 613 continue; |
| 610 | 614 |
| 611 while (cur_comment >= 0) { | 615 while (cur_comment >= 0) { |
| 612 if (end.byte() <= suffix_comment_tokens_[cur_comment].location().byte()) { | 616 if (end.byte() <= suffix_comment_tokens_[cur_comment].location().byte()) { |
| 613 const_cast<ParseNode*>(*i)->comments_mutable()->append_suffix( | 617 const_cast<ParseNode*>(*i)->comments_mutable()->append_suffix( |
| 614 suffix_comment_tokens_[cur_comment]); | 618 suffix_comment_tokens_[cur_comment]); |
| 615 --cur_comment; | 619 --cur_comment; |
| 616 } else { | 620 } else { |
| 617 break; | 621 break; |
| 618 } | 622 } |
| 619 } | 623 } |
| 620 | 624 |
| 621 // Suffix comments were assigned in reverse, so if there were multiple on | 625 // Suffix comments were assigned in reverse, so if there were multiple on |
| 622 // the same node, they need to be reversed. | 626 // the same node, they need to be reversed. |
| 623 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 627 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
| 628 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
| 624 } | 629 } |
| 625 } | 630 } |
| OLD | NEW |