Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: tools/gn/parser.cc

Issue 591373002: gn: start of format command (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn-more-comment-stuff
Patch Set: change 'copyright header block' to 'standard header block' for android_webview/tools/check_licenses… Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/parser.h ('k') | tools/gn/parser_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 {&Parser::Group, NULL, -1}, // LEFT_PAREN 67 {&Parser::Group, NULL, -1}, // LEFT_PAREN
68 {NULL, NULL, -1}, // RIGHT_PAREN 68 {NULL, NULL, -1}, // RIGHT_PAREN
69 {&Parser::List, &Parser::Subscript, PRECEDENCE_CALL}, // LEFT_BRACKET 69 {&Parser::List, &Parser::Subscript, PRECEDENCE_CALL}, // LEFT_BRACKET
70 {NULL, NULL, -1}, // RIGHT_BRACKET 70 {NULL, NULL, -1}, // RIGHT_BRACKET
71 {NULL, NULL, -1}, // LEFT_BRACE 71 {NULL, NULL, -1}, // LEFT_BRACE
72 {NULL, NULL, -1}, // RIGHT_BRACE 72 {NULL, NULL, -1}, // RIGHT_BRACE
73 {NULL, NULL, -1}, // IF 73 {NULL, NULL, -1}, // IF
74 {NULL, NULL, -1}, // ELSE 74 {NULL, NULL, -1}, // ELSE
75 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER 75 {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER
76 {NULL, NULL, -1}, // COMMA 76 {NULL, NULL, -1}, // COMMA
77 {NULL, NULL, -1}, // UNCLASSIFIED_COMMENT 77 {NULL, NULL, -1}, // UNCLASSIFIED_COMMENT
78 {NULL, NULL, -1}, // LINE_COMMENT 78 {NULL, NULL, -1}, // LINE_COMMENT
79 {NULL, NULL, -1}, // SUFFIX_COMMENT 79 {NULL, NULL, -1}, // SUFFIX_COMMENT
80 {&Parser::BlockComment, NULL, -1}, // BLOCK_COMMENT
80 }; 81 };
81 82
82 Parser::Parser(const std::vector<Token>& tokens, Err* err) 83 Parser::Parser(const std::vector<Token>& tokens, Err* err)
83 : err_(err), cur_(0) { 84 : err_(err), cur_(0) {
84 for (std::vector<Token>::const_iterator i(tokens.begin()); i != tokens.end(); 85 for (std::vector<Token>::const_iterator i(tokens.begin()); i != tokens.end();
85 ++i) { 86 ++i) {
86 switch(i->type()) { 87 switch(i->type()) {
87 case Token::LINE_COMMENT: 88 case Token::LINE_COMMENT:
88 line_comment_tokens_.push_back(*i); 89 line_comment_tokens_.push_back(*i);
89 break; 90 break;
90 case Token::SUFFIX_COMMENT: 91 case Token::SUFFIX_COMMENT:
91 suffix_comment_tokens_.push_back(*i); 92 suffix_comment_tokens_.push_back(*i);
92 break; 93 break;
93 default: 94 default:
95 // Note that BLOCK_COMMENTs (top-level standalone comments) are passed
96 // through the real parser.
94 tokens_.push_back(*i); 97 tokens_.push_back(*i);
95 break; 98 break;
96 } 99 }
97 } 100 }
98 } 101 }
99 102
100 Parser::~Parser() { 103 Parser::~Parser() {
101 } 104 }
102 105
103 // static 106 // static
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 226 }
224 227
225 scoped_ptr<ParseNode> Parser::Literal(Token token) { 228 scoped_ptr<ParseNode> Parser::Literal(Token token) {
226 return scoped_ptr<ParseNode>(new LiteralNode(token)).Pass(); 229 return scoped_ptr<ParseNode>(new LiteralNode(token)).Pass();
227 } 230 }
228 231
229 scoped_ptr<ParseNode> Parser::Name(Token token) { 232 scoped_ptr<ParseNode> Parser::Name(Token token) {
230 return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass(); 233 return IdentifierOrCall(scoped_ptr<ParseNode>(), token).Pass();
231 } 234 }
232 235
236 scoped_ptr<ParseNode> Parser::BlockComment(Token token) {
237 scoped_ptr<BlockCommentNode> comment(new BlockCommentNode());
238 comment->set_comment(token);
239 return comment.PassAs<ParseNode>();
240 }
241
233 scoped_ptr<ParseNode> Parser::Group(Token token) { 242 scoped_ptr<ParseNode> Parser::Group(Token token) {
234 scoped_ptr<ParseNode> expr = ParseExpression(); 243 scoped_ptr<ParseNode> expr = ParseExpression();
235 if (has_error()) 244 if (has_error())
236 return scoped_ptr<ParseNode>(); 245 return scoped_ptr<ParseNode>();
237 Consume(Token::RIGHT_PAREN, "Expected ')'"); 246 Consume(Token::RIGHT_PAREN, "Expected ')'");
238 return expr.Pass(); 247 return expr.Pass();
239 } 248 }
240 249
241 scoped_ptr<ParseNode> Parser::Not(Token token) { 250 scoped_ptr<ParseNode> Parser::Not(Token token) {
242 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1); 251 scoped_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1);
243 if (has_error()) 252 if (has_error())
244 return scoped_ptr<ParseNode>(); 253 return scoped_ptr<ParseNode>();
245 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode); 254 scoped_ptr<UnaryOpNode> unary_op(new UnaryOpNode);
246 unary_op->set_op(token); 255 unary_op->set_op(token);
247 unary_op->set_operand(expr.Pass()); 256 unary_op->set_operand(expr.Pass());
248 return unary_op.PassAs<ParseNode>(); 257 return unary_op.PassAs<ParseNode>();
249 } 258 }
250 259
251 scoped_ptr<ParseNode> Parser::List(Token node) { 260 scoped_ptr<ParseNode> Parser::List(Token node) {
252 scoped_ptr<ParseNode> list(ParseList(Token::RIGHT_BRACKET, true)); 261 scoped_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true));
253 if (!has_error() && !at_end()) 262 if (!has_error() && !at_end())
254 Consume(Token::RIGHT_BRACKET, "Expected ']'"); 263 Consume(Token::RIGHT_BRACKET, "Expected ']'");
255 return list.Pass(); 264 return list.Pass();
256 } 265 }
257 266
258 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left, 267 scoped_ptr<ParseNode> Parser::BinaryOperator(scoped_ptr<ParseNode> left,
259 Token token) { 268 Token token) {
260 scoped_ptr<ParseNode> right = 269 scoped_ptr<ParseNode> right =
261 ParseExpression(expressions_[token.type()].precedence + 1); 270 ParseExpression(expressions_[token.type()].precedence + 1);
262 if (!right) { 271 if (!right) {
263 *err_ = 272 *err_ =
264 Err(token, 273 Err(token,
265 "Expected right hand side for '" + token.value().as_string() + "'"); 274 "Expected right hand side for '" + token.value().as_string() + "'");
266 return scoped_ptr<ParseNode>(); 275 return scoped_ptr<ParseNode>();
267 } 276 }
268 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); 277 scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode);
269 binary_op->set_op(token); 278 binary_op->set_op(token);
270 binary_op->set_left(left.Pass()); 279 binary_op->set_left(left.Pass());
271 binary_op->set_right(right.Pass()); 280 binary_op->set_right(right.Pass());
272 return binary_op.PassAs<ParseNode>(); 281 return binary_op.PassAs<ParseNode>();
273 } 282 }
274 283
275 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left, 284 scoped_ptr<ParseNode> Parser::IdentifierOrCall(scoped_ptr<ParseNode> left,
276 Token token) { 285 Token token) {
277 scoped_ptr<ListNode> list(new ListNode); 286 scoped_ptr<ListNode> list(new ListNode);
278 list->set_begin_token(token); 287 list->set_begin_token(token);
279 list->set_end_token(token); 288 list->set_end_token(token);
280 scoped_ptr<BlockNode> block; 289 scoped_ptr<BlockNode> block;
281 bool has_arg = false; 290 bool has_arg = false;
282 if (Match(Token::LEFT_PAREN)) { 291 if (LookAhead(Token::LEFT_PAREN)) {
292 Token start_token = Consume();
283 // Parsing a function call. 293 // Parsing a function call.
284 has_arg = true; 294 has_arg = true;
285 if (Match(Token::RIGHT_PAREN)) { 295 if (Match(Token::RIGHT_PAREN)) {
286 // Nothing, just an empty call. 296 // Nothing, just an empty call.
287 } else { 297 } else {
288 list = ParseList(Token::RIGHT_PAREN, false); 298 list = ParseList(start_token, Token::RIGHT_PAREN, false);
289 if (has_error()) 299 if (has_error())
290 return scoped_ptr<ParseNode>(); 300 return scoped_ptr<ParseNode>();
291 Consume(Token::RIGHT_PAREN, "Expected ')' after call"); 301 Consume(Token::RIGHT_PAREN, "Expected ')' after call");
292 } 302 }
293 // Optionally with a scope. 303 // Optionally with a scope.
294 if (LookAhead(Token::LEFT_BRACE)) { 304 if (LookAhead(Token::LEFT_BRACE)) {
295 block = ParseBlock(); 305 block = ParseBlock();
296 if (has_error()) 306 if (has_error())
297 return scoped_ptr<ParseNode>(); 307 return scoped_ptr<ParseNode>();
298 } 308 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 } 371 }
362 372
363 scoped_ptr<AccessorNode> accessor(new AccessorNode); 373 scoped_ptr<AccessorNode> accessor(new AccessorNode);
364 accessor->set_base(left->AsIdentifier()->value()); 374 accessor->set_base(left->AsIdentifier()->value());
365 accessor->set_member(scoped_ptr<IdentifierNode>( 375 accessor->set_member(scoped_ptr<IdentifierNode>(
366 static_cast<IdentifierNode*>(right.release()))); 376 static_cast<IdentifierNode*>(right.release())));
367 return accessor.PassAs<ParseNode>(); 377 return accessor.PassAs<ParseNode>();
368 } 378 }
369 379
370 // Does not Consume the start or end token. 380 // Does not Consume the start or end token.
371 scoped_ptr<ListNode> Parser::ParseList(Token::Type stop_before, 381 scoped_ptr<ListNode> Parser::ParseList(Token start_token,
382 Token::Type stop_before,
372 bool allow_trailing_comma) { 383 bool allow_trailing_comma) {
373 scoped_ptr<ListNode> list(new ListNode); 384 scoped_ptr<ListNode> list(new ListNode);
374 list->set_begin_token(cur_token()); 385 list->set_begin_token(start_token);
375 bool just_got_comma = false; 386 bool just_got_comma = false;
376 bool first_time = true; 387 bool first_time = true;
377 while (!LookAhead(stop_before)) { 388 while (!LookAhead(stop_before)) {
378 if (!first_time) { 389 if (!first_time) {
379 if (!just_got_comma) { 390 if (!just_got_comma) {
380 // Require commas separate things in lists. 391 // Require commas separate things in lists.
381 *err_ = Err(cur_token(), "Expected comma between items."); 392 *err_ = Err(cur_token(), "Expected comma between items.");
382 return scoped_ptr<ListNode>(); 393 return scoped_ptr<ListNode>();
383 } 394 }
384 } 395 }
385 first_time = false; 396 first_time = false;
386 397
387 // Why _OR? We're parsing things that are higher precedence than the , 398 // Why _OR? We're parsing things that are higher precedence than the ,
388 // that separates the items of the list. , should appear lower than 399 // that separates the items of the list. , should appear lower than
389 // boolean expressions (the lowest of which is OR), but above assignments. 400 // boolean expressions (the lowest of which is OR), but above assignments.
390 list->append_item(ParseExpression(PRECEDENCE_OR)); 401 list->append_item(ParseExpression(PRECEDENCE_OR));
391 if (has_error()) 402 if (has_error())
392 return scoped_ptr<ListNode>(); 403 return scoped_ptr<ListNode>();
393 if (at_end()) { 404 if (at_end()) {
394 *err_ = 405 *err_ =
395 Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list."); 406 Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list.");
396 return scoped_ptr<ListNode>(); 407 return scoped_ptr<ListNode>();
397 } 408 }
398 just_got_comma = Match(Token::COMMA); 409 if (list->contents().back()->AsBlockComment()) {
410 // If there was a comment inside the list, we don't need a comma to the
411 // next item, so pretend we got one, if we're expecting one.
412 just_got_comma = allow_trailing_comma;
413 } else {
414 just_got_comma = Match(Token::COMMA);
415 }
399 } 416 }
400 if (just_got_comma && !allow_trailing_comma) { 417 if (just_got_comma && !allow_trailing_comma) {
401 *err_ = Err(cur_token(), "Trailing comma"); 418 *err_ = Err(cur_token(), "Trailing comma");
402 return scoped_ptr<ListNode>(); 419 return scoped_ptr<ListNode>();
403 } 420 }
404 list->set_end_token(cur_token()); 421 list->set_end_token(cur_token());
405 return list.Pass(); 422 return list.Pass();
406 } 423 }
407 424
408 scoped_ptr<ParseNode> Parser::ParseFile() { 425 scoped_ptr<ParseNode> Parser::ParseFile() {
(...skipping 18 matching lines...) Expand all
427 AssignComments(file.get()); 444 AssignComments(file.get());
428 445
429 return file.PassAs<ParseNode>(); 446 return file.PassAs<ParseNode>();
430 } 447 }
431 448
432 scoped_ptr<ParseNode> Parser::ParseStatement() { 449 scoped_ptr<ParseNode> Parser::ParseStatement() {
433 if (LookAhead(Token::LEFT_BRACE)) { 450 if (LookAhead(Token::LEFT_BRACE)) {
434 return ParseBlock().PassAs<ParseNode>(); 451 return ParseBlock().PassAs<ParseNode>();
435 } else if (LookAhead(Token::IF)) { 452 } else if (LookAhead(Token::IF)) {
436 return ParseCondition(); 453 return ParseCondition();
454 } else if (LookAhead(Token::BLOCK_COMMENT)) {
455 return BlockComment(Consume());
437 } else { 456 } else {
438 // TODO(scottmg): Is this too strict? Just drop all the testing if we want 457 // TODO(scottmg): Is this too strict? Just drop all the testing if we want
439 // to allow "pointless" expressions and return ParseExpression() directly. 458 // to allow "pointless" expressions and return ParseExpression() directly.
440 scoped_ptr<ParseNode> stmt = ParseExpression(); 459 scoped_ptr<ParseNode> stmt = ParseExpression();
441 if (stmt) { 460 if (stmt) {
442 if (stmt->AsFunctionCall() || IsAssignment(stmt.get())) 461 if (stmt->AsFunctionCall() || IsAssignment(stmt.get()))
443 return stmt.Pass(); 462 return stmt.Pass();
444 } 463 }
445 if (!has_error()) { 464 if (!has_error()) {
446 Token token = at_end() ? tokens_[tokens_.size() - 1] : cur_token(); 465 Token token = at_end() ? tokens_[tokens_.size() - 1] : cur_token();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 const std::vector<const ParseNode*>& contents = list->contents(); 539 const std::vector<const ParseNode*>& contents = list->contents();
521 for (std::vector<const ParseNode*>::const_iterator i(contents.begin()); 540 for (std::vector<const ParseNode*>::const_iterator i(contents.begin());
522 i != contents.end(); 541 i != contents.end();
523 ++i) { 542 ++i) {
524 TraverseOrder(*i, pre, post); 543 TraverseOrder(*i, pre, post);
525 } 544 }
526 } else if (root->AsLiteral()) { 545 } else if (root->AsLiteral()) {
527 // Nothing. 546 // Nothing.
528 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { 547 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) {
529 TraverseOrder(unaryop->operand(), pre, post); 548 TraverseOrder(unaryop->operand(), pre, post);
549 } else if (root->AsBlockComment()) {
550 // Nothing.
530 } else { 551 } else {
531 CHECK(false) << "Unhandled case in TraverseOrder."; 552 CHECK(false) << "Unhandled case in TraverseOrder.";
532 } 553 }
533 554
534 post->push_back(root); 555 post->push_back(root);
535 } 556 }
536 } 557 }
537 558
538 void Parser::AssignComments(ParseNode* file) { 559 void Parser::AssignComments(ParseNode* file) {
539 // Start by generating a pre- and post- order traversal of the tree so we 560 // Start by generating a pre- and post- order traversal of the tree so we
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 } else { 616 } else {
596 break; 617 break;
597 } 618 }
598 } 619 }
599 620
600 // Suffix comments were assigned in reverse, so if there were multiple on 621 // Suffix comments were assigned in reverse, so if there were multiple on
601 // the same node, they need to be reversed. 622 // the same node, they need to be reversed.
602 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix(); 623 const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix();
603 } 624 }
604 } 625 }
OLDNEW
« no previous file with comments | « tools/gn/parser.h ('k') | tools/gn/parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698