Add ICU message format support
[chromium-blink-merge.git] / tools / gn / parse_tree.h
blob90097529d4ad9d5f831ffc0b4e353b4f86d154d5
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.
5 #ifndef TOOLS_GN_PARSE_TREE_H_
6 #define TOOLS_GN_PARSE_TREE_H_
8 #include <vector>
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "tools/gn/err.h"
13 #include "tools/gn/token.h"
14 #include "tools/gn/value.h"
16 class AccessorNode;
17 class BinaryOpNode;
18 class BlockCommentNode;
19 class BlockNode;
20 class ConditionNode;
21 class EndNode;
22 class FunctionCallNode;
23 class IdentifierNode;
24 class ListNode;
25 class LiteralNode;
26 class Scope;
27 class UnaryOpNode;
29 class Comments {
30 public:
31 Comments();
32 virtual ~Comments();
34 const std::vector<Token>& before() const { return before_; }
35 void append_before(Token c) { before_.push_back(c); }
36 void clear_before() { before_.clear(); }
38 const std::vector<Token>& suffix() const { return suffix_; }
39 void append_suffix(Token c) { suffix_.push_back(c); }
40 // Reverse the order of the suffix comments. When walking the tree in
41 // post-order we append suffix comments in reverse order, so this fixes them
42 // up.
43 void ReverseSuffix();
45 const std::vector<Token>& after() const { return after_; }
46 void append_after(Token c) { after_.push_back(c); }
48 private:
49 // Whole line comments before the expression.
50 std::vector<Token> before_;
52 // End-of-line comments after this expression.
53 std::vector<Token> suffix_;
55 // For top-level expressions only, after_ lists whole-line comments
56 // following the expression.
57 std::vector<Token> after_;
59 DISALLOW_COPY_AND_ASSIGN(Comments);
62 // ParseNode -------------------------------------------------------------------
64 // A node in the AST.
65 class ParseNode {
66 public:
67 ParseNode();
68 virtual ~ParseNode();
70 virtual const AccessorNode* AsAccessor() const;
71 virtual const BinaryOpNode* AsBinaryOp() const;
72 virtual const BlockCommentNode* AsBlockComment() const;
73 virtual const BlockNode* AsBlock() const;
74 virtual const ConditionNode* AsConditionNode() const;
75 virtual const EndNode* AsEnd() const;
76 virtual const FunctionCallNode* AsFunctionCall() const;
77 virtual const IdentifierNode* AsIdentifier() const;
78 virtual const ListNode* AsList() const;
79 virtual const LiteralNode* AsLiteral() const;
80 virtual const UnaryOpNode* AsUnaryOp() const;
82 virtual Value Execute(Scope* scope, Err* err) const = 0;
84 virtual LocationRange GetRange() const = 0;
86 // Returns an error with the given messages and the range set to something
87 // that indicates this node.
88 virtual Err MakeErrorDescribing(
89 const std::string& msg,
90 const std::string& help = std::string()) const = 0;
92 // Prints a representation of this node to the given string, indenting
93 // by the given number of spaces.
94 virtual void Print(std::ostream& out, int indent) const = 0;
96 const Comments* comments() const { return comments_.get(); }
97 Comments* comments_mutable();
98 void PrintComments(std::ostream& out, int indent) const;
100 private:
101 scoped_ptr<Comments> comments_;
103 DISALLOW_COPY_AND_ASSIGN(ParseNode);
106 // AccessorNode ----------------------------------------------------------------
108 // Access an array or scope element.
110 // Currently, such values are only read-only. In that you can do:
111 // a = obj1.a
112 // b = obj2[0]
113 // But not
114 // obj1.a = 5
115 // obj2[0] = 6
117 // In the current design where the dot operator is used only for templates, we
118 // explicitly don't want to allow you to do "invoker.foo = 5", so if we added
119 // support for accessors to be lvalues, we would also need to add some concept
120 // of a constant scope. Supporting this would also add a lot of complications
121 // to the operator= implementation, since some accessors might return values
122 // in the const root scope that shouldn't be modified. Without a strong
123 // use-case for this, it seems simpler to just disallow it.
125 // Additionally, the left-hand-side of the accessor must currently be an
126 // identifier. So you can't do things like:
127 // function_call()[1]
128 // a = b.c.d
129 // These are easier to implement if we needed them but given the very limited
130 // use cases for this, it hasn't seemed worth the bother.
131 class AccessorNode : public ParseNode {
132 public:
133 AccessorNode();
134 ~AccessorNode() override;
136 const AccessorNode* AsAccessor() const override;
137 Value Execute(Scope* scope, Err* err) const override;
138 LocationRange GetRange() const override;
139 Err MakeErrorDescribing(
140 const std::string& msg,
141 const std::string& help = std::string()) const override;
142 void Print(std::ostream& out, int indent) const override;
144 // Base is the thing on the left of the [] or dot, currently always required
145 // to be an identifier token.
146 const Token& base() const { return base_; }
147 void set_base(const Token& b) { base_ = b; }
149 // Index is the expression inside the []. Will be null if member is set.
150 const ParseNode* index() const { return index_.get(); }
151 void set_index(scoped_ptr<ParseNode> i) { index_ = i.Pass(); }
153 // The member is the identifier on the right hand side of the dot. Will be
154 // null if the index is set.
155 const IdentifierNode* member() const { return member_.get(); }
156 void set_member(scoped_ptr<IdentifierNode> i) { member_ = i.Pass(); }
158 void SetNewLocation(int line_number);
160 private:
161 Value ExecuteArrayAccess(Scope* scope, Err* err) const;
162 Value ExecuteScopeAccess(Scope* scope, Err* err) const;
164 Token base_;
166 // Either index or member will be set according to what type of access this
167 // is.
168 scoped_ptr<ParseNode> index_;
169 scoped_ptr<IdentifierNode> member_;
171 DISALLOW_COPY_AND_ASSIGN(AccessorNode);
174 // BinaryOpNode ----------------------------------------------------------------
176 class BinaryOpNode : public ParseNode {
177 public:
178 BinaryOpNode();
179 ~BinaryOpNode() override;
181 const BinaryOpNode* AsBinaryOp() const override;
182 Value Execute(Scope* scope, Err* err) const override;
183 LocationRange GetRange() const override;
184 Err MakeErrorDescribing(
185 const std::string& msg,
186 const std::string& help = std::string()) const override;
187 void Print(std::ostream& out, int indent) const override;
189 const Token& op() const { return op_; }
190 void set_op(const Token& t) { op_ = t; }
192 const ParseNode* left() const { return left_.get(); }
193 void set_left(scoped_ptr<ParseNode> left) {
194 left_ = left.Pass();
197 const ParseNode* right() const { return right_.get(); }
198 void set_right(scoped_ptr<ParseNode> right) {
199 right_ = right.Pass();
202 private:
203 scoped_ptr<ParseNode> left_;
204 Token op_;
205 scoped_ptr<ParseNode> right_;
207 DISALLOW_COPY_AND_ASSIGN(BinaryOpNode);
210 // BlockNode -------------------------------------------------------------------
212 class BlockNode : public ParseNode {
213 public:
214 BlockNode();
215 ~BlockNode() override;
217 const BlockNode* AsBlock() const override;
218 Value Execute(Scope* scope, Err* err) const override;
219 LocationRange GetRange() const override;
220 Err MakeErrorDescribing(
221 const std::string& msg,
222 const std::string& help = std::string()) const override;
223 void Print(std::ostream& out, int indent) const override;
225 void set_begin_token(const Token& t) { begin_token_ = t; }
226 void set_end(scoped_ptr<EndNode> e) { end_ = e.Pass(); }
227 const EndNode* End() const { return end_.get(); }
229 const std::vector<ParseNode*>& statements() const { return statements_; }
230 void append_statement(scoped_ptr<ParseNode> s) {
231 statements_.push_back(s.release());
234 private:
235 // Tokens corresponding to { and }, if any (may be NULL). The end is stored
236 // in a custom parse node so that it can have comments hung off of it.
237 Token begin_token_;
238 scoped_ptr<EndNode> end_;
240 // Owning pointers, use unique_ptr when we can use C++11.
241 std::vector<ParseNode*> statements_;
243 DISALLOW_COPY_AND_ASSIGN(BlockNode);
246 // ConditionNode ---------------------------------------------------------------
248 class ConditionNode : public ParseNode {
249 public:
250 ConditionNode();
251 ~ConditionNode() override;
253 const ConditionNode* AsConditionNode() const override;
254 Value Execute(Scope* scope, Err* err) const override;
255 LocationRange GetRange() const override;
256 Err MakeErrorDescribing(
257 const std::string& msg,
258 const std::string& help = std::string()) const override;
259 void Print(std::ostream& out, int indent) const override;
261 void set_if_token(const Token& token) { if_token_ = token; }
263 const ParseNode* condition() const { return condition_.get(); }
264 void set_condition(scoped_ptr<ParseNode> c) {
265 condition_ = c.Pass();
268 const BlockNode* if_true() const { return if_true_.get(); }
269 void set_if_true(scoped_ptr<BlockNode> t) {
270 if_true_ = t.Pass();
273 // This is either empty, a block (for the else clause), or another
274 // condition.
275 const ParseNode* if_false() const { return if_false_.get(); }
276 void set_if_false(scoped_ptr<ParseNode> f) {
277 if_false_ = f.Pass();
280 private:
281 // Token corresponding to the "if" string.
282 Token if_token_;
284 scoped_ptr<ParseNode> condition_; // Always non-null.
285 scoped_ptr<BlockNode> if_true_; // Always non-null.
286 scoped_ptr<ParseNode> if_false_; // May be null.
288 DISALLOW_COPY_AND_ASSIGN(ConditionNode);
291 // FunctionCallNode ------------------------------------------------------------
293 class FunctionCallNode : public ParseNode {
294 public:
295 FunctionCallNode();
296 ~FunctionCallNode() override;
298 const FunctionCallNode* AsFunctionCall() const override;
299 Value Execute(Scope* scope, Err* err) const override;
300 LocationRange GetRange() const override;
301 Err MakeErrorDescribing(
302 const std::string& msg,
303 const std::string& help = std::string()) const override;
304 void Print(std::ostream& out, int indent) const override;
306 const Token& function() const { return function_; }
307 void set_function(Token t) { function_ = t; }
309 const ListNode* args() const { return args_.get(); }
310 void set_args(scoped_ptr<ListNode> a) { args_ = a.Pass(); }
312 const BlockNode* block() const { return block_.get(); }
313 void set_block(scoped_ptr<BlockNode> b) { block_ = b.Pass(); }
315 private:
316 Token function_;
317 scoped_ptr<ListNode> args_;
318 scoped_ptr<BlockNode> block_; // May be null.
320 DISALLOW_COPY_AND_ASSIGN(FunctionCallNode);
323 // IdentifierNode --------------------------------------------------------------
325 class IdentifierNode : public ParseNode {
326 public:
327 IdentifierNode();
328 explicit IdentifierNode(const Token& token);
329 ~IdentifierNode() override;
331 const IdentifierNode* AsIdentifier() 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 void Print(std::ostream& out, int indent) const override;
339 const Token& value() const { return value_; }
340 void set_value(const Token& t) { value_ = t; }
342 void SetNewLocation(int line_number);
344 private:
345 Token value_;
347 DISALLOW_COPY_AND_ASSIGN(IdentifierNode);
350 // ListNode --------------------------------------------------------------------
352 class ListNode : public ParseNode {
353 public:
354 ListNode();
355 ~ListNode() override;
357 const ListNode* AsList() const override;
358 Value Execute(Scope* scope, Err* err) const override;
359 LocationRange GetRange() const override;
360 Err MakeErrorDescribing(
361 const std::string& msg,
362 const std::string& help = std::string()) const override;
363 void Print(std::ostream& out, int indent) const override;
365 void set_begin_token(const Token& t) { begin_token_ = t; }
366 void set_end(scoped_ptr<EndNode> e) { end_ = e.Pass(); }
367 const EndNode* End() const { return end_.get(); }
369 void append_item(scoped_ptr<ParseNode> s) {
370 contents_.push_back(s.release());
372 const std::vector<const ParseNode*>& contents() const { return contents_; }
374 void SortAsStringsList();
376 // During formatting, do we want this list to always be multliline? This is
377 // used to make assignments to deps, sources, etc. always be multiline lists,
378 // rather than collapsed to a single line when they're one element.
379 bool prefer_multiline() const { return prefer_multiline_; }
380 void set_prefer_multiline(bool prefer_multiline) {
381 prefer_multiline_ = prefer_multiline;
384 struct SortRange {
385 size_t begin;
386 size_t end;
387 SortRange(size_t begin, size_t end) : begin(begin), end(end) {}
389 // Only public for testing.
390 std::vector<SortRange> GetSortRanges() const;
392 private:
393 // Tokens corresponding to the [ and ]. The end token is stored in inside an
394 // custom parse node so that it can have comments hung off of it.
395 Token begin_token_;
396 scoped_ptr<EndNode> end_;
397 bool prefer_multiline_;
399 // Owning pointers, use unique_ptr when we can use C++11.
400 std::vector<const ParseNode*> contents_;
402 DISALLOW_COPY_AND_ASSIGN(ListNode);
405 // LiteralNode -----------------------------------------------------------------
407 class LiteralNode : public ParseNode {
408 public:
409 LiteralNode();
410 explicit LiteralNode(const Token& token);
411 ~LiteralNode() override;
413 const LiteralNode* AsLiteral() const override;
414 Value Execute(Scope* scope, Err* err) const override;
415 LocationRange GetRange() const override;
416 Err MakeErrorDescribing(
417 const std::string& msg,
418 const std::string& help = std::string()) const override;
419 void Print(std::ostream& out, int indent) const override;
421 const Token& value() const { return value_; }
422 void set_value(const Token& t) { value_ = t; }
424 void SetNewLocation(int line_number);
426 private:
427 Token value_;
429 DISALLOW_COPY_AND_ASSIGN(LiteralNode);
432 // UnaryOpNode -----------------------------------------------------------------
434 class UnaryOpNode : public ParseNode {
435 public:
436 UnaryOpNode();
437 ~UnaryOpNode() override;
439 const UnaryOpNode* AsUnaryOp() const override;
440 Value Execute(Scope* scope, Err* err) const override;
441 LocationRange GetRange() const override;
442 Err MakeErrorDescribing(
443 const std::string& msg,
444 const std::string& help = std::string()) const override;
445 void Print(std::ostream& out, int indent) const override;
447 const Token& op() const { return op_; }
448 void set_op(const Token& t) { op_ = t; }
450 const ParseNode* operand() const { return operand_.get(); }
451 void set_operand(scoped_ptr<ParseNode> operand) {
452 operand_ = operand.Pass();
455 private:
456 Token op_;
457 scoped_ptr<ParseNode> operand_;
459 DISALLOW_COPY_AND_ASSIGN(UnaryOpNode);
462 // BlockCommentNode ------------------------------------------------------------
464 // This node type is only used for standalone comments (that is, those not
465 // specifically attached to another syntax element. The most common of these
466 // is a standard header block. This node contains only the last line of such
467 // a comment block as the anchor, and other lines of the block comment are
468 // hung off of it as Before comments, similar to other syntax elements.
469 class BlockCommentNode : public ParseNode {
470 public:
471 BlockCommentNode();
472 ~BlockCommentNode() override;
474 const BlockCommentNode* AsBlockComment() const override;
475 Value Execute(Scope* scope, Err* err) const override;
476 LocationRange GetRange() const override;
477 Err MakeErrorDescribing(
478 const std::string& msg,
479 const std::string& help = std::string()) const override;
480 void Print(std::ostream& out, int indent) const override;
482 const Token& comment() const { return comment_; }
483 void set_comment(const Token& t) { comment_ = t; }
485 private:
486 Token comment_;
488 DISALLOW_COPY_AND_ASSIGN(BlockCommentNode);
491 // EndNode ---------------------------------------------------------------------
493 // This node type is used as the end_ object for lists and blocks (rather than
494 // just the end ']', '}', or ')' token). This is so that during formatting
495 // traversal there is a node that appears at the end of the block to which
496 // comments can be attached.
497 class EndNode : public ParseNode {
498 public:
499 explicit EndNode(const Token& token);
500 ~EndNode() override;
502 const EndNode* AsEnd() const override;
503 Value Execute(Scope* scope, Err* err) const override;
504 LocationRange GetRange() const override;
505 Err MakeErrorDescribing(
506 const std::string& msg,
507 const std::string& help = std::string()) const override;
508 void Print(std::ostream& out, int indent) const override;
510 const Token& value() const { return value_; }
511 void set_value(const Token& t) { value_ = t; }
513 private:
514 Token value_;
516 DISALLOW_COPY_AND_ASSIGN(EndNode);
519 #endif // TOOLS_GN_PARSE_TREE_H_