• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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