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 |