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 |