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> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "tools/gn/functions.h" | 10 #include "tools/gn/functions.h" |
9 #include "tools/gn/operators.h" | 11 #include "tools/gn/operators.h" |
10 #include "tools/gn/token.h" | 12 #include "tools/gn/token.h" |
11 | 13 |
12 const char kGrammar_Help[] = | 14 const char kGrammar_Help[] = |
13 "GN build language grammar\n" | 15 "GN build language grammar\n" |
14 "\n" | 16 "\n" |
15 "Tokens\n" | 17 "Tokens\n" |
16 "\n" | 18 "\n" |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 | 210 |
209 // static | 211 // static |
210 scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, | 212 scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, |
211 Err* err) { | 213 Err* err) { |
212 Parser p(tokens, err); | 214 Parser p(tokens, err); |
213 scoped_ptr<ParseNode> expr = p.ParseExpression(); | 215 scoped_ptr<ParseNode> expr = p.ParseExpression(); |
214 if (!p.at_end() && !err->has_error()) { | 216 if (!p.at_end() && !err->has_error()) { |
215 *err = Err(p.cur_token(), "Trailing garbage"); | 217 *err = Err(p.cur_token(), "Trailing garbage"); |
216 return nullptr; | 218 return nullptr; |
217 } | 219 } |
218 return expr.Pass(); | 220 return expr; |
219 } | 221 } |
220 | 222 |
221 // static | 223 // static |
222 scoped_ptr<ParseNode> Parser::ParseValue(const std::vector<Token>& tokens, | 224 scoped_ptr<ParseNode> Parser::ParseValue(const std::vector<Token>& tokens, |
223 Err* err) { | 225 Err* err) { |
224 for (const Token& token : tokens) { | 226 for (const Token& token : tokens) { |
225 switch (token.type()) { | 227 switch (token.type()) { |
226 case Token::INTEGER: | 228 case Token::INTEGER: |
227 case Token::STRING: | 229 case Token::STRING: |
228 case Token::TRUE_TOKEN: | 230 case Token::TRUE_TOKEN: |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 | 323 |
322 if (prefix == nullptr) { | 324 if (prefix == nullptr) { |
323 *err_ = Err(token, | 325 *err_ = Err(token, |
324 std::string("Unexpected token '") + token.value().as_string() + | 326 std::string("Unexpected token '") + token.value().as_string() + |
325 std::string("'")); | 327 std::string("'")); |
326 return scoped_ptr<ParseNode>(); | 328 return scoped_ptr<ParseNode>(); |
327 } | 329 } |
328 | 330 |
329 scoped_ptr<ParseNode> left = (this->*prefix)(token); | 331 scoped_ptr<ParseNode> left = (this->*prefix)(token); |
330 if (has_error()) | 332 if (has_error()) |
331 return left.Pass(); | 333 return left; |
332 | 334 |
333 while (!at_end() && !IsStatementBreak(cur_token().type()) && | 335 while (!at_end() && !IsStatementBreak(cur_token().type()) && |
334 precedence <= expressions_[cur_token().type()].precedence) { | 336 precedence <= expressions_[cur_token().type()].precedence) { |
335 token = Consume(); | 337 token = Consume(); |
336 InfixFunc infix = expressions_[token.type()].infix; | 338 InfixFunc infix = expressions_[token.type()].infix; |
337 if (infix == nullptr) { | 339 if (infix == nullptr) { |
338 *err_ = Err(token, | 340 *err_ = Err(token, |
339 std::string("Unexpected token '") + | 341 std::string("Unexpected token '") + |
340 token.value().as_string() + std::string("'")); | 342 token.value().as_string() + std::string("'")); |
341 return scoped_ptr<ParseNode>(); | 343 return scoped_ptr<ParseNode>(); |
342 } | 344 } |
343 left = (this->*infix)(left.Pass(), token); | 345 left = (this->*infix)(std::move(left), token); |
344 if (has_error()) | 346 if (has_error()) |
345 return scoped_ptr<ParseNode>(); | 347 return scoped_ptr<ParseNode>(); |
346 } | 348 } |
347 | 349 |
348 return left.Pass(); | 350 return left; |
349 } | 351 } |
350 | 352 |
351 scoped_ptr<ParseNode> Parser::Literal(Token token) { | 353 scoped_ptr<ParseNode> Parser::Literal(Token token) { |
352 return make_scoped_ptr(new LiteralNode(token)); | 354 return make_scoped_ptr(new LiteralNode(token)); |
353 } | 355 } |
354 | 356 |
355 scoped_ptr<ParseNode> Parser::Name(Token token) { | 357 scoped_ptr<ParseNode> Parser::Name(Token token) { |
356 return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass(); | 358 return IdentifierOrCall(scoped_ptr<ParseNode>(), token); |
357 } | 359 } |
358 | 360 |
359 scoped_ptr<ParseNode> Parser::BlockComment(Token token) { | 361 scoped_ptr<ParseNode> Parser::BlockComment(Token token) { |
360 scoped_ptr<BlockCommentNode> comment(new BlockCommentNode()); | 362 scoped_ptr<BlockCommentNode> comment(new BlockCommentNode()); |
361 comment->set_comment(token); | 363 comment->set_comment(token); |
362 return comment.Pass(); | 364 return std::move(comment); |
363 } | 365 } |
364 | 366 |
365 scoped_ptr<ParseNode> Parser::Group(Token token) { | 367 scoped_ptr<ParseNode> Parser::Group(Token token) { |
366 scoped_ptr<ParseNode> expr = ParseExpression(); | 368 scoped_ptr<ParseNode> expr = ParseExpression(); |
367 if (has_error()) | 369 if (has_error()) |
368 return scoped_ptr<ParseNode>(); | 370 return scoped_ptr<ParseNode>(); |
369 Consume(Token::RIGHT_PAREN, "Expected ')'"); | 371 Consume(Token::RIGHT_PAREN, "Expected ')'"); |
370 return expr.Pass(); | 372 return expr; |
371 } | 373 } |
372 | 374 |
373 scoped_ptr<ParseNode> Parser::Not(Token token) { | 375 scoped_ptr<ParseNode> Parser::Not(Token token) { |
374 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); | 376 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); |
375 if (has_error()) | 377 if (has_error()) |
376 return scoped_ptr<ParseNode>(); | 378 return scoped_ptr<ParseNode>(); |
377 if (!expr) { | 379 if (!expr) { |
378 if (!has_error()) | 380 if (!has_error()) |
379 *err_ = Err(token, "Expected right-hand side for '!'."); | 381 *err_ = Err(token, "Expected right-hand side for '!'."); |
380 return scoped_ptr<ParseNode>(); | 382 return scoped_ptr<ParseNode>(); |
381 } | 383 } |
382 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); | 384 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); |
383 unary_op->set_op(token); | 385 unary_op->set_op(token); |
384 unary_op->set_operand(expr.Pass()); | 386 unary_op->set_operand(std::move(expr)); |
385 return unary_op.Pass(); | 387 return std::move(unary_op); |
386 } | 388 } |
387 | 389 |
388 scoped_ptr<ParseNode> Parser::List(Token node) { | 390 scoped_ptr<ParseNode> Parser::List(Token node) { |
389 scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); | 391 scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); |
390 if (!has_error() && !at_end()) | 392 if (!has_error() && !at_end()) |
391 Consume(Token::RIGHT_BRACKET, "Expected ']'"); | 393 Consume(Token::RIGHT_BRACKET, "Expected ']'"); |
392 return list.Pass(); | 394 return list; |
393 } | 395 } |
394 | 396 |
395 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, | 397 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, |
396 Token token) { | 398 Token token) { |
397 scoped_ptr<ParseNode> right = | 399 scoped_ptr<ParseNode> right = |
398 ParseExpression(expressions_[token.type()].precedence + 1); | 400 ParseExpression(expressions_[token.type()].precedence + 1); |
399 if (!right) { | 401 if (!right) { |
400 if (!has_error()) { | 402 if (!has_error()) { |
401 *err_ = Err(token, "Expected right-hand side for '" + | 403 *err_ = Err(token, "Expected right-hand side for '" + |
402 token.value().as_string() + "'"); | 404 token.value().as_string() + "'"); |
403 } | 405 } |
404 return scoped_ptr<ParseNode>(); | 406 return scoped_ptr<ParseNode>(); |
405 } | 407 } |
406 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); | 408 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); |
407 binary_op->set_op(token); | 409 binary_op->set_op(token); |
408 binary_op->set_left(left.Pass()); | 410 binary_op->set_left(std::move(left)); |
409 binary_op->set_right(right.Pass()); | 411 binary_op->set_right(std::move(right)); |
410 return binary_op.Pass(); | 412 return std::move(binary_op); |
411 } | 413 } |
412 | 414 |
413 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, | 415 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, |
414 Token token) { | 416 Token token) { |
415 scoped_ptr<ListNode> list(new ListNode); | 417 scoped_ptr<ListNode> list(new ListNode); |
416 list->set_begin_token(token); | 418 list->set_begin_token(token); |
417 list->set_end(make_scoped_ptr(new EndNode(token))); | 419 list->set_end(make_scoped_ptr(new EndNode(token))); |
418 scoped_ptr<BlockNode> block; | 420 scoped_ptr<BlockNode> block; |
419 bool has_arg = false; | 421 bool has_arg = false; |
420 if (LookAhead(Token::LEFT_PAREN)) { | 422 if (LookAhead(Token::LEFT_PAREN)) { |
(...skipping 11 matching lines...) Expand all Loading... |
432 // Optionally with a scope. | 434 // Optionally with a scope. |
433 if (LookAhead(Token::LEFT_BRACE)) { | 435 if (LookAhead(Token::LEFT_BRACE)) { |
434 block = ParseBlock(); | 436 block = ParseBlock(); |
435 if (has_error()) | 437 if (has_error()) |
436 return scoped_ptr<ParseNode>(); | 438 return scoped_ptr<ParseNode>(); |
437 } | 439 } |
438 } | 440 } |
439 | 441 |
440 if (!left && !has_arg) { | 442 if (!left && !has_arg) { |
441 // Not a function call, just a standalone identifier. | 443 // Not a function call, just a standalone identifier. |
442 return scoped_ptr<ParseNode>(new IdentifierNode(token)).Pass(); | 444 return scoped_ptr<ParseNode>(new IdentifierNode(token)); |
443 } | 445 } |
444 scoped_ptr<FunctionCallNode> func_call(new FunctionCallNode); | 446 scoped_ptr<FunctionCallNode> func_call(new FunctionCallNode); |
445 func_call->set_function(token); | 447 func_call->set_function(token); |
446 func_call->set_args(list.Pass()); | 448 func_call->set_args(std::move(list)); |
447 if (block) | 449 if (block) |
448 func_call->set_block(block.Pass()); | 450 func_call->set_block(std::move(block)); |
449 return func_call.Pass(); | 451 return std::move(func_call); |
450 } | 452 } |
451 | 453 |
452 scoped_ptr<ParseNode> Parser::Assignment(scoped_ptr<ParseNode> left, | 454 scoped_ptr<ParseNode> Parser::Assignment(scoped_ptr<ParseNode> left, |
453 Token token) { | 455 Token token) { |
454 if (left->AsIdentifier() == nullptr) { | 456 if (left->AsIdentifier() == nullptr) { |
455 *err_ = Err(left.get(), "Left-hand side of assignment must be identifier."); | 457 *err_ = Err(left.get(), "Left-hand side of assignment must be identifier."); |
456 return scoped_ptr<ParseNode>(); | 458 return scoped_ptr<ParseNode>(); |
457 } | 459 } |
458 scoped_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); | 460 scoped_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); |
459 if (!value) { | 461 if (!value) { |
460 if (!has_error()) | 462 if (!has_error()) |
461 *err_ = Err(token, "Expected right-hand side for assignment."); | 463 *err_ = Err(token, "Expected right-hand side for assignment."); |
462 return scoped_ptr<ParseNode>(); | 464 return scoped_ptr<ParseNode>(); |
463 } | 465 } |
464 scoped_ptr<BinaryOpNode> assign(new BinaryOpNode); | 466 scoped_ptr<BinaryOpNode> assign(new BinaryOpNode); |
465 assign->set_op(token); | 467 assign->set_op(token); |
466 assign->set_left(left.Pass()); | 468 assign->set_left(std::move(left)); |
467 assign->set_right(value.Pass()); | 469 assign->set_right(std::move(value)); |
468 return assign.Pass(); | 470 return std::move(assign); |
469 } | 471 } |
470 | 472 |
471 scoped_ptr<ParseNode> Parser::Subscript(scoped_ptr<ParseNode> left, | 473 scoped_ptr<ParseNode> Parser::Subscript(scoped_ptr<ParseNode> left, |
472 Token token) { | 474 Token token) { |
473 // TODO: Maybe support more complex expressions like a[0][0]. This would | 475 // TODO: Maybe support more complex expressions like a[0][0]. This would |
474 // require work on the evaluator too. | 476 // require work on the evaluator too. |
475 if (left->AsIdentifier() == nullptr) { | 477 if (left->AsIdentifier() == nullptr) { |
476 *err_ = Err(left.get(), "May only subscript identifiers.", | 478 *err_ = Err(left.get(), "May only subscript identifiers.", |
477 "The thing on the left hand side of the [] must be an identifier\n" | 479 "The thing on the left hand side of the [] must be an identifier\n" |
478 "and not an expression. If you need this, you'll have to assign the\n" | 480 "and not an expression. If you need this, you'll have to assign the\n" |
479 "value to a temporary before subscripting. Sorry."); | 481 "value to a temporary before subscripting. Sorry."); |
480 return scoped_ptr<ParseNode>(); | 482 return scoped_ptr<ParseNode>(); |
481 } | 483 } |
482 scoped_ptr<ParseNode> value = ParseExpression(); | 484 scoped_ptr<ParseNode> value = ParseExpression(); |
483 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); | 485 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); |
484 scoped_ptr<AccessorNode> accessor(new AccessorNode); | 486 scoped_ptr<AccessorNode> accessor(new AccessorNode); |
485 accessor->set_base(left->AsIdentifier()->value()); | 487 accessor->set_base(left->AsIdentifier()->value()); |
486 accessor->set_index(value.Pass()); | 488 accessor->set_index(std::move(value)); |
487 return accessor.Pass(); | 489 return std::move(accessor); |
488 } | 490 } |
489 | 491 |
490 scoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left, | 492 scoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left, |
491 Token token) { | 493 Token token) { |
492 if (left->AsIdentifier() == nullptr) { | 494 if (left->AsIdentifier() == nullptr) { |
493 *err_ = Err(left.get(), "May only use \".\" for identifiers.", | 495 *err_ = Err(left.get(), "May only use \".\" for identifiers.", |
494 "The thing on the left hand side of the dot must be an identifier\n" | 496 "The thing on the left hand side of the dot must be an identifier\n" |
495 "and not an expression. If you need this, you'll have to assign the\n" | 497 "and not an expression. If you need this, you'll have to assign the\n" |
496 "value to a temporary first. Sorry."); | 498 "value to a temporary first. Sorry."); |
497 return scoped_ptr<ParseNode>(); | 499 return scoped_ptr<ParseNode>(); |
498 } | 500 } |
499 | 501 |
500 scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); | 502 scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); |
501 if (!right || !right->AsIdentifier()) { | 503 if (!right || !right->AsIdentifier()) { |
502 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", | 504 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", |
503 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); | 505 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); |
504 return scoped_ptr<ParseNode>(); | 506 return scoped_ptr<ParseNode>(); |
505 } | 507 } |
506 | 508 |
507 scoped_ptr<AccessorNode> accessor(new AccessorNode); | 509 scoped_ptr<AccessorNode> accessor(new AccessorNode); |
508 accessor->set_base(left->AsIdentifier()->value()); | 510 accessor->set_base(left->AsIdentifier()->value()); |
509 accessor->set_member(scoped_ptr<IdentifierNode>( | 511 accessor->set_member(scoped_ptr<IdentifierNode>( |
510 static_cast<IdentifierNode*>(right.release()))); | 512 static_cast<IdentifierNode*>(right.release()))); |
511 return accessor.Pass(); | 513 return std::move(accessor); |
512 } | 514 } |
513 | 515 |
514 // Does not Consume the start or end token. | 516 // Does not Consume the start or end token. |
515 scoped_ptr<ListNode> Parser::ParseList(Token start_token, | 517 scoped_ptr<ListNode> Parser::ParseList(Token start_token, |
516 Token::Type stop_before, | 518 Token::Type stop_before, |
517 bool allow_trailing_comma) { | 519 bool allow_trailing_comma) { |
518 scoped_ptr<ListNode> list(new ListNode); | 520 scoped_ptr<ListNode> list(new ListNode); |
519 list->set_begin_token(start_token); | 521 list->set_begin_token(start_token); |
520 bool just_got_comma = false; | 522 bool just_got_comma = false; |
521 bool first_time = true; | 523 bool first_time = true; |
(...skipping 24 matching lines...) Expand all Loading... |
546 just_got_comma = allow_trailing_comma; | 548 just_got_comma = allow_trailing_comma; |
547 } else { | 549 } else { |
548 just_got_comma = Match(Token::COMMA); | 550 just_got_comma = Match(Token::COMMA); |
549 } | 551 } |
550 } | 552 } |
551 if (just_got_comma && !allow_trailing_comma) { | 553 if (just_got_comma && !allow_trailing_comma) { |
552 *err_ = Err(cur_token(), "Trailing comma"); | 554 *err_ = Err(cur_token(), "Trailing comma"); |
553 return scoped_ptr<ListNode>(); | 555 return scoped_ptr<ListNode>(); |
554 } | 556 } |
555 list->set_end(make_scoped_ptr(new EndNode(cur_token()))); | 557 list->set_end(make_scoped_ptr(new EndNode(cur_token()))); |
556 return list.Pass(); | 558 return list; |
557 } | 559 } |
558 | 560 |
559 scoped_ptr<ParseNode> Parser::ParseFile() { | 561 scoped_ptr<ParseNode> Parser::ParseFile() { |
560 scoped_ptr<BlockNode> file(new BlockNode); | 562 scoped_ptr<BlockNode> file(new BlockNode); |
561 for (;;) { | 563 for (;;) { |
562 if (at_end()) | 564 if (at_end()) |
563 break; | 565 break; |
564 scoped_ptr<ParseNode> statement = ParseStatement(); | 566 scoped_ptr<ParseNode> statement = ParseStatement(); |
565 if (!statement) | 567 if (!statement) |
566 break; | 568 break; |
567 file->append_statement(statement.Pass()); | 569 file->append_statement(std::move(statement)); |
568 } | 570 } |
569 if (!at_end() && !has_error()) | 571 if (!at_end() && !has_error()) |
570 *err_ = Err(cur_token(), "Unexpected here, should be newline."); | 572 *err_ = Err(cur_token(), "Unexpected here, should be newline."); |
571 if (has_error()) | 573 if (has_error()) |
572 return scoped_ptr<ParseNode>(); | 574 return scoped_ptr<ParseNode>(); |
573 | 575 |
574 // TODO(scottmg): If this is measurably expensive, it could be done only | 576 // TODO(scottmg): If this is measurably expensive, it could be done only |
575 // when necessary (when reformatting, or during tests). Comments are | 577 // when necessary (when reformatting, or during tests). Comments are |
576 // separate from the parse tree at this point, so downstream code can remain | 578 // separate from the parse tree at this point, so downstream code can remain |
577 // ignorant of them. | 579 // ignorant of them. |
578 AssignComments(file.get()); | 580 AssignComments(file.get()); |
579 | 581 |
580 return file.Pass(); | 582 return std::move(file); |
581 } | 583 } |
582 | 584 |
583 scoped_ptr<ParseNode> Parser::ParseStatement() { | 585 scoped_ptr<ParseNode> Parser::ParseStatement() { |
584 if (LookAhead(Token::IF)) { | 586 if (LookAhead(Token::IF)) { |
585 return ParseCondition(); | 587 return ParseCondition(); |
586 } else if (LookAhead(Token::BLOCK_COMMENT)) { | 588 } else if (LookAhead(Token::BLOCK_COMMENT)) { |
587 return BlockComment(Consume()); | 589 return BlockComment(Consume()); |
588 } else { | 590 } else { |
589 // TODO(scottmg): Is this too strict? Just drop all the testing if we want | 591 // TODO(scottmg): Is this too strict? Just drop all the testing if we want |
590 // to allow "pointless" expressions and return ParseExpression() directly. | 592 // to allow "pointless" expressions and return ParseExpression() directly. |
591 scoped_ptr<ParseNode> stmt = ParseExpression(); | 593 scoped_ptr<ParseNode> stmt = ParseExpression(); |
592 if (stmt) { | 594 if (stmt) { |
593 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) | 595 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) |
594 return stmt.Pass(); | 596 return stmt; |
595 } | 597 } |
596 if (!has_error()) { | 598 if (!has_error()) { |
597 Token token = at_end() ? tokens_[tokens_.size() - 1] : cur_token(); | 599 Token token = at_end() ? tokens_[tokens_.size() - 1] : cur_token(); |
598 *err_ = Err(token, "Expecting assignment or function call."); | 600 *err_ = Err(token, "Expecting assignment or function call."); |
599 } | 601 } |
600 return scoped_ptr<ParseNode>(); | 602 return scoped_ptr<ParseNode>(); |
601 } | 603 } |
602 } | 604 } |
603 | 605 |
604 scoped_ptr<BlockNode> Parser::ParseBlock() { | 606 scoped_ptr<BlockNode> Parser::ParseBlock() { |
605 Token begin_token = | 607 Token begin_token = |
606 Consume(Token::LEFT_BRACE, "Expected '{' to start a block."); | 608 Consume(Token::LEFT_BRACE, "Expected '{' to start a block."); |
607 if (has_error()) | 609 if (has_error()) |
608 return scoped_ptr<BlockNode>(); | 610 return scoped_ptr<BlockNode>(); |
609 scoped_ptr<BlockNode> block(new BlockNode); | 611 scoped_ptr<BlockNode> block(new BlockNode); |
610 block->set_begin_token(begin_token); | 612 block->set_begin_token(begin_token); |
611 | 613 |
612 for (;;) { | 614 for (;;) { |
613 if (LookAhead(Token::RIGHT_BRACE)) { | 615 if (LookAhead(Token::RIGHT_BRACE)) { |
614 block->set_end(make_scoped_ptr(new EndNode(Consume()))); | 616 block->set_end(make_scoped_ptr(new EndNode(Consume()))); |
615 break; | 617 break; |
616 } | 618 } |
617 | 619 |
618 scoped_ptr<ParseNode> statement = ParseStatement(); | 620 scoped_ptr<ParseNode> statement = ParseStatement(); |
619 if (!statement) | 621 if (!statement) |
620 return scoped_ptr<BlockNode>(); | 622 return scoped_ptr<BlockNode>(); |
621 block->append_statement(statement.Pass()); | 623 block->append_statement(std::move(statement)); |
622 } | 624 } |
623 return block.Pass(); | 625 return block; |
624 } | 626 } |
625 | 627 |
626 scoped_ptr<ParseNode> Parser::ParseCondition() { | 628 scoped_ptr<ParseNode> Parser::ParseCondition() { |
627 scoped_ptr<ConditionNode> condition(new ConditionNode); | 629 scoped_ptr<ConditionNode> condition(new ConditionNode); |
628 condition->set_if_token(Consume(Token::IF, "Expected 'if'")); | 630 condition->set_if_token(Consume(Token::IF, "Expected 'if'")); |
629 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); | 631 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); |
630 condition->set_condition(ParseExpression()); | 632 condition->set_condition(ParseExpression()); |
631 if (IsAssignment(condition->condition())) | 633 if (IsAssignment(condition->condition())) |
632 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); | 634 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); |
633 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); | 635 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); |
634 condition->set_if_true(ParseBlock().Pass()); | 636 condition->set_if_true(ParseBlock()); |
635 if (Match(Token::ELSE)) { | 637 if (Match(Token::ELSE)) { |
636 if (LookAhead(Token::LEFT_BRACE)) { | 638 if (LookAhead(Token::LEFT_BRACE)) { |
637 condition->set_if_false(ParseBlock().Pass()); | 639 condition->set_if_false(ParseBlock()); |
638 } else if (LookAhead(Token::IF)) { | 640 } else if (LookAhead(Token::IF)) { |
639 condition->set_if_false(ParseStatement().Pass()); | 641 condition->set_if_false(ParseStatement()); |
640 } else { | 642 } else { |
641 *err_ = Err(cur_token(), "Expected '{' or 'if' after 'else'."); | 643 *err_ = Err(cur_token(), "Expected '{' or 'if' after 'else'."); |
642 return scoped_ptr<ParseNode>(); | 644 return scoped_ptr<ParseNode>(); |
643 } | 645 } |
644 } | 646 } |
645 if (has_error()) | 647 if (has_error()) |
646 return scoped_ptr<ParseNode>(); | 648 return scoped_ptr<ParseNode>(); |
647 return condition.Pass(); | 649 return std::move(condition); |
648 } | 650 } |
649 | 651 |
650 void Parser::TraverseOrder(const ParseNode* root, | 652 void Parser::TraverseOrder(const ParseNode* root, |
651 std::vector<const ParseNode*>* pre, | 653 std::vector<const ParseNode*>* pre, |
652 std::vector<const ParseNode*>* post) { | 654 std::vector<const ParseNode*>* post) { |
653 if (root) { | 655 if (root) { |
654 pre->push_back(root); | 656 pre->push_back(root); |
655 | 657 |
656 if (const AccessorNode* accessor = root->AsAccessor()) { | 658 if (const AccessorNode* accessor = root->AsAccessor()) { |
657 TraverseOrder(accessor->index(), pre, post); | 659 TraverseOrder(accessor->index(), pre, post); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 break; | 753 break; |
752 } | 754 } |
753 } | 755 } |
754 | 756 |
755 // Suffix comments were assigned in reverse, so if there were multiple on | 757 // Suffix comments were assigned in reverse, so if there were multiple on |
756 // the same node, they need to be reversed. | 758 // the same node, they need to be reversed. |
757 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) | 759 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
758 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 760 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
759 } | 761 } |
760 } | 762 } |
OLD | NEW |