| 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 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 // TODO(scottmg): If this is measurably expensive, it could be done only | 439 // TODO(scottmg): If this is measurably expensive, it could be done only |
| 440 // when necessary (when reformatting, or during tests). Comments are | 440 // when necessary (when reformatting, or during tests). Comments are |
| 441 // separate from the parse tree at this point, so downstream code can remain | 441 // separate from the parse tree at this point, so downstream code can remain |
| 442 // ignorant of them. | 442 // ignorant of them. |
| 443 AssignComments(file.get()); | 443 AssignComments(file.get()); |
| 444 | 444 |
| 445 return file.Pass(); | 445 return file.Pass(); |
| 446 } | 446 } |
| 447 | 447 |
| 448 scoped_ptr<ParseNode> Parser::ParseStatement() { | 448 scoped_ptr<ParseNode> Parser::ParseStatement() { |
| 449 if (LookAhead(Token::LEFT_BRACE)) { | 449 if (LookAhead(Token::IF)) { |
| 450 return ParseBlock(); | |
| 451 } else if (LookAhead(Token::IF)) { | |
| 452 return ParseCondition(); | 450 return ParseCondition(); |
| 453 } else if (LookAhead(Token::BLOCK_COMMENT)) { | 451 } else if (LookAhead(Token::BLOCK_COMMENT)) { |
| 454 return BlockComment(Consume()); | 452 return BlockComment(Consume()); |
| 455 } else { | 453 } else { |
| 456 // TODO(scottmg): Is this too strict? Just drop all the testing if we want | 454 // TODO(scottmg): Is this too strict? Just drop all the testing if we want |
| 457 // to allow "pointless" expressions and return ParseExpression() directly. | 455 // to allow "pointless" expressions and return ParseExpression() directly. |
| 458 scoped_ptr<ParseNode> stmt = ParseExpression(); | 456 scoped_ptr<ParseNode> stmt = ParseExpression(); |
| 459 if (stmt) { | 457 if (stmt) { |
| 460 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) | 458 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) |
| 461 return stmt.Pass(); | 459 return stmt.Pass(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 scoped_ptr<ParseNode> Parser::ParseCondition() { | 491 scoped_ptr<ParseNode> Parser::ParseCondition() { |
| 494 scoped_ptr<ConditionNode> condition(new ConditionNode); | 492 scoped_ptr<ConditionNode> condition(new ConditionNode); |
| 495 condition->set_if_token(Consume(Token::IF, "Expected 'if'")); | 493 condition->set_if_token(Consume(Token::IF, "Expected 'if'")); |
| 496 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); | 494 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); |
| 497 condition->set_condition(ParseExpression()); | 495 condition->set_condition(ParseExpression()); |
| 498 if (IsAssignment(condition->condition())) | 496 if (IsAssignment(condition->condition())) |
| 499 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); | 497 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); |
| 500 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); | 498 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); |
| 501 condition->set_if_true(ParseBlock().Pass()); | 499 condition->set_if_true(ParseBlock().Pass()); |
| 502 if (Match(Token::ELSE)) { | 500 if (Match(Token::ELSE)) { |
| 503 if (!LookAhead(Token::LEFT_BRACE) && !LookAhead(Token::IF)) { | 501 if (LookAhead(Token::LEFT_BRACE)) { |
| 502 condition->set_if_false(ParseBlock().Pass()); |
| 503 } else if (LookAhead(Token::IF)) { |
| 504 condition->set_if_false(ParseStatement().Pass()); |
| 505 } else { |
| 504 *err_ = Err(cur_token(), "Expected '{' or 'if' after 'else'."); | 506 *err_ = Err(cur_token(), "Expected '{' or 'if' after 'else'."); |
| 505 return scoped_ptr<ParseNode>(); | 507 return scoped_ptr<ParseNode>(); |
| 506 } | 508 } |
| 507 condition->set_if_false(ParseStatement().Pass()); | |
| 508 } | 509 } |
| 509 if (has_error()) | 510 if (has_error()) |
| 510 return scoped_ptr<ParseNode>(); | 511 return scoped_ptr<ParseNode>(); |
| 511 return condition.Pass(); | 512 return condition.Pass(); |
| 512 } | 513 } |
| 513 | 514 |
| 514 void Parser::TraverseOrder(const ParseNode* root, | 515 void Parser::TraverseOrder(const ParseNode* root, |
| 515 std::vector<const ParseNode*>* pre, | 516 std::vector<const ParseNode*>* pre, |
| 516 std::vector<const ParseNode*>* post) { | 517 std::vector<const ParseNode*>* post) { |
| 517 if (root) { | 518 if (root) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 break; | 616 break; |
| 616 } | 617 } |
| 617 } | 618 } |
| 618 | 619 |
| 619 // Suffix comments were assigned in reverse, so if there were multiple on | 620 // Suffix comments were assigned in reverse, so if there were multiple on |
| 620 // the same node, they need to be reversed. | 621 // the same node, they need to be reversed. |
| 621 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) | 622 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
| 622 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 623 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
| 623 } | 624 } |
| 624 } | 625 } |
| OLD | NEW |