• 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 
210   static constexpr const char* kDumpAccessorKind = "accessor_kind";
211   static constexpr const char* kDumpAccessorKindSubscript = "subscript";
212   static constexpr const char* kDumpAccessorKindMember = "member";
213 
214   Token base_;
215 
216   // Either index or member will be set according to what type of access this
217   // is.
218   std::unique_ptr<ParseNode> subscript_;
219   std::unique_ptr<IdentifierNode> member_;
220 
221   AccessorNode(const AccessorNode&) = delete;
222   AccessorNode& operator=(const AccessorNode&) = delete;
223 };
224 
225 // BinaryOpNode ----------------------------------------------------------------
226 
227 class BinaryOpNode : public ParseNode {
228  public:
229   BinaryOpNode();
230   ~BinaryOpNode() override;
231 
232   const BinaryOpNode* AsBinaryOp() const override;
233   Value Execute(Scope* scope, Err* err) const override;
234   LocationRange GetRange() const override;
235   Err MakeErrorDescribing(
236       const std::string& msg,
237       const std::string& help = std::string()) const override;
238   base::Value GetJSONNode() const override;
239   static std::unique_ptr<BinaryOpNode> NewFromJSON(const base::Value& value);
240 
op()241   const Token& op() const { return op_; }
set_op(const Token & t)242   void set_op(const Token& t) { op_ = t; }
243 
left()244   const ParseNode* left() const { return left_.get(); }
set_left(std::unique_ptr<ParseNode> left)245   void set_left(std::unique_ptr<ParseNode> left) { left_ = std::move(left); }
246 
right()247   const ParseNode* right() const { return right_.get(); }
set_right(std::unique_ptr<ParseNode> right)248   void set_right(std::unique_ptr<ParseNode> right) {
249     right_ = std::move(right);
250   }
251 
252   static constexpr const char* kDumpNodeName = "BINARY";
253 
254  private:
255   std::unique_ptr<ParseNode> left_;
256   Token op_;
257   std::unique_ptr<ParseNode> right_;
258 
259   BinaryOpNode(const BinaryOpNode&) = delete;
260   BinaryOpNode& operator=(const BinaryOpNode&) = delete;
261 };
262 
263 // BlockNode -------------------------------------------------------------------
264 
265 class BlockNode : public ParseNode {
266  public:
267   // How Execute manages the scopes and results.
268   enum ResultMode {
269     // Creates a new scope for the execution of this block and returns it as
270     // a Value from Execute().
271     RETURNS_SCOPE,
272 
273     // Executes in the context of the calling scope (variables set will go
274     // into the invoking scope) and Execute will return an empty Value.
275     DISCARDS_RESULT
276   };
277 
278   BlockNode(ResultMode result_mode);
279   ~BlockNode() override;
280 
281   const BlockNode* AsBlock() const override;
282   Value Execute(Scope* scope, Err* err) const override;
283   LocationRange GetRange() const override;
284   Err MakeErrorDescribing(
285       const std::string& msg,
286       const std::string& help = std::string()) const override;
287   base::Value GetJSONNode() const override;
288   static std::unique_ptr<BlockNode> NewFromJSON(const base::Value& value);
289 
set_begin_token(const Token & t)290   void set_begin_token(const Token& t) { begin_token_ = t; }
set_end(std::unique_ptr<EndNode> e)291   void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); }
End()292   const EndNode* End() const { return end_.get(); }
293 
result_mode()294   ResultMode result_mode() const { return result_mode_; }
295 
statements()296   const std::vector<std::unique_ptr<ParseNode>>& statements() const {
297     return statements_;
298   }
append_statement(std::unique_ptr<ParseNode> s)299   void append_statement(std::unique_ptr<ParseNode> s) {
300     statements_.push_back(std::move(s));
301   }
302 
303   static constexpr const char* kDumpNodeName = "BLOCK";
304 
305  private:
306   static constexpr const char* kDumpResultMode = "result_mode";
307   static constexpr const char* kDumpResultModeReturnsScope = "returns_scope";
308   static constexpr const char* kDumpResultModeDiscardsResult =
309       "discards_result";
310 
311   const ResultMode result_mode_;
312 
313   // Tokens corresponding to { and }, if any (may be NULL). The end is stored
314   // in a custom parse node so that it can have comments hung off of it.
315   Token begin_token_;
316   std::unique_ptr<EndNode> end_;
317 
318   std::vector<std::unique_ptr<ParseNode>> statements_;
319 
320   BlockNode(const BlockNode&) = delete;
321   BlockNode& operator=(const BlockNode&) = delete;
322 };
323 
324 // ConditionNode ---------------------------------------------------------------
325 
326 class ConditionNode : public ParseNode {
327  public:
328   ConditionNode();
329   ~ConditionNode() override;
330 
331   const ConditionNode* AsCondition() const override;
332   Value Execute(Scope* scope, Err* err) const override;
333   LocationRange GetRange() const override;
334   Err MakeErrorDescribing(
335       const std::string& msg,
336       const std::string& help = std::string()) const override;
337   base::Value GetJSONNode() const override;
338   static std::unique_ptr<ConditionNode> NewFromJSON(const base::Value& value);
339 
set_if_token(const Token & token)340   void set_if_token(const Token& token) { if_token_ = token; }
341 
condition()342   const ParseNode* condition() const { return condition_.get(); }
set_condition(std::unique_ptr<ParseNode> c)343   void set_condition(std::unique_ptr<ParseNode> c) {
344     condition_ = std::move(c);
345   }
346 
if_true()347   const BlockNode* if_true() const { return if_true_.get(); }
set_if_true(std::unique_ptr<BlockNode> t)348   void set_if_true(std::unique_ptr<BlockNode> t) { if_true_ = std::move(t); }
349 
350   // This is either empty, a block (for the else clause), or another
351   // condition.
if_false()352   const ParseNode* if_false() const { return if_false_.get(); }
set_if_false(std::unique_ptr<ParseNode> f)353   void set_if_false(std::unique_ptr<ParseNode> f) { if_false_ = std::move(f); }
354 
355   static constexpr const char* kDumpNodeName = "CONDITION";
356 
357  private:
358   // Token corresponding to the "if" string.
359   Token if_token_;
360 
361   std::unique_ptr<ParseNode> condition_;  // Always non-null.
362   std::unique_ptr<BlockNode> if_true_;    // Always non-null.
363   std::unique_ptr<ParseNode> if_false_;   // May be null.
364 
365   ConditionNode(const ConditionNode&) = delete;
366   ConditionNode& operator=(const ConditionNode&) = delete;
367 };
368 
369 // FunctionCallNode ------------------------------------------------------------
370 
371 class FunctionCallNode : public ParseNode {
372  public:
373   FunctionCallNode();
374   ~FunctionCallNode() override;
375 
376   const FunctionCallNode* AsFunctionCall() const override;
377   Value Execute(Scope* scope, Err* err) const override;
378   LocationRange GetRange() const override;
379   Err MakeErrorDescribing(
380       const std::string& msg,
381       const std::string& help = std::string()) const override;
382   base::Value GetJSONNode() const override;
383   static std::unique_ptr<FunctionCallNode> NewFromJSON(
384       const base::Value& value);
385 
function()386   const Token& function() const { return function_; }
set_function(Token t)387   void set_function(Token t) { function_ = t; }
388 
args()389   const ListNode* args() const { return args_.get(); }
set_args(std::unique_ptr<ListNode> a)390   void set_args(std::unique_ptr<ListNode> a) { args_ = std::move(a); }
391 
block()392   const BlockNode* block() const { return block_.get(); }
set_block(std::unique_ptr<BlockNode> b)393   void set_block(std::unique_ptr<BlockNode> b) { block_ = std::move(b); }
394 
395   void SetNewLocation(int line_number);
396 
397   static constexpr const char* kDumpNodeName = "FUNCTION";
398 
399  private:
400   Token function_;
401   std::unique_ptr<ListNode> args_;
402   std::unique_ptr<BlockNode> block_;  // May be null.
403 
404   FunctionCallNode(const FunctionCallNode&) = delete;
405   FunctionCallNode& operator=(const FunctionCallNode&) = delete;
406 };
407 
408 // IdentifierNode --------------------------------------------------------------
409 
410 class IdentifierNode : public ParseNode {
411  public:
412   IdentifierNode();
413   explicit IdentifierNode(const Token& token);
414   ~IdentifierNode() override;
415 
416   const IdentifierNode* AsIdentifier() const override;
417   Value Execute(Scope* scope, Err* err) const override;
418   LocationRange GetRange() const override;
419   Err MakeErrorDescribing(
420       const std::string& msg,
421       const std::string& help = std::string()) const override;
422   base::Value GetJSONNode() const override;
423   static std::unique_ptr<IdentifierNode> NewFromJSON(const base::Value& value);
424 
value()425   const Token& value() const { return value_; }
set_value(const Token & t)426   void set_value(const Token& t) { value_ = t; }
427 
428   void SetNewLocation(int line_number);
429 
430   static constexpr const char* kDumpNodeName = "IDENTIFIER";
431 
432  private:
433   Token value_;
434 
435   IdentifierNode(const IdentifierNode&) = delete;
436   IdentifierNode& operator=(const IdentifierNode&) = delete;
437 };
438 
439 // ListNode --------------------------------------------------------------------
440 
441 class ListNode : public ParseNode {
442  public:
443   ListNode();
444   ~ListNode() override;
445 
446   const ListNode* AsList() const override;
447   Value Execute(Scope* scope, Err* err) const override;
448   LocationRange GetRange() const override;
449   Err MakeErrorDescribing(
450       const std::string& msg,
451       const std::string& help = std::string()) const override;
452   base::Value GetJSONNode() const override;
453   static std::unique_ptr<ListNode> NewFromJSON(const base::Value& value);
454 
set_begin_token(const Token & t)455   void set_begin_token(const Token& t) { begin_token_ = t; }
Begin()456   const Token& Begin() const { return begin_token_; }
set_end(std::unique_ptr<EndNode> e)457   void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); }
End()458   const EndNode* End() const { return end_.get(); }
459 
append_item(std::unique_ptr<ParseNode> s)460   void append_item(std::unique_ptr<ParseNode> s) {
461     contents_.push_back(std::move(s));
462   }
contents()463   const std::vector<std::unique_ptr<const ParseNode>>& contents() const {
464     return contents_;
465   }
466 
467   void SortAsStringsList();
468   void SortAsTargetsList();
469 
470   struct SortRange {
471     size_t begin;
472     size_t end;
SortRangeSortRange473     SortRange(size_t begin, size_t end) : begin(begin), end(end) {}
474   };
475   // Only public for testing.
476   std::vector<SortRange> GetSortRanges() const;
477 
478   static constexpr const char* kDumpNodeName = "LIST";
479 
480  private:
481   template <typename Comparator>
482   void SortList(Comparator comparator);
483 
484   // Tokens corresponding to the [ and ]. The end token is stored in inside an
485   // custom parse node so that it can have comments hung off of it.
486   Token begin_token_;
487   std::unique_ptr<EndNode> end_;
488 
489   std::vector<std::unique_ptr<const ParseNode>> contents_;
490 
491   ListNode(const ListNode&) = delete;
492   ListNode& operator=(const ListNode&) = delete;
493 };
494 
495 // LiteralNode -----------------------------------------------------------------
496 
497 class LiteralNode : public ParseNode {
498  public:
499   LiteralNode();
500   explicit LiteralNode(const Token& token);
501   ~LiteralNode() override;
502 
503   const LiteralNode* AsLiteral() const override;
504   Value Execute(Scope* scope, Err* err) const override;
505   LocationRange GetRange() const override;
506   Err MakeErrorDescribing(
507       const std::string& msg,
508       const std::string& help = std::string()) const override;
509   base::Value GetJSONNode() const override;
510   static std::unique_ptr<LiteralNode> NewFromJSON(const base::Value& value);
511 
value()512   const Token& value() const { return value_; }
set_value(const Token & t)513   void set_value(const Token& t) { value_ = t; }
514 
515   void SetNewLocation(int line_number);
516 
517   static constexpr const char* kDumpNodeName = "LITERAL";
518 
519  private:
520   Token value_;
521 
522   LiteralNode(const LiteralNode&) = delete;
523   LiteralNode& operator=(const LiteralNode&) = delete;
524 };
525 
526 // UnaryOpNode -----------------------------------------------------------------
527 
528 class UnaryOpNode : public ParseNode {
529  public:
530   UnaryOpNode();
531   ~UnaryOpNode() override;
532 
533   const UnaryOpNode* AsUnaryOp() const override;
534   Value Execute(Scope* scope, Err* err) const override;
535   LocationRange GetRange() const override;
536   Err MakeErrorDescribing(
537       const std::string& msg,
538       const std::string& help = std::string()) const override;
539   base::Value GetJSONNode() const override;
540   static std::unique_ptr<UnaryOpNode> NewFromJSON(const base::Value& value);
541 
op()542   const Token& op() const { return op_; }
set_op(const Token & t)543   void set_op(const Token& t) { op_ = t; }
544 
operand()545   const ParseNode* operand() const { return operand_.get(); }
set_operand(std::unique_ptr<ParseNode> operand)546   void set_operand(std::unique_ptr<ParseNode> operand) {
547     operand_ = std::move(operand);
548   }
549 
550   static constexpr const char* kDumpNodeName = "UNARY";
551 
552  private:
553   Token op_;
554   std::unique_ptr<ParseNode> operand_;
555 
556   UnaryOpNode(const UnaryOpNode&) = delete;
557   UnaryOpNode& operator=(const UnaryOpNode&) = delete;
558 };
559 
560 // BlockCommentNode ------------------------------------------------------------
561 
562 // This node type is only used for standalone comments (that is, those not
563 // specifically attached to another syntax element. The most common of these
564 // is a standard header block. This node contains only the last line of such
565 // a comment block as the anchor, and other lines of the block comment are
566 // hung off of it as Before comments, similar to other syntax elements.
567 class BlockCommentNode : public ParseNode {
568  public:
569   BlockCommentNode();
570   ~BlockCommentNode() override;
571 
572   const BlockCommentNode* AsBlockComment() const override;
573   Value Execute(Scope* scope, Err* err) const override;
574   LocationRange GetRange() const override;
575   Err MakeErrorDescribing(
576       const std::string& msg,
577       const std::string& help = std::string()) const override;
578   base::Value GetJSONNode() const override;
579   static std::unique_ptr<BlockCommentNode> NewFromJSON(
580       const base::Value& value);
581 
comment()582   const Token& comment() const { return comment_; }
set_comment(const Token & t)583   void set_comment(const Token& t) { comment_ = t; }
584 
585   static constexpr const char* kDumpNodeName = "BLOCK_COMMENT";
586 
587  private:
588   Token comment_;
589 
590   BlockCommentNode(const BlockCommentNode&) = delete;
591   BlockCommentNode& operator=(const BlockCommentNode&) = delete;
592 };
593 
594 // EndNode ---------------------------------------------------------------------
595 
596 // This node type is used as the end_ object for lists and blocks (rather than
597 // just the end ']', '}', or ')' token). This is so that during formatting
598 // traversal there is a node that appears at the end of the block to which
599 // comments can be attached.
600 class EndNode : public ParseNode {
601  public:
602   explicit EndNode(const Token& token);
603   ~EndNode() override;
604 
605   const EndNode* AsEnd() const override;
606   Value Execute(Scope* scope, Err* err) const override;
607   LocationRange GetRange() const override;
608   Err MakeErrorDescribing(
609       const std::string& msg,
610       const std::string& help = std::string()) const override;
611   base::Value GetJSONNode() const override;
612   static std::unique_ptr<EndNode> NewFromJSON(const base::Value& value);
613 
value()614   const Token& value() const { return value_; }
set_value(const Token & t)615   void set_value(const Token& t) { value_ = t; }
616 
617   static constexpr const char* kDumpNodeName = "END";
618 
619  private:
620   Token value_;
621 
622   EndNode(const EndNode&) = delete;
623   EndNode& operator=(const EndNode&) = delete;
624 };
625 
626 #endif  // TOOLS_GN_PARSE_TREE_H_
627