| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 {nullptr, nullptr, -1}, // ELSE | 274 {nullptr, nullptr, -1}, // ELSE |
| 275 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER | 275 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER |
| 276 {nullptr, nullptr, -1}, // COMMA | 276 {nullptr, nullptr, -1}, // COMMA |
| 277 {nullptr, nullptr, -1}, // UNCLASSIFIED_COMMENT | 277 {nullptr, nullptr, -1}, // UNCLASSIFIED_COMMENT |
| 278 {nullptr, nullptr, -1}, // LINE_COMMENT | 278 {nullptr, nullptr, -1}, // LINE_COMMENT |
| 279 {nullptr, nullptr, -1}, // SUFFIX_COMMENT | 279 {nullptr, nullptr, -1}, // SUFFIX_COMMENT |
| 280 {&Parser::BlockComment, nullptr, -1}, // BLOCK_COMMENT | 280 {&Parser::BlockComment, nullptr, -1}, // BLOCK_COMMENT |
| 281 }; | 281 }; |
| 282 | 282 |
| 283 Parser::Parser(const std::vector<Token>& tokens, Err* err) | 283 Parser::Parser(const std::vector<Token>& tokens, Err* err) |
| 284 : err_(err), cur_(0) { | 284 : invalid_token_(Location(), Token::INVALID, base::StringPiece()), |
| 285 err_(err), |
| 286 cur_(0) { |
| 285 for (const auto& token : tokens) { | 287 for (const auto& token : tokens) { |
| 286 switch (token.type()) { | 288 switch (token.type()) { |
| 287 case Token::LINE_COMMENT: | 289 case Token::LINE_COMMENT: |
| 288 line_comment_tokens_.push_back(token); | 290 line_comment_tokens_.push_back(token); |
| 289 break; | 291 break; |
| 290 case Token::SUFFIX_COMMENT: | 292 case Token::SUFFIX_COMMENT: |
| 291 suffix_comment_tokens_.push_back(token); | 293 suffix_comment_tokens_.push_back(token); |
| 292 break; | 294 break; |
| 293 default: | 295 default: |
| 294 // Note that BLOCK_COMMENTs (top-level standalone comments) are passed | 296 // Note that BLOCK_COMMENTs (top-level standalone comments) are passed |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 return cur_token().type() == type; | 372 return cur_token().type() == type; |
| 371 } | 373 } |
| 372 | 374 |
| 373 bool Parser::Match(Token::Type type) { | 375 bool Parser::Match(Token::Type type) { |
| 374 if (!LookAhead(type)) | 376 if (!LookAhead(type)) |
| 375 return false; | 377 return false; |
| 376 Consume(); | 378 Consume(); |
| 377 return true; | 379 return true; |
| 378 } | 380 } |
| 379 | 381 |
| 380 Token Parser::Consume(Token::Type type, const char* error_message) { | 382 const Token& Parser::Consume(Token::Type type, const char* error_message) { |
| 381 Token::Type types[1] = { type }; | 383 Token::Type types[1] = { type }; |
| 382 return Consume(types, 1, error_message); | 384 return Consume(types, 1, error_message); |
| 383 } | 385 } |
| 384 | 386 |
| 385 Token Parser::Consume(Token::Type* types, | 387 const Token& Parser::Consume(Token::Type* types, |
| 386 size_t num_types, | 388 size_t num_types, |
| 387 const char* error_message) { | 389 const char* error_message) { |
| 388 if (has_error()) { | 390 if (has_error()) { |
| 389 // Don't overwrite current error, but make progress through tokens so that | 391 // Don't overwrite current error, but make progress through tokens so that |
| 390 // a loop that's expecting a particular token will still terminate. | 392 // a loop that's expecting a particular token will still terminate. |
| 391 if (!at_end()) | 393 if (!at_end()) |
| 392 cur_++; | 394 cur_++; |
| 393 return Token(Location(), Token::INVALID, base::StringPiece()); | 395 return invalid_token_; |
| 394 } | 396 } |
| 395 if (at_end()) { | 397 if (at_end()) { |
| 396 const char kEOFMsg[] = "I hit EOF instead."; | 398 const char kEOFMsg[] = "I hit EOF instead."; |
| 397 if (tokens_.empty()) | 399 if (tokens_.empty()) |
| 398 *err_ = Err(Location(), error_message, kEOFMsg); | 400 *err_ = Err(Location(), error_message, kEOFMsg); |
| 399 else | 401 else |
| 400 *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg); | 402 *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg); |
| 401 return Token(Location(), Token::INVALID, base::StringPiece()); | 403 return invalid_token_; |
| 402 } | 404 } |
| 403 | 405 |
| 404 for (size_t i = 0; i < num_types; ++i) { | 406 for (size_t i = 0; i < num_types; ++i) { |
| 405 if (cur_token().type() == types[i]) | 407 if (cur_token().type() == types[i]) |
| 406 return Consume(); | 408 return Consume(); |
| 407 } | 409 } |
| 408 *err_ = Err(cur_token(), error_message); | 410 *err_ = Err(cur_token(), error_message); |
| 409 return Token(Location(), Token::INVALID, base::StringPiece()); | 411 return invalid_token_; |
| 410 } | 412 } |
| 411 | 413 |
| 412 Token Parser::Consume() { | 414 const Token& Parser::Consume() { |
| 413 return tokens_[cur_++]; | 415 return tokens_[cur_++]; |
| 414 } | 416 } |
| 415 | 417 |
| 416 std::unique_ptr<ParseNode> Parser::ParseExpression() { | 418 std::unique_ptr<ParseNode> Parser::ParseExpression() { |
| 417 return ParseExpression(0); | 419 return ParseExpression(0); |
| 418 } | 420 } |
| 419 | 421 |
| 420 std::unique_ptr<ParseNode> Parser::ParseExpression(int precedence) { | 422 std::unique_ptr<ParseNode> Parser::ParseExpression(int precedence) { |
| 421 if (at_end()) | 423 if (at_end()) |
| 422 return std::unique_ptr<ParseNode>(); | 424 return std::unique_ptr<ParseNode>(); |
| 423 | 425 |
| 424 Token token = Consume(); | 426 const Token& token = Consume(); |
| 425 PrefixFunc prefix = expressions_[token.type()].prefix; | 427 PrefixFunc prefix = expressions_[token.type()].prefix; |
| 426 | 428 |
| 427 if (prefix == nullptr) { | 429 if (prefix == nullptr) { |
| 428 *err_ = Err(token, | 430 *err_ = Err(token, |
| 429 std::string("Unexpected token '") + token.value().as_string() + | 431 std::string("Unexpected token '") + token.value().as_string() + |
| 430 std::string("'")); | 432 std::string("'")); |
| 431 return std::unique_ptr<ParseNode>(); | 433 return std::unique_ptr<ParseNode>(); |
| 432 } | 434 } |
| 433 | 435 |
| 434 std::unique_ptr<ParseNode> left = (this->*prefix)(token); | 436 std::unique_ptr<ParseNode> left = (this->*prefix)(token); |
| 435 if (has_error()) | 437 if (has_error()) |
| 436 return left; | 438 return left; |
| 437 | 439 |
| 438 while (!at_end() && !IsStatementBreak(cur_token().type()) && | 440 while (!at_end() && !IsStatementBreak(cur_token().type()) && |
| 439 precedence <= expressions_[cur_token().type()].precedence) { | 441 precedence <= expressions_[cur_token().type()].precedence) { |
| 440 token = Consume(); | 442 const Token& next_token = Consume(); |
| 441 InfixFunc infix = expressions_[token.type()].infix; | 443 InfixFunc infix = expressions_[next_token.type()].infix; |
| 442 if (infix == nullptr) { | 444 if (infix == nullptr) { |
| 443 *err_ = Err(token, | 445 *err_ = Err(next_token, std::string("Unexpected token '") + |
| 444 std::string("Unexpected token '") + | 446 next_token.value().as_string() + |
| 445 token.value().as_string() + std::string("'")); | 447 std::string("'")); |
| 446 return std::unique_ptr<ParseNode>(); | 448 return std::unique_ptr<ParseNode>(); |
| 447 } | 449 } |
| 448 left = (this->*infix)(std::move(left), token); | 450 left = (this->*infix)(std::move(left), next_token); |
| 449 if (has_error()) | 451 if (has_error()) |
| 450 return std::unique_ptr<ParseNode>(); | 452 return std::unique_ptr<ParseNode>(); |
| 451 } | 453 } |
| 452 | 454 |
| 453 return left; | 455 return left; |
| 454 } | 456 } |
| 455 | 457 |
| 456 std::unique_ptr<ParseNode> Parser::Block(Token token) { | 458 std::unique_ptr<ParseNode> Parser::Block(const Token& token) { |
| 457 // This entrypoint into ParseBlock means it's part of an expression and we | 459 // This entrypoint into ParseBlock means it's part of an expression and we |
| 458 // always want the result. | 460 // always want the result. |
| 459 return ParseBlock(token, BlockNode::RETURNS_SCOPE); | 461 return ParseBlock(token, BlockNode::RETURNS_SCOPE); |
| 460 } | 462 } |
| 461 | 463 |
| 462 std::unique_ptr<ParseNode> Parser::Literal(Token token) { | 464 std::unique_ptr<ParseNode> Parser::Literal(const Token& token) { |
| 463 return base::WrapUnique(new LiteralNode(token)); | 465 return base::WrapUnique(new LiteralNode(token)); |
| 464 } | 466 } |
| 465 | 467 |
| 466 std::unique_ptr<ParseNode> Parser::Name(Token token) { | 468 std::unique_ptr<ParseNode> Parser::Name(const Token& token) { |
| 467 return IdentifierOrCall(std::unique_ptr<ParseNode>(), token); | 469 return IdentifierOrCall(std::unique_ptr<ParseNode>(), token); |
| 468 } | 470 } |
| 469 | 471 |
| 470 std::unique_ptr<ParseNode> Parser::BlockComment(Token token) { | 472 std::unique_ptr<ParseNode> Parser::BlockComment(const Token& token) { |
| 471 std::unique_ptr<BlockCommentNode> comment(new BlockCommentNode()); | 473 std::unique_ptr<BlockCommentNode> comment(new BlockCommentNode()); |
| 472 comment->set_comment(token); | 474 comment->set_comment(token); |
| 473 return std::move(comment); | 475 return std::move(comment); |
| 474 } | 476 } |
| 475 | 477 |
| 476 std::unique_ptr<ParseNode> Parser::Group(Token token) { | 478 std::unique_ptr<ParseNode> Parser::Group(const Token& token) { |
| 477 std::unique_ptr<ParseNode> expr = ParseExpression(); | 479 std::unique_ptr<ParseNode> expr = ParseExpression(); |
| 478 if (has_error()) | 480 if (has_error()) |
| 479 return std::unique_ptr<ParseNode>(); | 481 return std::unique_ptr<ParseNode>(); |
| 480 Consume(Token::RIGHT_PAREN, "Expected ')'"); | 482 Consume(Token::RIGHT_PAREN, "Expected ')'"); |
| 481 return expr; | 483 return expr; |
| 482 } | 484 } |
| 483 | 485 |
| 484 std::unique_ptr<ParseNode> Parser::Not(Token token) { | 486 std::unique_ptr<ParseNode> Parser::Not(const Token& token) { |
| 485 std::unique_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); | 487 std::unique_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); |
| 486 if (has_error()) | 488 if (has_error()) |
| 487 return std::unique_ptr<ParseNode>(); | 489 return std::unique_ptr<ParseNode>(); |
| 488 if (!expr) { | 490 if (!expr) { |
| 489 if (!has_error()) | 491 if (!has_error()) |
| 490 *err_ = Err(token, "Expected right-hand side for '!'."); | 492 *err_ = Err(token, "Expected right-hand side for '!'."); |
| 491 return std::unique_ptr<ParseNode>(); | 493 return std::unique_ptr<ParseNode>(); |
| 492 } | 494 } |
| 493 std::unique_ptr<UnaryOpNode> unary_op(new UnaryOpNode); | 495 std::unique_ptr<UnaryOpNode> unary_op(new UnaryOpNode); |
| 494 unary_op->set_op(token); | 496 unary_op->set_op(token); |
| 495 unary_op->set_operand(std::move(expr)); | 497 unary_op->set_operand(std::move(expr)); |
| 496 return std::move(unary_op); | 498 return std::move(unary_op); |
| 497 } | 499 } |
| 498 | 500 |
| 499 std::unique_ptr<ParseNode> Parser::List(Token node) { | 501 std::unique_ptr<ParseNode> Parser::List(const Token& node) { |
| 500 std::unique_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); | 502 std::unique_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); |
| 501 if (!has_error() && !at_end()) | 503 if (!has_error() && !at_end()) |
| 502 Consume(Token::RIGHT_BRACKET, "Expected ']'"); | 504 Consume(Token::RIGHT_BRACKET, "Expected ']'"); |
| 503 return list; | 505 return list; |
| 504 } | 506 } |
| 505 | 507 |
| 506 std::unique_ptr<ParseNode> Parser::BinaryOperator( | 508 std::unique_ptr<ParseNode> Parser::BinaryOperator( |
| 507 std::unique_ptr<ParseNode> left, | 509 std::unique_ptr<ParseNode> left, |
| 508 Token token) { | 510 const Token& token) { |
| 509 std::unique_ptr<ParseNode> right = | 511 std::unique_ptr<ParseNode> right = |
| 510 ParseExpression(expressions_[token.type()].precedence + 1); | 512 ParseExpression(expressions_[token.type()].precedence + 1); |
| 511 if (!right) { | 513 if (!right) { |
| 512 if (!has_error()) { | 514 if (!has_error()) { |
| 513 *err_ = Err(token, "Expected right-hand side for '" + | 515 *err_ = Err(token, "Expected right-hand side for '" + |
| 514 token.value().as_string() + "'"); | 516 token.value().as_string() + "'"); |
| 515 } | 517 } |
| 516 return std::unique_ptr<ParseNode>(); | 518 return std::unique_ptr<ParseNode>(); |
| 517 } | 519 } |
| 518 std::unique_ptr<BinaryOpNode> binary_op(new BinaryOpNode); | 520 std::unique_ptr<BinaryOpNode> binary_op(new BinaryOpNode); |
| 519 binary_op->set_op(token); | 521 binary_op->set_op(token); |
| 520 binary_op->set_left(std::move(left)); | 522 binary_op->set_left(std::move(left)); |
| 521 binary_op->set_right(std::move(right)); | 523 binary_op->set_right(std::move(right)); |
| 522 return std::move(binary_op); | 524 return std::move(binary_op); |
| 523 } | 525 } |
| 524 | 526 |
| 525 std::unique_ptr<ParseNode> Parser::IdentifierOrCall( | 527 std::unique_ptr<ParseNode> Parser::IdentifierOrCall( |
| 526 std::unique_ptr<ParseNode> left, | 528 std::unique_ptr<ParseNode> left, |
| 527 Token token) { | 529 const Token& token) { |
| 528 std::unique_ptr<ListNode> list(new ListNode); | 530 std::unique_ptr<ListNode> list(new ListNode); |
| 529 list->set_begin_token(token); | 531 list->set_begin_token(token); |
| 530 list->set_end(base::WrapUnique(new EndNode(token))); | 532 list->set_end(base::WrapUnique(new EndNode(token))); |
| 531 std::unique_ptr<BlockNode> block; | 533 std::unique_ptr<BlockNode> block; |
| 532 bool has_arg = false; | 534 bool has_arg = false; |
| 533 if (LookAhead(Token::LEFT_PAREN)) { | 535 if (LookAhead(Token::LEFT_PAREN)) { |
| 534 Token start_token = Consume(); | 536 const Token& start_token = Consume(); |
| 535 // Parsing a function call. | 537 // Parsing a function call. |
| 536 has_arg = true; | 538 has_arg = true; |
| 537 if (Match(Token::RIGHT_PAREN)) { | 539 if (Match(Token::RIGHT_PAREN)) { |
| 538 // Nothing, just an empty call. | 540 // Nothing, just an empty call. |
| 539 } else { | 541 } else { |
| 540 list = ParseList(start_token, Token::RIGHT_PAREN, false); | 542 list = ParseList(start_token, Token::RIGHT_PAREN, false); |
| 541 if (has_error()) | 543 if (has_error()) |
| 542 return std::unique_ptr<ParseNode>(); | 544 return std::unique_ptr<ParseNode>(); |
| 543 Consume(Token::RIGHT_PAREN, "Expected ')' after call"); | 545 Consume(Token::RIGHT_PAREN, "Expected ')' after call"); |
| 544 } | 546 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 556 } | 558 } |
| 557 std::unique_ptr<FunctionCallNode> func_call(new FunctionCallNode); | 559 std::unique_ptr<FunctionCallNode> func_call(new FunctionCallNode); |
| 558 func_call->set_function(token); | 560 func_call->set_function(token); |
| 559 func_call->set_args(std::move(list)); | 561 func_call->set_args(std::move(list)); |
| 560 if (block) | 562 if (block) |
| 561 func_call->set_block(std::move(block)); | 563 func_call->set_block(std::move(block)); |
| 562 return std::move(func_call); | 564 return std::move(func_call); |
| 563 } | 565 } |
| 564 | 566 |
| 565 std::unique_ptr<ParseNode> Parser::Assignment(std::unique_ptr<ParseNode> left, | 567 std::unique_ptr<ParseNode> Parser::Assignment(std::unique_ptr<ParseNode> left, |
| 566 Token token) { | 568 const Token& token) { |
| 567 if (left->AsIdentifier() == nullptr && left->AsAccessor() == nullptr) { | 569 if (left->AsIdentifier() == nullptr && left->AsAccessor() == nullptr) { |
| 568 *err_ = Err(left.get(), | 570 *err_ = Err(left.get(), |
| 569 "The left-hand side of an assignment must be an identifier, " | 571 "The left-hand side of an assignment must be an identifier, " |
| 570 "scope access, or array access."); | 572 "scope access, or array access."); |
| 571 return std::unique_ptr<ParseNode>(); | 573 return std::unique_ptr<ParseNode>(); |
| 572 } | 574 } |
| 573 std::unique_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); | 575 std::unique_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); |
| 574 if (!value) { | 576 if (!value) { |
| 575 if (!has_error()) | 577 if (!has_error()) |
| 576 *err_ = Err(token, "Expected right-hand side for assignment."); | 578 *err_ = Err(token, "Expected right-hand side for assignment."); |
| 577 return std::unique_ptr<ParseNode>(); | 579 return std::unique_ptr<ParseNode>(); |
| 578 } | 580 } |
| 579 std::unique_ptr<BinaryOpNode> assign(new BinaryOpNode); | 581 std::unique_ptr<BinaryOpNode> assign(new BinaryOpNode); |
| 580 assign->set_op(token); | 582 assign->set_op(token); |
| 581 assign->set_left(std::move(left)); | 583 assign->set_left(std::move(left)); |
| 582 assign->set_right(std::move(value)); | 584 assign->set_right(std::move(value)); |
| 583 return std::move(assign); | 585 return std::move(assign); |
| 584 } | 586 } |
| 585 | 587 |
| 586 std::unique_ptr<ParseNode> Parser::Subscript(std::unique_ptr<ParseNode> left, | 588 std::unique_ptr<ParseNode> Parser::Subscript(std::unique_ptr<ParseNode> left, |
| 587 Token token) { | 589 const Token& token) { |
| 588 // TODO: Maybe support more complex expressions like a[0][0]. This would | 590 // TODO: Maybe support more complex expressions like a[0][0]. This would |
| 589 // require work on the evaluator too. | 591 // require work on the evaluator too. |
| 590 if (left->AsIdentifier() == nullptr) { | 592 if (left->AsIdentifier() == nullptr) { |
| 591 *err_ = Err(left.get(), "May only subscript identifiers.", | 593 *err_ = Err(left.get(), "May only subscript identifiers.", |
| 592 "The thing on the left hand side of the [] must be an identifier\n" | 594 "The thing on the left hand side of the [] must be an identifier\n" |
| 593 "and not an expression. If you need this, you'll have to assign the\n" | 595 "and not an expression. If you need this, you'll have to assign the\n" |
| 594 "value to a temporary before subscripting. Sorry."); | 596 "value to a temporary before subscripting. Sorry."); |
| 595 return std::unique_ptr<ParseNode>(); | 597 return std::unique_ptr<ParseNode>(); |
| 596 } | 598 } |
| 597 std::unique_ptr<ParseNode> value = ParseExpression(); | 599 std::unique_ptr<ParseNode> value = ParseExpression(); |
| 598 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); | 600 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); |
| 599 std::unique_ptr<AccessorNode> accessor(new AccessorNode); | 601 std::unique_ptr<AccessorNode> accessor(new AccessorNode); |
| 600 accessor->set_base(left->AsIdentifier()->value()); | 602 accessor->set_base(left->AsIdentifier()->value()); |
| 601 accessor->set_index(std::move(value)); | 603 accessor->set_index(std::move(value)); |
| 602 return std::move(accessor); | 604 return std::move(accessor); |
| 603 } | 605 } |
| 604 | 606 |
| 605 std::unique_ptr<ParseNode> Parser::DotOperator(std::unique_ptr<ParseNode> left, | 607 std::unique_ptr<ParseNode> Parser::DotOperator(std::unique_ptr<ParseNode> left, |
| 606 Token token) { | 608 const Token& token) { |
| 607 if (left->AsIdentifier() == nullptr) { | 609 if (left->AsIdentifier() == nullptr) { |
| 608 *err_ = Err(left.get(), "May only use \".\" for identifiers.", | 610 *err_ = Err(left.get(), "May only use \".\" for identifiers.", |
| 609 "The thing on the left hand side of the dot must be an identifier\n" | 611 "The thing on the left hand side of the dot must be an identifier\n" |
| 610 "and not an expression. If you need this, you'll have to assign the\n" | 612 "and not an expression. If you need this, you'll have to assign the\n" |
| 611 "value to a temporary first. Sorry."); | 613 "value to a temporary first. Sorry."); |
| 612 return std::unique_ptr<ParseNode>(); | 614 return std::unique_ptr<ParseNode>(); |
| 613 } | 615 } |
| 614 | 616 |
| 615 std::unique_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); | 617 std::unique_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); |
| 616 if (!right || !right->AsIdentifier()) { | 618 if (!right || !right->AsIdentifier()) { |
| 617 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", | 619 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", |
| 618 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); | 620 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); |
| 619 return std::unique_ptr<ParseNode>(); | 621 return std::unique_ptr<ParseNode>(); |
| 620 } | 622 } |
| 621 | 623 |
| 622 std::unique_ptr<AccessorNode> accessor(new AccessorNode); | 624 std::unique_ptr<AccessorNode> accessor(new AccessorNode); |
| 623 accessor->set_base(left->AsIdentifier()->value()); | 625 accessor->set_base(left->AsIdentifier()->value()); |
| 624 accessor->set_member(std::unique_ptr<IdentifierNode>( | 626 accessor->set_member(std::unique_ptr<IdentifierNode>( |
| 625 static_cast<IdentifierNode*>(right.release()))); | 627 static_cast<IdentifierNode*>(right.release()))); |
| 626 return std::move(accessor); | 628 return std::move(accessor); |
| 627 } | 629 } |
| 628 | 630 |
| 629 // Does not Consume the start or end token. | 631 // Does not Consume the start or end token. |
| 630 std::unique_ptr<ListNode> Parser::ParseList(Token start_token, | 632 std::unique_ptr<ListNode> Parser::ParseList(const Token& start_token, |
| 631 Token::Type stop_before, | 633 Token::Type stop_before, |
| 632 bool allow_trailing_comma) { | 634 bool allow_trailing_comma) { |
| 633 std::unique_ptr<ListNode> list(new ListNode); | 635 std::unique_ptr<ListNode> list(new ListNode); |
| 634 list->set_begin_token(start_token); | 636 list->set_begin_token(start_token); |
| 635 bool just_got_comma = false; | 637 bool just_got_comma = false; |
| 636 bool first_time = true; | 638 bool first_time = true; |
| 637 while (!LookAhead(stop_before)) { | 639 while (!LookAhead(stop_before)) { |
| 638 if (!first_time) { | 640 if (!first_time) { |
| 639 if (!just_got_comma) { | 641 if (!just_got_comma) { |
| 640 // Require commas separate things in lists. | 642 // Require commas separate things in lists. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 return BlockComment(Consume()); | 704 return BlockComment(Consume()); |
| 703 } else { | 705 } else { |
| 704 // TODO(scottmg): Is this too strict? Just drop all the testing if we want | 706 // TODO(scottmg): Is this too strict? Just drop all the testing if we want |
| 705 // to allow "pointless" expressions and return ParseExpression() directly. | 707 // to allow "pointless" expressions and return ParseExpression() directly. |
| 706 std::unique_ptr<ParseNode> stmt = ParseExpression(); | 708 std::unique_ptr<ParseNode> stmt = ParseExpression(); |
| 707 if (stmt) { | 709 if (stmt) { |
| 708 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) | 710 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) |
| 709 return stmt; | 711 return stmt; |
| 710 } | 712 } |
| 711 if (!has_error()) { | 713 if (!has_error()) { |
| 712 Token token = cur_or_last_token(); | 714 const Token& token = cur_or_last_token(); |
| 713 *err_ = Err(token, "Expecting assignment or function call."); | 715 *err_ = Err(token, "Expecting assignment or function call."); |
| 714 } | 716 } |
| 715 return std::unique_ptr<ParseNode>(); | 717 return std::unique_ptr<ParseNode>(); |
| 716 } | 718 } |
| 717 } | 719 } |
| 718 | 720 |
| 719 std::unique_ptr<BlockNode> Parser::ParseBlock( | 721 std::unique_ptr<BlockNode> Parser::ParseBlock( |
| 720 Token begin_brace, | 722 const Token& begin_brace, |
| 721 BlockNode::ResultMode result_mode) { | 723 BlockNode::ResultMode result_mode) { |
| 722 if (has_error()) | 724 if (has_error()) |
| 723 return std::unique_ptr<BlockNode>(); | 725 return std::unique_ptr<BlockNode>(); |
| 724 std::unique_ptr<BlockNode> block(new BlockNode(result_mode)); | 726 std::unique_ptr<BlockNode> block(new BlockNode(result_mode)); |
| 725 block->set_begin_token(begin_brace); | 727 block->set_begin_token(begin_brace); |
| 726 | 728 |
| 727 for (;;) { | 729 for (;;) { |
| 728 if (LookAhead(Token::RIGHT_BRACE)) { | 730 if (LookAhead(Token::RIGHT_BRACE)) { |
| 729 block->set_end(base::WrapUnique(new EndNode(Consume()))); | 731 block->set_end(base::WrapUnique(new EndNode(Consume()))); |
| 730 break; | 732 break; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 break; | 875 break; |
| 874 } | 876 } |
| 875 } | 877 } |
| 876 | 878 |
| 877 // Suffix comments were assigned in reverse, so if there were multiple on | 879 // Suffix comments were assigned in reverse, so if there were multiple on |
| 878 // the same node, they need to be reversed. | 880 // the same node, they need to be reversed. |
| 879 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) | 881 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
| 880 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 882 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
| 881 } | 883 } |
| 882 } | 884 } |
| OLD | NEW |