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 <utility> 12 #include <vector> 13 14 #include "base/macros.h" 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 DISALLOW_COPY_AND_ASSIGN(Comments); 72 }; 73 74 // ParseNode ------------------------------------------------------------------- 75 76 // A node in the AST. 77 class ParseNode { 78 public: 79 ParseNode(); 80 virtual ~ParseNode(); 81 82 virtual const AccessorNode* AsAccessor() const; 83 virtual const BinaryOpNode* AsBinaryOp() const; 84 virtual const BlockCommentNode* AsBlockComment() const; 85 virtual const BlockNode* AsBlock() const; 86 virtual const ConditionNode* AsConditionNode() const; 87 virtual const EndNode* AsEnd() const; 88 virtual const FunctionCallNode* AsFunctionCall() const; 89 virtual const IdentifierNode* AsIdentifier() const; 90 virtual const ListNode* AsList() const; 91 virtual const LiteralNode* AsLiteral() const; 92 virtual const UnaryOpNode* AsUnaryOp() const; 93 94 virtual Value Execute(Scope* scope, Err* err) const = 0; 95 96 virtual LocationRange GetRange() const = 0; 97 98 // Returns an error with the given messages and the range set to something 99 // that indicates this node. 100 virtual Err MakeErrorDescribing( 101 const std::string& msg, 102 const std::string& help = std::string()) const = 0; 103 104 // Generates a representation of this node in base::Value, to be used for 105 // exporting the tree as a JSON or formatted text with indents. 106 virtual base::Value GetJSONNode() const = 0; 107 comments()108 const Comments* comments() const { return comments_.get(); } 109 Comments* comments_mutable(); 110 111 protected: 112 // Helper functions for GetJSONNode. Creates and fills a Value object with 113 // given type (and value). 114 base::Value CreateJSONNode(const char* type) const; 115 base::Value CreateJSONNode(const char* type, 116 const std::string_view& value) const; 117 118 private: 119 // Helper function for CreateJSONNode. 120 void AddCommentsJSONNodes(base::Value* out_value) const; 121 122 std::unique_ptr<Comments> comments_; 123 124 DISALLOW_COPY_AND_ASSIGN(ParseNode); 125 }; 126 127 // AccessorNode ---------------------------------------------------------------- 128 129 // Access an array or scope element. 130 // 131 // Currently, such values are only read-only. In that you can do: 132 // a = obj1.a 133 // b = obj2[0] 134 // But not 135 // obj1.a = 5 136 // obj2[0] = 6 137 // 138 // In the current design where the dot operator is used only for templates, we 139 // explicitly don't want to allow you to do "invoker.foo = 5", so if we added 140 // support for accessors to be lvalues, we would also need to add some concept 141 // of a constant scope. Supporting this would also add a lot of complications 142 // to the operator= implementation, since some accessors might return values 143 // in the const root scope that shouldn't be modified. Without a strong 144 // use-case for this, it seems simpler to just disallow it. 145 // 146 // Additionally, the left-hand-side of the accessor must currently be an 147 // identifier. So you can't do things like: 148 // function_call()[1] 149 // a = b.c.d 150 // These are easier to implement if we needed them but given the very limited 151 // use cases for this, it hasn't seemed worth the bother. 152 class AccessorNode : public ParseNode { 153 public: 154 AccessorNode(); 155 ~AccessorNode() override; 156 157 const AccessorNode* AsAccessor() const override; 158 Value Execute(Scope* scope, Err* err) const override; 159 LocationRange GetRange() const override; 160 Err MakeErrorDescribing( 161 const std::string& msg, 162 const std::string& help = std::string()) const override; 163 base::Value GetJSONNode() const override; 164 165 // Base is the thing on the left of the [] or dot, currently always required 166 // to be an identifier token. base()167 const Token& base() const { return base_; } set_base(const Token & b)168 void set_base(const Token& b) { base_ = b; } 169 170 // Subscript is the expression inside the []. Will be null if member is set. subscript()171 const ParseNode* subscript() const { return subscript_.get(); } set_subscript(std::unique_ptr<ParseNode> key)172 void set_subscript(std::unique_ptr<ParseNode> key) { 173 subscript_ = std::move(key); 174 } 175 176 // The member is the identifier on the right hand side of the dot. Will be 177 // null if the index is set. member()178 const IdentifierNode* member() const { return member_.get(); } set_member(std::unique_ptr<IdentifierNode> i)179 void set_member(std::unique_ptr<IdentifierNode> i) { member_ = std::move(i); } 180 181 void SetNewLocation(int line_number); 182 183 // Evaluates the index for list accessor operations and range checks it 184 // against the max length of the list. If the index is OK, sets 185 // |*computed_index| and returns true. Otherwise sets the |*err| and returns 186 // false. 187 bool ComputeAndValidateListIndex(Scope* scope, 188 size_t max_len, 189 size_t* computed_index, 190 Err* err) const; 191 192 private: 193 Value ExecuteSubscriptAccess(Scope* scope, Err* err) const; 194 Value ExecuteArrayAccess(Scope* scope, 195 const Value* base_value, 196 Err* err) const; 197 Value ExecuteScopeSubscriptAccess(Scope* scope, 198 const Value* base_value, 199 Err* err) const; 200 Value ExecuteScopeAccess(Scope* scope, Err* err) const; 201 202 Token base_; 203 204 // Either index or member will be set according to what type of access this 205 // is. 206 std::unique_ptr<ParseNode> subscript_; 207 std::unique_ptr<IdentifierNode> member_; 208 209 DISALLOW_COPY_AND_ASSIGN(AccessorNode); 210 }; 211 212 // BinaryOpNode ---------------------------------------------------------------- 213 214 class BinaryOpNode : public ParseNode { 215 public: 216 BinaryOpNode(); 217 ~BinaryOpNode() override; 218 219 const BinaryOpNode* AsBinaryOp() const override; 220 Value Execute(Scope* scope, Err* err) const override; 221 LocationRange GetRange() const override; 222 Err MakeErrorDescribing( 223 const std::string& msg, 224 const std::string& help = std::string()) const override; 225 base::Value GetJSONNode() const override; 226 op()227 const Token& op() const { return op_; } set_op(const Token & t)228 void set_op(const Token& t) { op_ = t; } 229 left()230 const ParseNode* left() const { return left_.get(); } set_left(std::unique_ptr<ParseNode> left)231 void set_left(std::unique_ptr<ParseNode> left) { left_ = std::move(left); } 232 right()233 const ParseNode* right() const { return right_.get(); } set_right(std::unique_ptr<ParseNode> right)234 void set_right(std::unique_ptr<ParseNode> right) { 235 right_ = std::move(right); 236 } 237 238 private: 239 std::unique_ptr<ParseNode> left_; 240 Token op_; 241 std::unique_ptr<ParseNode> right_; 242 243 DISALLOW_COPY_AND_ASSIGN(BinaryOpNode); 244 }; 245 246 // BlockNode ------------------------------------------------------------------- 247 248 class BlockNode : public ParseNode { 249 public: 250 // How Execute manages the scopes and results. 251 enum ResultMode { 252 // Creates a new scope for the execution of this block and returns it as 253 // a Value from Execute(). 254 RETURNS_SCOPE, 255 256 // Executes in the context of the calling scope (variables set will go 257 // into the invoking scope) and Execute will return an empty Value. 258 DISCARDS_RESULT 259 }; 260 261 BlockNode(ResultMode result_mode); 262 ~BlockNode() override; 263 264 const BlockNode* AsBlock() const override; 265 Value Execute(Scope* scope, Err* err) const override; 266 LocationRange GetRange() const override; 267 Err MakeErrorDescribing( 268 const std::string& msg, 269 const std::string& help = std::string()) const override; 270 base::Value GetJSONNode() const override; 271 set_begin_token(const Token & t)272 void set_begin_token(const Token& t) { begin_token_ = t; } set_end(std::unique_ptr<EndNode> e)273 void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); } End()274 const EndNode* End() const { return end_.get(); } 275 result_mode()276 ResultMode result_mode() const { return result_mode_; } 277 statements()278 const std::vector<std::unique_ptr<ParseNode>>& statements() const { 279 return statements_; 280 } append_statement(std::unique_ptr<ParseNode> s)281 void append_statement(std::unique_ptr<ParseNode> s) { 282 statements_.push_back(std::move(s)); 283 } 284 285 private: 286 const ResultMode result_mode_; 287 288 // Tokens corresponding to { and }, if any (may be NULL). The end is stored 289 // in a custom parse node so that it can have comments hung off of it. 290 Token begin_token_; 291 std::unique_ptr<EndNode> end_; 292 293 std::vector<std::unique_ptr<ParseNode>> statements_; 294 295 DISALLOW_COPY_AND_ASSIGN(BlockNode); 296 }; 297 298 // ConditionNode --------------------------------------------------------------- 299 300 class ConditionNode : public ParseNode { 301 public: 302 ConditionNode(); 303 ~ConditionNode() override; 304 305 const ConditionNode* AsConditionNode() const override; 306 Value Execute(Scope* scope, Err* err) const override; 307 LocationRange GetRange() const override; 308 Err MakeErrorDescribing( 309 const std::string& msg, 310 const std::string& help = std::string()) const override; 311 base::Value GetJSONNode() const override; 312 set_if_token(const Token & token)313 void set_if_token(const Token& token) { if_token_ = token; } 314 condition()315 const ParseNode* condition() const { return condition_.get(); } set_condition(std::unique_ptr<ParseNode> c)316 void set_condition(std::unique_ptr<ParseNode> c) { 317 condition_ = std::move(c); 318 } 319 if_true()320 const BlockNode* if_true() const { return if_true_.get(); } set_if_true(std::unique_ptr<BlockNode> t)321 void set_if_true(std::unique_ptr<BlockNode> t) { if_true_ = std::move(t); } 322 323 // This is either empty, a block (for the else clause), or another 324 // condition. if_false()325 const ParseNode* if_false() const { return if_false_.get(); } set_if_false(std::unique_ptr<ParseNode> f)326 void set_if_false(std::unique_ptr<ParseNode> f) { if_false_ = std::move(f); } 327 328 private: 329 // Token corresponding to the "if" string. 330 Token if_token_; 331 332 std::unique_ptr<ParseNode> condition_; // Always non-null. 333 std::unique_ptr<BlockNode> if_true_; // Always non-null. 334 std::unique_ptr<ParseNode> if_false_; // May be null. 335 336 DISALLOW_COPY_AND_ASSIGN(ConditionNode); 337 }; 338 339 // FunctionCallNode ------------------------------------------------------------ 340 341 class FunctionCallNode : public ParseNode { 342 public: 343 FunctionCallNode(); 344 ~FunctionCallNode() override; 345 346 const FunctionCallNode* AsFunctionCall() const override; 347 Value Execute(Scope* scope, Err* err) const override; 348 LocationRange GetRange() const override; 349 Err MakeErrorDescribing( 350 const std::string& msg, 351 const std::string& help = std::string()) const override; 352 base::Value GetJSONNode() const override; 353 function()354 const Token& function() const { return function_; } set_function(Token t)355 void set_function(Token t) { function_ = t; } 356 args()357 const ListNode* args() const { return args_.get(); } set_args(std::unique_ptr<ListNode> a)358 void set_args(std::unique_ptr<ListNode> a) { args_ = std::move(a); } 359 block()360 const BlockNode* block() const { return block_.get(); } set_block(std::unique_ptr<BlockNode> b)361 void set_block(std::unique_ptr<BlockNode> b) { block_ = std::move(b); } 362 363 void SetNewLocation(int line_number); 364 365 private: 366 Token function_; 367 std::unique_ptr<ListNode> args_; 368 std::unique_ptr<BlockNode> block_; // May be null. 369 370 DISALLOW_COPY_AND_ASSIGN(FunctionCallNode); 371 }; 372 373 // IdentifierNode -------------------------------------------------------------- 374 375 class IdentifierNode : public ParseNode { 376 public: 377 IdentifierNode(); 378 explicit IdentifierNode(const Token& token); 379 ~IdentifierNode() override; 380 381 const IdentifierNode* AsIdentifier() const override; 382 Value Execute(Scope* scope, Err* err) const override; 383 LocationRange GetRange() const override; 384 Err MakeErrorDescribing( 385 const std::string& msg, 386 const std::string& help = std::string()) const override; 387 base::Value GetJSONNode() const override; 388 value()389 const Token& value() const { return value_; } set_value(const Token & t)390 void set_value(const Token& t) { value_ = t; } 391 392 void SetNewLocation(int line_number); 393 394 private: 395 Token value_; 396 397 DISALLOW_COPY_AND_ASSIGN(IdentifierNode); 398 }; 399 400 // ListNode -------------------------------------------------------------------- 401 402 class ListNode : public ParseNode { 403 public: 404 ListNode(); 405 ~ListNode() override; 406 407 const ListNode* AsList() const override; 408 Value Execute(Scope* scope, Err* err) const override; 409 LocationRange GetRange() const override; 410 Err MakeErrorDescribing( 411 const std::string& msg, 412 const std::string& help = std::string()) const override; 413 base::Value GetJSONNode() const override; 414 set_begin_token(const Token & t)415 void set_begin_token(const Token& t) { begin_token_ = t; } Begin()416 const Token& Begin() const { return begin_token_; } set_end(std::unique_ptr<EndNode> e)417 void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); } End()418 const EndNode* End() const { return end_.get(); } 419 append_item(std::unique_ptr<ParseNode> s)420 void append_item(std::unique_ptr<ParseNode> s) { 421 contents_.push_back(std::move(s)); 422 } contents()423 const std::vector<std::unique_ptr<const ParseNode>>& contents() const { 424 return contents_; 425 } 426 427 void SortAsStringsList(); 428 void SortAsDepsList(); 429 430 struct SortRange { 431 size_t begin; 432 size_t end; SortRangeSortRange433 SortRange(size_t begin, size_t end) : begin(begin), end(end) {} 434 }; 435 // Only public for testing. 436 std::vector<SortRange> GetSortRanges() const; 437 438 private: 439 template <typename Comparator> 440 void SortList(Comparator comparator); 441 442 // Tokens corresponding to the [ and ]. The end token is stored in inside an 443 // custom parse node so that it can have comments hung off of it. 444 Token begin_token_; 445 std::unique_ptr<EndNode> end_; 446 447 std::vector<std::unique_ptr<const ParseNode>> contents_; 448 449 DISALLOW_COPY_AND_ASSIGN(ListNode); 450 }; 451 452 // LiteralNode ----------------------------------------------------------------- 453 454 class LiteralNode : public ParseNode { 455 public: 456 LiteralNode(); 457 explicit LiteralNode(const Token& token); 458 ~LiteralNode() override; 459 460 const LiteralNode* AsLiteral() const override; 461 Value Execute(Scope* scope, Err* err) const override; 462 LocationRange GetRange() const override; 463 Err MakeErrorDescribing( 464 const std::string& msg, 465 const std::string& help = std::string()) const override; 466 base::Value GetJSONNode() const override; 467 value()468 const Token& value() const { return value_; } set_value(const Token & t)469 void set_value(const Token& t) { value_ = t; } 470 471 void SetNewLocation(int line_number); 472 473 private: 474 Token value_; 475 476 DISALLOW_COPY_AND_ASSIGN(LiteralNode); 477 }; 478 479 // UnaryOpNode ----------------------------------------------------------------- 480 481 class UnaryOpNode : public ParseNode { 482 public: 483 UnaryOpNode(); 484 ~UnaryOpNode() override; 485 486 const UnaryOpNode* AsUnaryOp() const override; 487 Value Execute(Scope* scope, Err* err) const override; 488 LocationRange GetRange() const override; 489 Err MakeErrorDescribing( 490 const std::string& msg, 491 const std::string& help = std::string()) const override; 492 base::Value GetJSONNode() const override; 493 op()494 const Token& op() const { return op_; } set_op(const Token & t)495 void set_op(const Token& t) { op_ = t; } 496 operand()497 const ParseNode* operand() const { return operand_.get(); } set_operand(std::unique_ptr<ParseNode> operand)498 void set_operand(std::unique_ptr<ParseNode> operand) { 499 operand_ = std::move(operand); 500 } 501 502 private: 503 Token op_; 504 std::unique_ptr<ParseNode> operand_; 505 506 DISALLOW_COPY_AND_ASSIGN(UnaryOpNode); 507 }; 508 509 // BlockCommentNode ------------------------------------------------------------ 510 511 // This node type is only used for standalone comments (that is, those not 512 // specifically attached to another syntax element. The most common of these 513 // is a standard header block. This node contains only the last line of such 514 // a comment block as the anchor, and other lines of the block comment are 515 // hung off of it as Before comments, similar to other syntax elements. 516 class BlockCommentNode : public ParseNode { 517 public: 518 BlockCommentNode(); 519 ~BlockCommentNode() override; 520 521 const BlockCommentNode* AsBlockComment() const override; 522 Value Execute(Scope* scope, Err* err) const override; 523 LocationRange GetRange() const override; 524 Err MakeErrorDescribing( 525 const std::string& msg, 526 const std::string& help = std::string()) const override; 527 base::Value GetJSONNode() const override; 528 comment()529 const Token& comment() const { return comment_; } set_comment(const Token & t)530 void set_comment(const Token& t) { comment_ = t; } 531 532 private: 533 Token comment_; 534 535 DISALLOW_COPY_AND_ASSIGN(BlockCommentNode); 536 }; 537 538 // EndNode --------------------------------------------------------------------- 539 540 // This node type is used as the end_ object for lists and blocks (rather than 541 // just the end ']', '}', or ')' token). This is so that during formatting 542 // traversal there is a node that appears at the end of the block to which 543 // comments can be attached. 544 class EndNode : public ParseNode { 545 public: 546 explicit EndNode(const Token& token); 547 ~EndNode() override; 548 549 const EndNode* AsEnd() const override; 550 Value Execute(Scope* scope, Err* err) const override; 551 LocationRange GetRange() const override; 552 Err MakeErrorDescribing( 553 const std::string& msg, 554 const std::string& help = std::string()) const override; 555 base::Value GetJSONNode() const override; 556 value()557 const Token& value() const { return value_; } set_value(const Token & t)558 void set_value(const Token& t) { value_ = t; } 559 560 private: 561 Token value_; 562 563 DISALLOW_COPY_AND_ASSIGN(EndNode); 564 }; 565 566 #endif // TOOLS_GN_PARSE_TREE_H_ 567