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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 static_cast<IdentifierNode*>(right.release()))); | 350 static_cast<IdentifierNode*>(right.release()))); |
351 return accessor.PassAs<ParseNode>(); | 351 return accessor.PassAs<ParseNode>(); |
352 } | 352 } |
353 | 353 |
354 // Does not Consume the start or end token. | 354 // Does not Consume the start or end token. |
355 scoped_ptr<ListNode> Parser::ParseList(Token::Type stop_before, | 355 scoped_ptr<ListNode> Parser::ParseList(Token::Type stop_before, |
356 bool allow_trailing_comma) { | 356 bool allow_trailing_comma) { |
357 scoped_ptr<ListNode> list(new ListNode); | 357 scoped_ptr<ListNode> list(new ListNode); |
358 list->set_begin_token(cur_token()); | 358 list->set_begin_token(cur_token()); |
359 bool just_got_comma = false; | 359 bool just_got_comma = false; |
| 360 bool first_time = true; |
360 while (!LookAhead(stop_before)) { | 361 while (!LookAhead(stop_before)) { |
361 just_got_comma = false; | 362 if (!first_time) { |
| 363 if (!just_got_comma) { |
| 364 // Require commas separate things in lists. |
| 365 *err_ = Err(cur_token(), "Expected comma between items."); |
| 366 return scoped_ptr<ListNode>(); |
| 367 } |
| 368 } |
| 369 first_time = false; |
| 370 |
362 // Why _OR? We're parsing things that are higher precedence than the , | 371 // Why _OR? We're parsing things that are higher precedence than the , |
363 // that separates the items of the list. , should appear lower than | 372 // that separates the items of the list. , should appear lower than |
364 // boolean expressions (the lowest of which is OR), but above assignments. | 373 // boolean expressions (the lowest of which is OR), but above assignments. |
365 list->append_item(ParseExpression(PRECEDENCE_OR)); | 374 list->append_item(ParseExpression(PRECEDENCE_OR)); |
366 if (has_error()) | 375 if (has_error()) |
367 return scoped_ptr<ListNode>(); | 376 return scoped_ptr<ListNode>(); |
368 if (at_end()) { | 377 if (at_end()) { |
369 *err_ = | 378 *err_ = |
370 Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list."); | 379 Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list."); |
371 return scoped_ptr<ListNode>(); | 380 return scoped_ptr<ListNode>(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 if (IsAssignment(condition->condition())) | 457 if (IsAssignment(condition->condition())) |
449 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); | 458 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); |
450 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); | 459 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); |
451 condition->set_if_true(ParseBlock().Pass()); | 460 condition->set_if_true(ParseBlock().Pass()); |
452 if (Match(Token::ELSE)) | 461 if (Match(Token::ELSE)) |
453 condition->set_if_false(ParseStatement().Pass()); | 462 condition->set_if_false(ParseStatement().Pass()); |
454 if (has_error()) | 463 if (has_error()) |
455 return scoped_ptr<ParseNode>(); | 464 return scoped_ptr<ParseNode>(); |
456 return condition.PassAs<ParseNode>(); | 465 return condition.PassAs<ParseNode>(); |
457 } | 466 } |
OLD | NEW |