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 |