1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_PARSE_TREE_H_ 6 #define TOOLS_GN_PARSE_TREE_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <string_view> 12 #include <utility> 13 #include <vector> 14 15 #include "base/values.h" 16 #include "gn/err.h" 17 #include "gn/token.h" 18 #include "gn/value.h" 19 20 class AccessorNode; 21 class BinaryOpNode; 22 class BlockCommentNode; 23 class BlockNode; 24 class ConditionNode; 25 class EndNode; 26 class FunctionCallNode; 27 class IdentifierNode; 28 class ListNode; 29 class LiteralNode; 30 class Scope; 31 class UnaryOpNode; 32 33 // Dictionary keys used for JSON-formatted tree dump. 34 extern const char kJsonNodeChild[]; 35 extern const char kJsonNodeType[]; 36 extern const char kJsonNodeValue[]; 37 extern const char kJsonBeforeComment[]; 38 extern const char kJsonSuffixComment[]; 39 extern const char kJsonAfterComment[]; 40 41 class Comments { 42 public: 43 Comments(); 44 virtual ~Comments(); 45 before()46 const std::vector<Token>& before() const { return before_; } append_before(Token c)47 void append_before(Token c) { before_.push_back(c); } clear_before()48 void clear_before() { before_.clear(); } 49 suffix()50 const std::vector<Token>& suffix() const { return suffix_; } append_suffix(Token c)51 void append_suffix(Token c) { suffix_.push_back(c); } 52 // Reverse the order of the suffix comments. When walking the tree in 53 // post-order we append suffix comments in reverse order, so this fixes them 54 // up. 55 void ReverseSuffix(); 56 after()57 const std::vector<Token>& after() const { return after_; } append_after(Token c)58 void append_after(Token c) { after_.push_back(c); } 59 60 private: 61 // Whole line comments before the expression. 62 std::vector<Token> before_; 63 64 // End-of-line comments after this expression. 65 std::vector<Token> suffix_; 66 67 // For top-level expressions only, after_ lists whole-line comments 68 // following the expression. 69 std::vector<Token> after_; 70 71 Comments(const Comments&) = delete; 72 Comments& operator=(const Comments&) = delete; 73 }; 74 75 // ParseNode ------------------------------------------------------------------- 76 77 // A node in the AST. 78 class ParseNode { 79 public: 80 ParseNode(); 81 virtual ~ParseNode(); 82 83 virtual const AccessorNode* AsAccessor() const; 84 virtual const BinaryOpNode* AsBinaryOp() const; 85 virtual const BlockCommentNode* AsBlockComment() const; 86 virtual const BlockNode* AsBlock() const; 87 virtual const ConditionNode* AsCondition() const; 88 virtual const EndNode* AsEnd() const; 89 virtual const FunctionCallNode* AsFunctionCall() const; 90 virtual const IdentifierNode* AsIdentifier() const; 91 virtual const ListNode* AsList() const; 92 virtual const LiteralNode* AsLiteral() const; 93 virtual const UnaryOpNode* AsUnaryOp() const; 94 95 virtual Value Execute(Scope* scope, Err* err) const = 0; 96 97 virtual LocationRange GetRange() const = 0; 98 99 // Returns an error with the given messages and the range set to something 100 // that indicates this node. 101 virtual Err MakeErrorDescribing( 102 const std::string& msg, 103 const std::string& help = std::string()) const = 0; 104 105 // Generates a representation of this node in base::Value, to be used for 106 // exporting the tree as a JSON or formatted text with indents. 107 virtual base::Value GetJSONNode() const = 0; 108 comments()109 const Comments* comments() const { return comments_.get(); } 110 Comments* comments_mutable(); 111 112 static std::unique_ptr<ParseNode> BuildFromJSON(const base::Value& value); 113 114 protected: 115 // Helper functions for GetJSONNode. Creates and fills a Value object with 116 // given type (and value). 117 base::Value CreateJSONNode(const char* type, LocationRange location) const; 118 base::Value CreateJSONNode(const char* type, 119 std::string_view value, 120 LocationRange location) const; 121 122 private: 123 // Helper function for CreateJSONNode. 124 void AddCommentsJSONNodes(base::Value* out_value) const; 125 126 std::unique_ptr<Comments> comments_; 127 128 ParseNode(const ParseNode&) = delete; 129 ParseNode& operator=(const ParseNode&) = delete; 130 }; 131 132 // AccessorNode ---------------------------------------------------------------- 133 134 // Access an array or scope element. 135 // 136 // Currently, such values are only read-only. In that you can do: 137 // a = obj1.a 138 // b = obj2[0] 139 // But not 140 // obj1.a = 5 141 // obj2[0] = 6 142 // 143 // In the current design where the dot operator is used only for templates, we 144 // explicitly don't want to allow you to do "invoker.foo = 5", so if we added 145 // support for accessors to be lvalues, we would also need to add some concept 146 // of a constant scope. Supporting this would also add a lot of complications 147 // to the operator= implementation, since some accessors might return values 148 // in the const root scope that shouldn't be modified. Without a strong 149 // use-case for this, it seems simpler to just disallow it. 150 // 151 // Additionally, the left-hand-side of the accessor must currently be an 152 // identifier. So you can't do things like: 153 // function_call()[1] 154 // a = b.c.d 155 // These are easier to implement if we needed them but given the very limited 156 // use cases for this, it hasn't seemed worth the bother. 157 class AccessorNode : public ParseNode { 158 public: 159 AccessorNode(); 160 ~AccessorNode() override; 161 162 const AccessorNode* AsAccessor() const override; 163 Value Execute(Scope* scope, Err* err) const override; 164 LocationRange GetRange() const override; 165 Err MakeErrorDescribing( 166 const std::string& msg, 167 const std::string& help = std::string()) const override; 168 base::Value GetJSONNode() const override; 169 static std::unique_ptr<AccessorNode> NewFromJSON(const base::Value& value); 170 171 // Base is the thing on the left of the [] or dot, currently always required 172 // to be an identifier token. base()173 const Token& base() const { return base_; } set_base(const Token & b)174 void set_base(const Token& b) { base_ = b; } 175 176 // Subscript is the expression inside the []. Will be null if member is set. subscript()177 const ParseNode* subscript() const { return subscript_.get(); } set_subscript(std::unique_ptr<ParseNode> key)178 void set_subscript(std::unique_ptr<ParseNode> key) { 179 subscript_ = std::move(key); 180 } 181 182 // The member is the identifier on the right hand side of the dot. Will be 183 // null if the index is set. member()184 const IdentifierNode* member() const { return member_.get(); } set_member(std::unique_ptr<IdentifierNode> i)185 void set_member(std::unique_ptr<IdentifierNode> i) { member_ = std::move(i); } 186 187 void SetNewLocation(int line_number); 188 189 // Evaluates the index for list accessor operations and range checks it 190 // against the max length of the list. If the index is OK, sets 191 // |*computed_index| and returns true. Otherwise sets the |*err| and returns 192 // false. 193 bool ComputeAndValidateListIndex(Scope* scope, 194 size_t max_len, 195 size_t* computed_index, 196 Err* err) const; 197 198 static constexpr const char* kDumpNodeName = "ACCESSOR"; 199 200 private: 201 Value ExecuteSubscriptAccess(Scope* scope, Err* err) const; 202 Value ExecuteArrayAccess(Scope* scope, 203 const Value* base_value, 204 Err* err) const; 205 Value ExecuteScopeSubscriptAccess(Scope* scope, 206 const Value* base_value, 207 Err* err) const; 208 Value ExecuteScopeAccess(Scope* scope, Err* err) const; 209 const Value* ExecuteScopeAccessForMember(Scope* scope, 210 std::string_view member_str, 211 Err* err) const; 212 213 static constexpr const char* kDumpAccessorKind = "accessor_kind"; 214 static constexpr const char* kDumpAccessorKindSubscript = "subscript"; 215 static constexpr const char* kDumpAccessorKindMember = "member"; 216 217 Token base_; 218 219 // Either index or member will be set according to what type of access this 220 // is. 221 std::unique_ptr<ParseNode> subscript_; 222 std::unique_ptr<IdentifierNode> member_; 223 224 AccessorNode(const AccessorNode&) = delete; 225 AccessorNode& operator=(const AccessorNode&) = delete; 226 }; 227 228 // BinaryOpNode ---------------------------------------------------------------- 229 230 class BinaryOpNode : public ParseNode { 231 public: 232 BinaryOpNode(); 233 ~BinaryOpNode() override; 234 235 const BinaryOpNode* AsBinaryOp() const override; 236 Value Execute(Scope* scope, Err* err) const override; 237 LocationRange GetRange() const override; 238 Err MakeErrorDescribing( 239 const std::string& msg, 240 const std::string& help = std::string()) const override; 241 base::Value GetJSONNode() const override; 242 static std::unique_ptr<BinaryOpNode> NewFromJSON(const base::Value& value); 243 op()244 const Token& op() const { return op_; } set_op(const Token & t)245 void set_op(const Token& t) { op_ = t; } 246 left()247 const ParseNode* left() const { return left_.get(); } set_left(std::unique_ptr<ParseNode> left)248 void set_left(std::unique_ptr<ParseNode> left) { left_ = std::move(left); } 249 right()250 const ParseNode* right() const { return right_.get(); } set_right(std::unique_ptr<ParseNode> right)251 void set_right(std::unique_ptr<ParseNode> right) { 252 right_ = std::move(right); 253 } 254 255 static constexpr const char* kDumpNodeName = "BINARY"; 256 257 private: 258 std::unique_ptr<ParseNode> left_; 259 Token op_; 260 std::unique_ptr<ParseNode> right_; 261 262 BinaryOpNode(const BinaryOpNode&) = delete; 263 BinaryOpNode& operator=(const BinaryOpNode&) = delete; 264 }; 265 266 // BlockNode ------------------------------------------------------------------- 267 268 class BlockNode : public ParseNode { 269 public: 270 // How Execute manages the scopes and results. 271 enum ResultMode { 272 // Creates a new scope for the execution of this block and returns it as 273 // a Value from Execute(). 274 RETURNS_SCOPE, 275 276 // Executes in the context of the calling scope (variables set will go 277 // into the invoking scope) and Execute will return an empty Value. 278 DISCARDS_RESULT 279 }; 280 281 BlockNode(ResultMode result_mode); 282 ~BlockNode() override; 283 284 const BlockNode* AsBlock() const override; 285 Value Execute(Scope* scope, Err* err) const override; 286 LocationRange GetRange() const override; 287 Err MakeErrorDescribing( 288 const std::string& msg, 289 const std::string& help = std::string()) const override; 290 base::Value GetJSONNode() const override; 291 static std::unique_ptr<BlockNode> NewFromJSON(const base::Value& value); 292 set_begin_token(const Token & t)293 void set_begin_token(const Token& t) { begin_token_ = t; } set_end(std::unique_ptr<EndNode> e)294 void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); } End()295 const EndNode* End() const { return end_.get(); } 296 result_mode()297 ResultMode result_mode() const { return result_mode_; } 298 statements()299 const std::vector<std::unique_ptr<ParseNode>>& statements() const { 300 return statements_; 301 } append_statement(std::unique_ptr<ParseNode> s)302 void append_statement(std::unique_ptr<ParseNode> s) { 303 statements_.push_back(std::move(s)); 304 } 305 306 static constexpr const char* kDumpNodeName = "BLOCK"; 307 308 private: 309 static constexpr const char* kDumpResultMode = "result_mode"; 310 static constexpr const char* kDumpResultModeReturnsScope = "returns_scope"; 311 static constexpr const char* kDumpResultModeDiscardsResult = 312 "discards_result"; 313 314 const ResultMode result_mode_; 315 316 // Tokens corresponding to { and }, if any (may be NULL). The end is stored 317 // in a custom parse node so that it can have comments hung off of it. 318 Token begin_token_; 319 std::unique_ptr<EndNode> end_; 320 321 std::vector<std::unique_ptr<ParseNode>> statements_; 322 323 BlockNode(const BlockNode&) = delete; 324 BlockNode& operator=(const BlockNode&) = delete; 325 }; 326 327 // ConditionNode --------------------------------------------------------------- 328 329 class ConditionNode : public ParseNode { 330 public: 331 ConditionNode(); 332 ~ConditionNode() override; 333 334 const ConditionNode* AsCondition() const override; 335 Value Execute(Scope* scope, Err* err) const override; 336 LocationRange GetRange() const override; 337 Err MakeErrorDescribing( 338 const std::string& msg, 339 const std::string& help = std::string()) const override; 340 base::Value GetJSONNode() const override; 341 static std::unique_ptr<ConditionNode> NewFromJSON(const base::Value& value); 342 set_if_token(const Token & token)343 void set_if_token(const Token& token) { if_token_ = token; } 344 condition()345 const ParseNode* condition() const { return condition_.get(); } set_condition(std::unique_ptr<ParseNode> c)346 void set_condition(std::unique_ptr<ParseNode> c) { 347 condition_ = std::move(c); 348 } 349 if_true()350 const BlockNode* if_true() const { return if_true_.get(); } set_if_true(std::unique_ptr<BlockNode> t)351 void set_if_true(std::unique_ptr<BlockNode> t) { if_true_ = std::move(t); } 352 353 // This is either empty, a block (for the else clause), or another 354 // condition. if_false()355 const ParseNode* if_false() const { return if_false_.get(); } set_if_false(std::unique_ptr<ParseNode> f)356 void set_if_false(std::unique_ptr<ParseNode> f) { if_false_ = std::move(f); } 357 358 static constexpr const char* kDumpNodeName = "CONDITION"; 359 360 private: 361 // Token corresponding to the "if" string. 362 Token if_token_; 363 364 std::unique_ptr<ParseNode> condition_; // Always non-null. 365 std::unique_ptr<BlockNode> if_true_; // Always non-null. 366 std::unique_ptr<ParseNode> if_false_; // May be null. 367 368 ConditionNode(const ConditionNode&) = delete; 369 ConditionNode& operator=(const ConditionNode&) = delete; 370 }; 371 372 // FunctionCallNode ------------------------------------------------------------ 373 374 class FunctionCallNode : public ParseNode { 375 public: 376 FunctionCallNode(); 377 ~FunctionCallNode() override; 378 379 const FunctionCallNode* AsFunctionCall() const override; 380 Value Execute(Scope* scope, Err* err) const override; 381 LocationRange GetRange() const override; 382 Err MakeErrorDescribing( 383 const std::string& msg, 384 const std::string& help = std::string()) const override; 385 base::Value GetJSONNode() const override; 386 static std::unique_ptr<FunctionCallNode> NewFromJSON( 387 const base::Value& value); 388 function()389 const Token& function() const { return function_; } set_function(Token t)390 void set_function(Token t) { function_ = t; } 391 args()392 const ListNode* args() const { return args_.get(); } set_args(std::unique_ptr<ListNode> a)393 void set_args(std::unique_ptr<ListNode> a) { args_ = std::move(a); } 394 block()395 const BlockNode* block() const { return block_.get(); } set_block(std::unique_ptr<BlockNode> b)396 void set_block(std::unique_ptr<BlockNode> b) { block_ = std::move(b); } 397 398 void SetNewLocation(int line_number); 399 400 static constexpr const char* kDumpNodeName = "FUNCTION"; 401 402 private: 403 Token function_; 404 std::unique_ptr<ListNode> args_; 405 std::unique_ptr<BlockNode> block_; // May be null. 406 407 FunctionCallNode(const FunctionCallNode&) = delete; 408 FunctionCallNode& operator=(const FunctionCallNode&) = delete; 409 }; 410 411 // IdentifierNode -------------------------------------------------------------- 412 413 class IdentifierNode : public ParseNode { 414 public: 415 IdentifierNode(); 416 explicit IdentifierNode(const Token& token); 417 ~IdentifierNode() override; 418 419 const IdentifierNode* AsIdentifier() const override; 420 Value Execute(Scope* scope, Err* err) const override; 421 LocationRange GetRange() const override; 422 Err MakeErrorDescribing( 423 const std::string& msg, 424 const std::string& help = std::string()) const override; 425 base::Value GetJSONNode() const override; 426 static std::unique_ptr<IdentifierNode> NewFromJSON(const base::Value& value); 427 value()428 const Token& value() const { return value_; } set_value(const Token & t)429 void set_value(const Token& t) { value_ = t; } 430 431 void SetNewLocation(int line_number); 432 433 static constexpr const char* kDumpNodeName = "IDENTIFIER"; 434 435 private: 436 Token value_; 437 438 IdentifierNode(const IdentifierNode&) = delete; 439 IdentifierNode& operator=(const IdentifierNode&) = delete; 440 }; 441 442 // ListNode -------------------------------------------------------------------- 443 444 class ListNode : public ParseNode { 445 public: 446 ListNode(); 447 ~ListNode() override; 448 449 const ListNode* AsList() const override; 450 Value Execute(Scope* scope, Err* err) const override; 451 LocationRange GetRange() const override; 452 Err MakeErrorDescribing( 453 const std::string& msg, 454 const std::string& help = std::string()) const override; 455 base::Value GetJSONNode() const override; 456 static std::unique_ptr<ListNode> NewFromJSON(const base::Value& value); 457 set_begin_token(const Token & t)458 void set_begin_token(const Token& t) { begin_token_ = t; } Begin()459 const Token& Begin() const { return begin_token_; } set_end(std::unique_ptr<EndNode> e)460 void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); } End()461 const EndNode* End() const { return end_.get(); } 462 append_item(std::unique_ptr<ParseNode> s)463 void append_item(std::unique_ptr<ParseNode> s) { 464 contents_.push_back(std::move(s)); 465 } contents()466 const std::vector<std::unique_ptr<const ParseNode>>& contents() const { 467 return contents_; 468 } 469 470 void SortAsStringsList(); 471 void SortAsTargetsList(); 472 473 struct SortRange { 474 size_t begin; 475 size_t end; SortRangeSortRange476 SortRange(size_t begin, size_t end) : begin(begin), end(end) {} 477 }; 478 // Only public for testing. 479 std::vector<SortRange> GetSortRanges() const; 480 481 static constexpr const char* kDumpNodeName = "LIST"; 482 483 private: 484 template <typename Comparator> 485 void SortList(Comparator comparator); 486 487 // Tokens corresponding to the [ and ]. The end token is stored in inside an 488 // custom parse node so that it can have comments hung off of it. 489 Token begin_token_; 490 std::unique_ptr<EndNode> end_; 491 492 std::vector<std::unique_ptr<const ParseNode>> contents_; 493 494 ListNode(const ListNode&) = delete; 495 ListNode& operator=(const ListNode&) = delete; 496 }; 497 498 // LiteralNode ----------------------------------------------------------------- 499 500 class LiteralNode : public ParseNode { 501 public: 502 LiteralNode(); 503 explicit LiteralNode(const Token& token); 504 ~LiteralNode() override; 505 506 const LiteralNode* AsLiteral() const override; 507 Value Execute(Scope* scope, Err* err) const override; 508 LocationRange GetRange() const override; 509 Err MakeErrorDescribing( 510 const std::string& msg, 511 const std::string& help = std::string()) const override; 512 base::Value GetJSONNode() const override; 513 static std::unique_ptr<LiteralNode> NewFromJSON(const base::Value& value); 514 value()515 const Token& value() const { return value_; } set_value(const Token & t)516 void set_value(const Token& t) { value_ = t; } 517 518 void SetNewLocation(int line_number); 519 520 static constexpr const char* kDumpNodeName = "LITERAL"; 521 522 private: 523 Token value_; 524 525 LiteralNode(const LiteralNode&) = delete; 526 LiteralNode& operator=(const LiteralNode&) = delete; 527 }; 528 529 // UnaryOpNode ----------------------------------------------------------------- 530 531 class UnaryOpNode : public ParseNode { 532 public: 533 UnaryOpNode(); 534 ~UnaryOpNode() override; 535 536 const UnaryOpNode* AsUnaryOp() const override; 537 Value Execute(Scope* scope, Err* err) const override; 538 LocationRange GetRange() const override; 539 Err MakeErrorDescribing( 540 const std::string& msg, 541 const std::string& help = std::string()) const override; 542 base::Value GetJSONNode() const override; 543 static std::unique_ptr<UnaryOpNode> NewFromJSON(const base::Value& value); 544 op()545 const Token& op() const { return op_; } set_op(const Token & t)546 void set_op(const Token& t) { op_ = t; } 547 operand()548 const ParseNode* operand() const { return operand_.get(); } set_operand(std::unique_ptr<ParseNode> operand)549 void set_operand(std::unique_ptr<ParseNode> operand) { 550 operand_ = std::move(operand); 551 } 552 553 static constexpr const char* kDumpNodeName = "UNARY"; 554 555 private: 556 Token op_; 557 std::unique_ptr<ParseNode> operand_; 558 559 UnaryOpNode(const UnaryOpNode&) = delete; 560 UnaryOpNode& operator=(const UnaryOpNode&) = delete; 561 }; 562 563 // BlockCommentNode ------------------------------------------------------------ 564 565 // This node type is only used for standalone comments (that is, those not 566 // specifically attached to another syntax element. The most common of these 567 // is a standard header block. This node contains only the last line of such 568 // a comment block as the anchor, and other lines of the block comment are 569 // hung off of it as Before comments, similar to other syntax elements. 570 class BlockCommentNode : public ParseNode { 571 public: 572 BlockCommentNode(); 573 ~BlockCommentNode() override; 574 575 const BlockCommentNode* AsBlockComment() const override; 576 Value Execute(Scope* scope, Err* err) const override; 577 LocationRange GetRange() const override; 578 Err MakeErrorDescribing( 579 const std::string& msg, 580 const std::string& help = std::string()) const override; 581 base::Value GetJSONNode() const override; 582 static std::unique_ptr<BlockCommentNode> NewFromJSON( 583 const base::Value& value); 584 comment()585 const Token& comment() const { return comment_; } set_comment(const Token & t)586 void set_comment(const Token& t) { comment_ = t; } 587 588 static constexpr const char* kDumpNodeName = "BLOCK_COMMENT"; 589 590 private: 591 Token comment_; 592 593 BlockCommentNode(const BlockCommentNode&) = delete; 594 BlockCommentNode& operator=(const BlockCommentNode&) = delete; 595 }; 596 597 // EndNode --------------------------------------------------------------------- 598 599 // This node type is used as the end_ object for lists and blocks (rather than 600 // just the end ']', '}', or ')' token). This is so that during formatting 601 // traversal there is a node that appears at the end of the block to which 602 // comments can be attached. 603 class EndNode : public ParseNode { 604 public: 605 explicit EndNode(const Token& token); 606 ~EndNode() override; 607 608 const EndNode* AsEnd() const override; 609 Value Execute(Scope* scope, Err* err) const override; 610 LocationRange GetRange() const override; 611 Err MakeErrorDescribing( 612 const std::string& msg, 613 const std::string& help = std::string()) const override; 614 base::Value GetJSONNode() const override; 615 static std::unique_ptr<EndNode> NewFromJSON(const base::Value& value); 616 value()617 const Token& value() const { return value_; } set_value(const Token & t)618 void set_value(const Token& t) { value_ = t; } 619 620 static constexpr const char* kDumpNodeName = "END"; 621 622 private: 623 Token value_; 624 625 EndNode(const EndNode&) = delete; 626 EndNode& operator=(const EndNode&) = delete; 627 }; 628 629 #endif // TOOLS_GN_PARSE_TREE_H_ 630