1 //===--- Forest.h - Parse forest, the output of the GLR parser ---*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // A parse forest represents a set of possible parse trees efficiently, it is
10 // produced by the GLR parser.
11 //
12 // Despite the name, its data structure is a tree-like DAG with a single root.
13 // Multiple ways to parse the same tokens are presented as an ambiguous node
14 // with all possible interpretations as children.
15 // Common sub-parses are shared: if two interpretations both parse "1 + 1" as
16 // "expr := expr + expr", they will share a Sequence node representing the expr.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #ifndef CLANG_PSEUDO_FOREST_H
21 #define CLANG_PSEUDO_FOREST_H
22 
23 #include "clang-pseudo/Token.h"
24 #include "clang-pseudo/grammar/Grammar.h"
25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/STLExtras.h"
27 #include "llvm/Support/Allocator.h"
28 #include <cstdint>
29 
30 namespace clang {
31 namespace pseudo {
32 
33 // A node represents ways to parse a sequence of tokens, it interprets a fixed
34 // range of tokens as a fixed grammar symbol.
35 //
36 // There are different kinds of nodes, some nodes have "children" (stored in a
37 // trailing array) and have pointers to them. "Children" has different semantics
38 // depending on the node kinds. For an Ambiguous node, it means all
39 // possible interpretations; for a Sequence node, it means each symbol on the
40 // right hand side of the production rule.
41 //
42 // Since this is a node in a DAG, a node may have multiple parents. And a node
43 // doesn't have parent pointers.
alignas(class ForestNode *)44 class alignas(class ForestNode *) ForestNode {
45 public:
46   class RecursiveIterator;
47   enum Kind {
48     // A Terminal node is a single terminal symbol bound to a token.
49     Terminal,
50     // A Sequence node is a nonterminal symbol parsed from a grammar rule,
51     // elements() are the parses of each symbol on the RHS of the rule.
52     // If the rule is A := X Y Z, the node is for nonterminal A, and elements()
53     // are [X, Y, Z].
54     Sequence,
55     // An Ambiguous node exposes multiple ways to interpret the code as the
56     // same symbol, alternatives() are all possible parses.
57     Ambiguous,
58     // An Opaque node is a placeholder. It asserts that tokens match a symbol,
59     // without saying how.
60     // It is used for lazy-parsing (not parsed yet), or error-recovery (invalid
61     // code).
62     Opaque,
63   };
64   Kind kind() const { return K; }
65 
66   SymbolID symbol() const { return Symbol; }
67 
68   // The start of the token range, it is a poistion within a token stream.
69   Token::Index startTokenIndex() const { return StartIndex; }
70 
71   // Returns the corresponding grammar rule.
72   // REQUIRES: this is a Sequence node.
73   RuleID rule() const {
74     assert(kind() == Sequence);
75     return Data & ((1 << RuleBits) - 1);
76   }
77   // Returns the parses of each element on the RHS of the rule.
78   // REQUIRES: this is a Sequence node;
79   llvm::ArrayRef<const ForestNode *> elements() const {
80     assert(kind() == Sequence);
81     return children(Data >> RuleBits);
82   };
83 
84   // Returns all possible interpretations of the code.
85   // REQUIRES: this is an Ambiguous node.
86   llvm::ArrayRef<const ForestNode *> alternatives() const {
87     assert(kind() == Ambiguous);
88     return children(Data);
89   }
90 
91   llvm::ArrayRef<const ForestNode *> children() const {
92     switch (kind()) {
93     case Sequence:
94       return elements();
95     case Ambiguous:
96       return alternatives();
97     case Terminal:
98     case Opaque:
99       return {};
100     }
101     llvm_unreachable("Bad kind");
102   }
103 
104   // Iteration over all nodes in the forest, including this.
105   llvm::iterator_range<RecursiveIterator> descendants() const;
106 
107   std::string dump(const Grammar &) const;
108   std::string dumpRecursive(const Grammar &, bool Abbreviated = false) const;
109 
110 private:
111   friend class ForestArena;
112 
113   ForestNode(Kind K, SymbolID Symbol, Token::Index StartIndex, uint16_t Data)
114       : StartIndex(StartIndex), K(K), Symbol(Symbol), Data(Data) {}
115 
116   ForestNode(const ForestNode &) = delete;
117   ForestNode &operator=(const ForestNode &) = delete;
118   ForestNode(ForestNode &&) = delete;
119   ForestNode &operator=(ForestNode &&) = delete;
120 
121   static uint16_t sequenceData(RuleID Rule,
122                                llvm::ArrayRef<const ForestNode *> Elements) {
123     assert(Rule < (1 << RuleBits));
124     assert(Elements.size() < (1 << (16 - RuleBits)));
125     return Rule | Elements.size() << RuleBits;
126   }
127   static uint16_t
128   ambiguousData(llvm::ArrayRef<const ForestNode *> Alternatives) {
129     return Alternatives.size();
130   }
131 
132   // Retrieves the trailing array.
133   llvm::ArrayRef<const ForestNode *> children(uint16_t Num) const {
134     return llvm::makeArrayRef(reinterpret_cast<ForestNode *const *>(this + 1),
135                               Num);
136   }
137 
138   Token::Index StartIndex;
139   Kind K : 4;
140   SymbolID Symbol : SymbolBits;
141   // Sequence - child count : 4 | RuleID : RuleBits (12)
142   // Ambiguous - child count : 16
143   // Terminal, Opaque - unused
144   uint16_t Data;
145   // An array of ForestNode* following the object.
146 };
147 // ForestNode may not be destroyed (for BumpPtrAllocator).
148 static_assert(std::is_trivially_destructible<ForestNode>(), "");
149 
150 // A memory arena for the parse forest.
151 class ForestArena {
152 public:
153   llvm::ArrayRef<ForestNode> createTerminals(const TokenStream &Code);
createSequence(SymbolID SID,RuleID RID,llvm::ArrayRef<const ForestNode * > Elements)154   ForestNode &createSequence(SymbolID SID, RuleID RID,
155                              llvm::ArrayRef<const ForestNode *> Elements) {
156     assert(!Elements.empty());
157     return create(ForestNode::Sequence, SID,
158                   Elements.front()->startTokenIndex(),
159                   ForestNode::sequenceData(RID, Elements), Elements);
160   }
createAmbiguous(SymbolID SID,llvm::ArrayRef<const ForestNode * > Alternatives)161   ForestNode &createAmbiguous(SymbolID SID,
162                               llvm::ArrayRef<const ForestNode *> Alternatives) {
163     assert(!Alternatives.empty());
164     assert(llvm::all_of(Alternatives,
165                         [SID](const ForestNode *Alternative) {
166                           return SID == Alternative->symbol();
167                         }) &&
168            "Ambiguous alternatives must represent the same symbol!");
169     return create(ForestNode::Ambiguous, SID,
170                   Alternatives.front()->startTokenIndex(),
171                   ForestNode::ambiguousData(Alternatives), Alternatives);
172   }
createOpaque(SymbolID SID,Token::Index Start)173   ForestNode &createOpaque(SymbolID SID, Token::Index Start) {
174     return create(ForestNode::Opaque, SID, Start, 0, {});
175   }
176 
createTerminal(tok::TokenKind TK,Token::Index Start)177   ForestNode &createTerminal(tok::TokenKind TK, Token::Index Start) {
178     return create(ForestNode::Terminal, tokenSymbol(TK), Start, 0, {});
179   }
180 
nodeCount()181   size_t nodeCount() const { return NodeCount; }
bytes()182   size_t bytes() const { return Arena.getBytesAllocated() + sizeof(this); }
183 
184 private:
create(ForestNode::Kind K,SymbolID SID,Token::Index Start,uint16_t Data,llvm::ArrayRef<const ForestNode * > Elements)185   ForestNode &create(ForestNode::Kind K, SymbolID SID, Token::Index Start,
186                      uint16_t Data,
187                      llvm::ArrayRef<const ForestNode *> Elements) {
188     ++NodeCount;
189     ForestNode *New = new (Arena.Allocate(
190         sizeof(ForestNode) + Elements.size() * sizeof(ForestNode *),
191         alignof(ForestNode))) ForestNode(K, SID, Start, Data);
192     if (!Elements.empty())
193       llvm::copy(Elements, reinterpret_cast<const ForestNode **>(New + 1));
194     return *New;
195   }
196 
197   llvm::BumpPtrAllocator Arena;
198   uint32_t NodeCount = 0;
199 };
200 
201 class ForestNode::RecursiveIterator
202     : public std::iterator<std::input_iterator_tag, const ForestNode> {
203   llvm::DenseSet<const ForestNode *> Seen;
204   struct StackFrame {
205     const ForestNode *Parent;
206     unsigned ChildIndex;
207   };
208   std::vector<StackFrame> Stack;
209   const ForestNode *Cur;
210 
211 public:
Cur(N)212   RecursiveIterator(const ForestNode *N = nullptr) : Cur(N) {}
213 
214   const ForestNode &operator*() const { return *Cur; };
215   void operator++();
216   bool operator==(const RecursiveIterator &I) const { return Cur == I.Cur; }
217   bool operator!=(const RecursiveIterator &I) const { return !(*this == I); }
218 };
219 
220 } // namespace pseudo
221 } // namespace clang
222 
223 #endif // CLANG_PSEUDO_FOREST_H
224