• 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 <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