| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 } | 99 } |
| 100 } | 100 } |
| 101 | 101 |
| 102 Parser::~Parser() { | 102 Parser::~Parser() { |
| 103 } | 103 } |
| 104 | 104 |
| 105 // static | 105 // static |
| 106 scoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens, | 106 scoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens, |
| 107 Err* err) { | 107 Err* err) { |
| 108 Parser p(tokens, err); | 108 Parser p(tokens, err); |
| 109 return p.ParseFile().PassAs<ParseNode>(); | 109 return p.ParseFile(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 // static | 112 // static |
| 113 scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, | 113 scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, |
| 114 Err* err) { | 114 Err* err) { |
| 115 Parser p(tokens, err); | 115 Parser p(tokens, err); |
| 116 return p.ParseExpression().Pass(); | 116 return p.ParseExpression().Pass(); |
| 117 } | 117 } |
| 118 | 118 |
| 119 bool Parser::IsAssignment(const ParseNode* node) const { | 119 bool Parser::IsAssignment(const ParseNode* node) const { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 } | 218 } |
| 219 left = (this->*infix)(left.Pass(), token); | 219 left = (this->*infix)(left.Pass(), token); |
| 220 if (has_error()) | 220 if (has_error()) |
| 221 return scoped_ptr<ParseNode>(); | 221 return scoped_ptr<ParseNode>(); |
| 222 } | 222 } |
| 223 | 223 |
| 224 return left.Pass(); | 224 return left.Pass(); |
| 225 } | 225 } |
| 226 | 226 |
| 227 scoped_ptr<ParseNode> Parser::Literal(Token token) { | 227 scoped_ptr<ParseNode> Parser::Literal(Token token) { |
| 228 return scoped_ptr<ParseNode>(new LiteralNode(token)).Pass(); | 228 return make_scoped_ptr(new LiteralNode(token)); |
| 229 } | 229 } |
| 230 | 230 |
| 231 scoped_ptr<ParseNode> Parser::Name(Token token) { | 231 scoped_ptr<ParseNode> Parser::Name(Token token) { |
| 232 return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass(); | 232 return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass(); |
| 233 } | 233 } |
| 234 | 234 |
| 235 scoped_ptr<ParseNode> Parser::BlockComment(Token token) { | 235 scoped_ptr<ParseNode> Parser::BlockComment(Token token) { |
| 236 scoped_ptr<BlockCommentNode> comment(new BlockCommentNode()); | 236 scoped_ptr<BlockCommentNode> comment(new BlockCommentNode()); |
| 237 comment->set_comment(token); | 237 comment->set_comment(token); |
| 238 return comment.PassAs<ParseNode>(); | 238 return comment.Pass(); |
| 239 } | 239 } |
| 240 | 240 |
| 241 scoped_ptr<ParseNode> Parser::Group(Token token) { | 241 scoped_ptr<ParseNode> Parser::Group(Token token) { |
| 242 scoped_ptr<ParseNode> expr = ParseExpression(); | 242 scoped_ptr<ParseNode> expr = ParseExpression(); |
| 243 if (has_error()) | 243 if (has_error()) |
| 244 return scoped_ptr<ParseNode>(); | 244 return scoped_ptr<ParseNode>(); |
| 245 Consume(Token::RIGHT_PAREN, "Expected ')'"); | 245 Consume(Token::RIGHT_PAREN, "Expected ')'"); |
| 246 return expr.Pass(); | 246 return expr.Pass(); |
| 247 } | 247 } |
| 248 | 248 |
| 249 scoped_ptr<ParseNode> Parser::Not(Token token) { | 249 scoped_ptr<ParseNode> Parser::Not(Token token) { |
| 250 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); | 250 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); |
| 251 if (has_error()) | 251 if (has_error()) |
| 252 return scoped_ptr<ParseNode>(); | 252 return scoped_ptr<ParseNode>(); |
| 253 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); | 253 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); |
| 254 unary_op->set_op(token); | 254 unary_op->set_op(token); |
| 255 unary_op->set_operand(expr.Pass()); | 255 unary_op->set_operand(expr.Pass()); |
| 256 return unary_op.PassAs<ParseNode>(); | 256 return unary_op.Pass(); |
| 257 } | 257 } |
| 258 | 258 |
| 259 scoped_ptr<ParseNode> Parser::List(Token node) { | 259 scoped_ptr<ParseNode> Parser::List(Token node) { |
| 260 scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); | 260 scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true)); |
| 261 if (!has_error() && !at_end()) | 261 if (!has_error() && !at_end()) |
| 262 Consume(Token::RIGHT_BRACKET, "Expected ']'"); | 262 Consume(Token::RIGHT_BRACKET, "Expected ']'"); |
| 263 return list.Pass(); | 263 return list.Pass(); |
| 264 } | 264 } |
| 265 | 265 |
| 266 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, | 266 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, |
| 267 Token token) { | 267 Token token) { |
| 268 scoped_ptr<ParseNode> right = | 268 scoped_ptr<ParseNode> right = |
| 269 ParseExpression(expressions_[token.type()].precedence + 1); | 269 ParseExpression(expressions_[token.type()].precedence + 1); |
| 270 if (!right) { | 270 if (!right) { |
| 271 *err_ = | 271 *err_ = |
| 272 Err(token, | 272 Err(token, |
| 273 "Expected right hand side for '" + token.value().as_string() + "'"); | 273 "Expected right hand side for '" + token.value().as_string() + "'"); |
| 274 return scoped_ptr<ParseNode>(); | 274 return scoped_ptr<ParseNode>(); |
| 275 } | 275 } |
| 276 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); | 276 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); |
| 277 binary_op->set_op(token); | 277 binary_op->set_op(token); |
| 278 binary_op->set_left(left.Pass()); | 278 binary_op->set_left(left.Pass()); |
| 279 binary_op->set_right(right.Pass()); | 279 binary_op->set_right(right.Pass()); |
| 280 return binary_op.PassAs<ParseNode>(); | 280 return binary_op.Pass(); |
| 281 } | 281 } |
| 282 | 282 |
| 283 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, | 283 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, |
| 284 Token token) { | 284 Token token) { |
| 285 scoped_ptr<ListNode> list(new ListNode); | 285 scoped_ptr<ListNode> list(new ListNode); |
| 286 list->set_begin_token(token); | 286 list->set_begin_token(token); |
| 287 list->set_end(make_scoped_ptr(new EndNode(token))); | 287 list->set_end(make_scoped_ptr(new EndNode(token))); |
| 288 scoped_ptr<BlockNode> block; | 288 scoped_ptr<BlockNode> block; |
| 289 bool has_arg = false; | 289 bool has_arg = false; |
| 290 if (LookAhead(Token::LEFT_PAREN)) { | 290 if (LookAhead(Token::LEFT_PAREN)) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 309 | 309 |
| 310 if (!left && !has_arg) { | 310 if (!left && !has_arg) { |
| 311 // Not a function call, just a standalone identifier. | 311 // Not a function call, just a standalone identifier. |
| 312 return scoped_ptr<ParseNode>(new IdentifierNode(token)).Pass(); | 312 return scoped_ptr<ParseNode>(new IdentifierNode(token)).Pass(); |
| 313 } | 313 } |
| 314 scoped_ptr<FunctionCallNode> func_call(new FunctionCallNode); | 314 scoped_ptr<FunctionCallNode> func_call(new FunctionCallNode); |
| 315 func_call->set_function(token); | 315 func_call->set_function(token); |
| 316 func_call->set_args(list.Pass()); | 316 func_call->set_args(list.Pass()); |
| 317 if (block) | 317 if (block) |
| 318 func_call->set_block(block.Pass()); | 318 func_call->set_block(block.Pass()); |
| 319 return func_call.PassAs<ParseNode>(); | 319 return func_call.Pass(); |
| 320 } | 320 } |
| 321 | 321 |
| 322 scoped_ptr<ParseNode> Parser::Assignment(scoped_ptr<ParseNode> left, | 322 scoped_ptr<ParseNode> Parser::Assignment(scoped_ptr<ParseNode> left, |
| 323 Token token) { | 323 Token token) { |
| 324 if (left->AsIdentifier() == NULL) { | 324 if (left->AsIdentifier() == NULL) { |
| 325 *err_ = Err(left.get(), "Left-hand side of assignment must be identifier."); | 325 *err_ = Err(left.get(), "Left-hand side of assignment must be identifier."); |
| 326 return scoped_ptr<ParseNode>(); | 326 return scoped_ptr<ParseNode>(); |
| 327 } | 327 } |
| 328 scoped_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); | 328 scoped_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT); |
| 329 scoped_ptr<BinaryOpNode> assign(new BinaryOpNode); | 329 scoped_ptr<BinaryOpNode> assign(new BinaryOpNode); |
| 330 assign->set_op(token); | 330 assign->set_op(token); |
| 331 assign->set_left(left.Pass()); | 331 assign->set_left(left.Pass()); |
| 332 assign->set_right(value.Pass()); | 332 assign->set_right(value.Pass()); |
| 333 return assign.PassAs<ParseNode>(); | 333 return assign.Pass(); |
| 334 } | 334 } |
| 335 | 335 |
| 336 scoped_ptr<ParseNode> Parser::Subscript(scoped_ptr<ParseNode> left, | 336 scoped_ptr<ParseNode> Parser::Subscript(scoped_ptr<ParseNode> left, |
| 337 Token token) { | 337 Token token) { |
| 338 // TODO: Maybe support more complex expressions like a[0][0]. This would | 338 // TODO: Maybe support more complex expressions like a[0][0]. This would |
| 339 // require work on the evaluator too. | 339 // require work on the evaluator too. |
| 340 if (left->AsIdentifier() == NULL) { | 340 if (left->AsIdentifier() == NULL) { |
| 341 *err_ = Err(left.get(), "May only subscript identifiers.", | 341 *err_ = Err(left.get(), "May only subscript identifiers.", |
| 342 "The thing on the left hand side of the [] must be an identifier\n" | 342 "The thing on the left hand side of the [] must be an identifier\n" |
| 343 "and not an expression. If you need this, you'll have to assign the\n" | 343 "and not an expression. If you need this, you'll have to assign the\n" |
| 344 "value to a temporary before subscripting. Sorry."); | 344 "value to a temporary before subscripting. Sorry."); |
| 345 return scoped_ptr<ParseNode>(); | 345 return scoped_ptr<ParseNode>(); |
| 346 } | 346 } |
| 347 scoped_ptr<ParseNode> value = ParseExpression(); | 347 scoped_ptr<ParseNode> value = ParseExpression(); |
| 348 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); | 348 Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript."); |
| 349 scoped_ptr<AccessorNode> accessor(new AccessorNode); | 349 scoped_ptr<AccessorNode> accessor(new AccessorNode); |
| 350 accessor->set_base(left->AsIdentifier()->value()); | 350 accessor->set_base(left->AsIdentifier()->value()); |
| 351 accessor->set_index(value.Pass()); | 351 accessor->set_index(value.Pass()); |
| 352 return accessor.PassAs<ParseNode>(); | 352 return accessor.Pass(); |
| 353 } | 353 } |
| 354 | 354 |
| 355 scoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left, | 355 scoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left, |
| 356 Token token) { | 356 Token token) { |
| 357 if (left->AsIdentifier() == NULL) { | 357 if (left->AsIdentifier() == NULL) { |
| 358 *err_ = Err(left.get(), "May only use \".\" for identifiers.", | 358 *err_ = Err(left.get(), "May only use \".\" for identifiers.", |
| 359 "The thing on the left hand side of the dot must be an identifier\n" | 359 "The thing on the left hand side of the dot must be an identifier\n" |
| 360 "and not an expression. If you need this, you'll have to assign the\n" | 360 "and not an expression. If you need this, you'll have to assign the\n" |
| 361 "value to a temporary first. Sorry."); | 361 "value to a temporary first. Sorry."); |
| 362 return scoped_ptr<ParseNode>(); | 362 return scoped_ptr<ParseNode>(); |
| 363 } | 363 } |
| 364 | 364 |
| 365 scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); | 365 scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT); |
| 366 if (!right || !right->AsIdentifier()) { | 366 if (!right || !right->AsIdentifier()) { |
| 367 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", | 367 *err_ = Err(token, "Expected identifier for right-hand-side of \".\"", |
| 368 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); | 368 "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()"); |
| 369 return scoped_ptr<ParseNode>(); | 369 return scoped_ptr<ParseNode>(); |
| 370 } | 370 } |
| 371 | 371 |
| 372 scoped_ptr<AccessorNode> accessor(new AccessorNode); | 372 scoped_ptr<AccessorNode> accessor(new AccessorNode); |
| 373 accessor->set_base(left->AsIdentifier()->value()); | 373 accessor->set_base(left->AsIdentifier()->value()); |
| 374 accessor->set_member(scoped_ptr<IdentifierNode>( | 374 accessor->set_member(scoped_ptr<IdentifierNode>( |
| 375 static_cast<IdentifierNode*>(right.release()))); | 375 static_cast<IdentifierNode*>(right.release()))); |
| 376 return accessor.PassAs<ParseNode>(); | 376 return accessor.Pass(); |
| 377 } | 377 } |
| 378 | 378 |
| 379 // Does not Consume the start or end token. | 379 // Does not Consume the start or end token. |
| 380 scoped_ptr<ListNode> Parser::ParseList(Token start_token, | 380 scoped_ptr<ListNode> Parser::ParseList(Token start_token, |
| 381 Token::Type stop_before, | 381 Token::Type stop_before, |
| 382 bool allow_trailing_comma) { | 382 bool allow_trailing_comma) { |
| 383 scoped_ptr<ListNode> list(new ListNode); | 383 scoped_ptr<ListNode> list(new ListNode); |
| 384 list->set_begin_token(start_token); | 384 list->set_begin_token(start_token); |
| 385 bool just_got_comma = false; | 385 bool just_got_comma = false; |
| 386 bool first_time = true; | 386 bool first_time = true; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 *err_ = Err(cur_token(), "Unexpected here, should be newline."); | 435 *err_ = Err(cur_token(), "Unexpected here, should be newline."); |
| 436 if (has_error()) | 436 if (has_error()) |
| 437 return scoped_ptr<ParseNode>(); | 437 return scoped_ptr<ParseNode>(); |
| 438 | 438 |
| 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.PassAs<ParseNode>(); | 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::LEFT_BRACE)) { |
| 450 return ParseBlock().PassAs<ParseNode>(); | 450 return ParseBlock(); |
| 451 } else if (LookAhead(Token::IF)) { | 451 } else if (LookAhead(Token::IF)) { |
| 452 return ParseCondition(); | 452 return ParseCondition(); |
| 453 } else if (LookAhead(Token::BLOCK_COMMENT)) { | 453 } else if (LookAhead(Token::BLOCK_COMMENT)) { |
| 454 return BlockComment(Consume()); | 454 return BlockComment(Consume()); |
| 455 } else { | 455 } else { |
| 456 // TODO(scottmg): Is this too strict? Just drop all the testing if we want | 456 // TODO(scottmg): Is this too strict? Just drop all the testing if we want |
| 457 // to allow "pointless" expressions and return ParseExpression() directly. | 457 // to allow "pointless" expressions and return ParseExpression() directly. |
| 458 scoped_ptr<ParseNode> stmt = ParseExpression(); | 458 scoped_ptr<ParseNode> stmt = ParseExpression(); |
| 459 if (stmt) { | 459 if (stmt) { |
| 460 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) | 460 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); | 496 Consume(Token::LEFT_PAREN, "Expected '(' after 'if'."); |
| 497 condition->set_condition(ParseExpression()); | 497 condition->set_condition(ParseExpression()); |
| 498 if (IsAssignment(condition->condition())) | 498 if (IsAssignment(condition->condition())) |
| 499 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); | 499 *err_ = Err(condition->condition(), "Assignment not allowed in 'if'."); |
| 500 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); | 500 Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'."); |
| 501 condition->set_if_true(ParseBlock().Pass()); | 501 condition->set_if_true(ParseBlock().Pass()); |
| 502 if (Match(Token::ELSE)) | 502 if (Match(Token::ELSE)) |
| 503 condition->set_if_false(ParseStatement().Pass()); | 503 condition->set_if_false(ParseStatement().Pass()); |
| 504 if (has_error()) | 504 if (has_error()) |
| 505 return scoped_ptr<ParseNode>(); | 505 return scoped_ptr<ParseNode>(); |
| 506 return condition.PassAs<ParseNode>(); | 506 return condition.Pass(); |
| 507 } | 507 } |
| 508 | 508 |
| 509 void Parser::TraverseOrder(const ParseNode* root, | 509 void Parser::TraverseOrder(const ParseNode* root, |
| 510 std::vector<const ParseNode*>* pre, | 510 std::vector<const ParseNode*>* pre, |
| 511 std::vector<const ParseNode*>* post) { | 511 std::vector<const ParseNode*>* post) { |
| 512 if (root) { | 512 if (root) { |
| 513 pre->push_back(root); | 513 pre->push_back(root); |
| 514 | 514 |
| 515 if (const AccessorNode* accessor = root->AsAccessor()) { | 515 if (const AccessorNode* accessor = root->AsAccessor()) { |
| 516 TraverseOrder(accessor->index(), pre, post); | 516 TraverseOrder(accessor->index(), pre, post); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 break; | 610 break; |
| 611 } | 611 } |
| 612 } | 612 } |
| 613 | 613 |
| 614 // Suffix comments were assigned in reverse, so if there were multiple on | 614 // Suffix comments were assigned in reverse, so if there were multiple on |
| 615 // the same node, they need to be reversed. | 615 // the same node, they need to be reversed. |
| 616 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) | 616 if ((*i)->comments() && !(*i)->comments()->suffix().empty()) |
| 617 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); | 617 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); |
| 618 } | 618 } |
| 619 } | 619 } |
| OLD | NEW |