1 //===--- GLR.cpp   -----------------------------------------------*- 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 #include "clang-pseudo/GLR.h"
10 #include "clang-pseudo/Language.h"
11 #include "clang-pseudo/grammar/Grammar.h"
12 #include "clang-pseudo/grammar/LRTable.h"
13 #include "clang/Basic/TokenKinds.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/ScopeExit.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include <algorithm>
21 #include <memory>
22 #include <queue>
23 
24 #define DEBUG_TYPE "GLR.cpp"
25 
26 namespace clang {
27 namespace pseudo {
28 namespace {
29 
30 Token::Index findRecoveryEndpoint(RecoveryStrategy Strategy,
31                                   const GSS::Node *RecoveryNode,
32                                   const TokenStream &Tokens) {
33   assert(Strategy == RecoveryStrategy::Braces);
34   const ForestNode *LBrace = RecoveryNode->Payload;
35   assert(LBrace->kind() == ForestNode::Terminal &&
36          LBrace->symbol() == tokenSymbol(tok::l_brace));
37   if (const Token *RBrace = Tokens.tokens()[LBrace->startTokenIndex()].pair())
38     return Tokens.index(*RBrace);
39   return Token::Invalid;
40 }
41 
42 } // namespace
43 
44 void glrRecover(llvm::ArrayRef<const GSS::Node *> OldHeads,
45                 unsigned &TokenIndex, const ParseParams &Params,
46                 const Language &Lang,
47                 std::vector<const GSS::Node *> &NewHeads) {
48   LLVM_DEBUG(llvm::dbgs() << "Recovery at token " << TokenIndex << "...\n");
49   // Describes a possibility to recover by forcibly interpreting a range of
50   // tokens around the cursor as a nonterminal that we expected to see.
51   struct PlaceholderRecovery {
52     // The token prior to the nonterminal which is being recovered.
53     // This starts of the region we're skipping, so higher Position is better.
54     Token::Index Position;
55     // The nonterminal which will be created in order to recover.
56     SymbolID Symbol;
57     // The heuristic used to choose the bounds of the nonterminal to recover.
58     RecoveryStrategy Strategy;
59 
60     // The GSS head where we are expecting the recovered nonterminal.
61     const GSS::Node *RecoveryNode;
62     // Payload of nodes on the way back from the OldHead to the recovery node.
63     // These represent the partial parse that is being discarded.
64     // They should become the children of the opaque recovery node.
65     // FIXME: internal structure of opaque nodes is not implemented.
66     //
67     // There may be multiple paths leading to the same recovery node, we choose
68     // one arbitrarily.
69     std::vector<const ForestNode *> DiscardedParse;
70   };
71   std::vector<PlaceholderRecovery> Options;
72 
73   // Find recovery options by walking up the stack.
74   //
75   // This is similar to exception handling: we walk up the "frames" of nested
76   // rules being parsed until we find one that has a "handler" which allows us
77   // to determine the node bounds without parsing it.
78   //
79   // Unfortunately there's a significant difference: the stack contains both
80   // "upward" nodes (ancestor parses) and "leftward" ones.
81   // e.g. when parsing `{ if (1) ? }` as compound-stmt, the stack contains:
82   //   stmt := IF ( expr ) . stmt      - current state, we should recover here!
83   //   stmt := IF ( expr . ) stmt      - (left, no recovery here)
84   //   stmt := IF ( . expr ) stmt      - left, we should NOT recover here!
85   //   stmt := IF . ( expr ) stmt      - (left, no recovery here)
86   //   stmt-seq := . stmt              - up, we might recover here
87   //   compound-stmt := { . stmt-seq } - up, we should recover here!
88   //
89   // It's not obvious how to avoid collecting "leftward" recovery options.
90   // I think the distinction is ill-defined after merging items into states.
91   // For now, we have to take this into account when defining recovery rules.
92   // (e.g. in the expr recovery above, stay inside the parentheses).
93   // FIXME: find a more satisfying way to avoid such false recovery.
94   // FIXME: Add a test for spurious recovery once tests can define strategies.
95   std::vector<const ForestNode *> Path;
96   llvm::DenseSet<const GSS::Node *> Seen;
97   auto WalkUp = [&](const GSS::Node *N, Token::Index NextTok, auto &WalkUp) {
98     if (!Seen.insert(N).second)
99       return;
100     for (auto Strategy : Lang.Table.getRecovery(N->State)) {
101       Options.push_back(PlaceholderRecovery{
102           NextTok,
103           Strategy.Result,
104           Strategy.Strategy,
105           N,
106           Path,
107       });
108       LLVM_DEBUG(llvm::dbgs()
109                  << "Option: recover " << Lang.G.symbolName(Strategy.Result)
110                  << " at token " << NextTok << "\n");
111     }
112     Path.push_back(N->Payload);
113     for (const GSS::Node *Parent : N->parents())
114       WalkUp(Parent, N->Payload->startTokenIndex(), WalkUp);
115     Path.pop_back();
116   };
117   for (auto *N : OldHeads)
118     WalkUp(N, TokenIndex, WalkUp);
119 
120   // Now we select the option(s) we will use to recover.
121   //
122   // We prefer options starting further right, as these discard less code
123   // (e.g. we prefer to recover inner scopes rather than outer ones).
124   // The options also need to agree on an endpoint, so the parser has a
125   // consistent position afterwards.
126   //
127   // So conceptually we're sorting by the tuple (start, end), though we avoid
128   // computing `end` for options that can't be winners.
129 
130   // Consider options starting further right first.
131   // Don't drop the others yet though, we may still use them if preferred fails.
132   llvm::stable_sort(Options, [&](const auto &L, const auto &R) {
133     return L.Position > R.Position;
134   });
135 
136   // We may find multiple winners, but they will have the same range.
137   llvm::Optional<Token::Range> RecoveryRange;
138   std::vector<const PlaceholderRecovery *> BestOptions;
139   for (const PlaceholderRecovery &Option : Options) {
140     // If this starts further left than options we've already found, then
141     // we'll never find anything better. Skip computing End for the rest.
142     if (RecoveryRange && Option.Position < RecoveryRange->Begin)
143       break;
144 
145     auto End =
146         findRecoveryEndpoint(Option.Strategy, Option.RecoveryNode, Params.Code);
147     // Recovery may not take the parse backwards.
148     if (End == Token::Invalid || End < TokenIndex)
149       continue;
150     if (RecoveryRange) {
151       // If this is worse than our previous options, ignore it.
152       if (RecoveryRange->End < End)
153         continue;
154       // If this is an improvement over our previous options, then drop them.
155       if (RecoveryRange->End > End)
156         BestOptions.clear();
157     }
158     // Create recovery nodes and heads for them in the GSS. These may be
159     // discarded if a better recovery is later found, but this path isn't hot.
160     RecoveryRange = {Option.Position, End};
161     BestOptions.push_back(&Option);
162   }
163 
164   if (BestOptions.empty()) {
165     LLVM_DEBUG(llvm::dbgs() << "Recovery failed after trying " << Options.size()
166                             << " strategies\n");
167     return;
168   }
169 
170   // We've settled on a set of recovery options, so create their nodes and
171   // advance the cursor.
172   LLVM_DEBUG({
173     llvm::dbgs() << "Recovered range=" << *RecoveryRange << ":";
174     for (const auto *Option : BestOptions)
175       llvm::dbgs() << " " << Lang.G.symbolName(Option->Symbol);
176     llvm::dbgs() << "\n";
177   });
178   // FIXME: in general, we might have the same Option->Symbol multiple times,
179   // and we risk creating redundant Forest and GSS nodes.
180   // We also may inadvertently set up the next glrReduce to create a sequence
181   // node duplicating an opaque node that we're creating here.
182   // There are various options, including simply breaking ties between options.
183   // For now it's obscure enough to ignore.
184   for (const PlaceholderRecovery *Option : BestOptions) {
185     const ForestNode &Placeholder =
186         Params.Forest.createOpaque(Option->Symbol, RecoveryRange->Begin);
187     const GSS::Node *NewHead = Params.GSStack.addNode(
188         *Lang.Table.getGoToState(Option->RecoveryNode->State, Option->Symbol),
189         &Placeholder, {Option->RecoveryNode});
190     NewHeads.push_back(NewHead);
191   }
192   TokenIndex = RecoveryRange->End;
193 }
194 
195 using StateID = LRTable::StateID;
196 
197 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GSS::Node &N) {
198   std::vector<std::string> ParentStates;
199   for (const auto *Parent : N.parents())
200     ParentStates.push_back(llvm::formatv("{0}", Parent->State));
201   OS << llvm::formatv("state {0}, parsed symbol {1}, parents {3}", N.State,
202                       N.Payload ? N.Payload->symbol() : 0,
203                       llvm::join(ParentStates, ", "));
204   return OS;
205 }
206 
207 // Apply all pending shift actions.
208 // In theory, LR parsing doesn't have shift/shift conflicts on a single head.
209 // But we may have multiple active heads, and each head has a shift action.
210 //
211 // We merge the stack -- if multiple heads will reach the same state after
212 // shifting a token, we shift only once by combining these heads.
213 //
214 // E.g. we have two heads (2, 3) in the GSS, and will shift both to reach 4:
215 //   0---1---2
216 //       └---3
217 // After the shift action, the GSS is:
218 //   0---1---2---4
219 //       └---3---┘
220 void glrShift(llvm::ArrayRef<const GSS::Node *> OldHeads,
221               const ForestNode &NewTok, const ParseParams &Params,
222               const Language &Lang, std::vector<const GSS::Node *> &NewHeads) {
223   assert(NewTok.kind() == ForestNode::Terminal);
224   LLVM_DEBUG(llvm::dbgs() << llvm::formatv("  Shift {0} ({1} active heads):\n",
225                                            Lang.G.symbolName(NewTok.symbol()),
226                                            OldHeads.size()));
227 
228   // We group pending shifts by their target state so we can merge them.
229   llvm::SmallVector<std::pair<StateID, const GSS::Node *>, 8> Shifts;
230   for (const auto *H : OldHeads)
231     if (auto S = Lang.Table.getShiftState(H->State, NewTok.symbol()))
232       Shifts.push_back({*S, H});
233   llvm::stable_sort(Shifts, llvm::less_first{});
234 
235   auto Rest = llvm::makeArrayRef(Shifts);
236   llvm::SmallVector<const GSS::Node *> Parents;
237   while (!Rest.empty()) {
238     // Collect the batch of PendingShift that have compatible shift states.
239     // Their heads become TempParents, the parents of the new GSS node.
240     StateID NextState = Rest.front().first;
241 
242     Parents.clear();
243     for (const auto &Base : Rest) {
244       if (Base.first != NextState)
245         break;
246       Parents.push_back(Base.second);
247     }
248     Rest = Rest.drop_front(Parents.size());
249 
250     LLVM_DEBUG(llvm::dbgs() << llvm::formatv("    --> S{0} ({1} heads)\n",
251                                              NextState, Parents.size()));
252     NewHeads.push_back(Params.GSStack.addNode(NextState, &NewTok, Parents));
253   }
254 }
255 
256 namespace {
257 // A KeyedQueue yields pairs of keys and values in order of the keys.
258 template <typename Key, typename Value>
259 using KeyedQueue =
260     std::priority_queue<std::pair<Key, Value>,
261                         std::vector<std::pair<Key, Value>>, llvm::less_first>;
262 
263 template <typename T> void sortAndUnique(std::vector<T> &Vec) {
264   llvm::sort(Vec);
265   Vec.erase(std::unique(Vec.begin(), Vec.end()), Vec.end());
266 }
267 
268 // Perform reduces until no more are possible.
269 //
270 // Generally this means walking up from the heads gathering ForestNodes that
271 // will match the RHS of the rule we're reducing into a sequence ForestNode,
272 // and ending up at a base node.
273 // Then we push a new GSS node onto that base, taking care to:
274 //  - pack alternative sequence ForestNodes into an ambiguous ForestNode.
275 //  - use the same GSS node for multiple heads if the parse state matches.
276 //
277 // Examples of reduction:
278 //   Before (simple):
279 //     0--1(expr)--2(semi)
280 //   After reducing 2 by `stmt := expr semi`:
281 //     0--3(stmt)                // 3 is goto(0, stmt)
282 //
283 //   Before (splitting due to R/R conflict):
284 //     0--1(IDENTIFIER)
285 //   After reducing 1 by `class-name := IDENTIFIER` & `enum-name := IDENTIFIER`:
286 //     0--2(class-name)          // 2 is goto(0, class-name)
287 //     └--3(enum-name)           // 3 is goto(0, enum-name)
288 //
289 //   Before (splitting due to multiple bases):
290 //     0--2(class-name)--4(STAR)
291 //     └--3(enum-name)---┘
292 //   After reducing 4 by `ptr-operator := STAR`:
293 //     0--2(class-name)--5(ptr-operator)    // 5 is goto(2, ptr-operator)
294 //     └--3(enum-name)---6(ptr-operator)    // 6 is goto(3, ptr-operator)
295 //
296 //   Before (joining due to same goto state, multiple bases):
297 //     0--1(cv-qualifier)--3(class-name)
298 //     └--2(cv-qualifier)--4(enum-name)
299 //   After reducing 3 by `type-name := class-name` and
300 //                  4 by `type-name := enum-name`:
301 //     0--1(cv-qualifier)--5(type-name)  // 5 is goto(1, type-name) and
302 //     └--2(cv-qualifier)--┘             //      goto(2, type-name)
303 //
304 //   Before (joining due to same goto state, the same base):
305 //     0--1(class-name)--3(STAR)
306 //     └--2(enum-name)--4(STAR)
307 //   After reducing 3 by `pointer := class-name STAR` and
308 //                  2 by`enum-name := class-name STAR`:
309 //     0--5(pointer)       // 5 is goto(0, pointer)
310 //
311 // (This is a functor rather than a function to allow it to reuse scratch
312 // storage across calls).
313 class GLRReduce {
314   const ParseParams &Params;
315   const Language& Lang;
316   // There are two interacting complications:
317   // 1.  Performing one reduce can unlock new reduces on the newly-created head.
318   // 2a. The ambiguous ForestNodes must be complete (have all sequence nodes).
319   //     This means we must have unlocked all the reduces that contribute to it.
320   // 2b. Similarly, the new GSS nodes must be complete (have all parents).
321   //
322   // We define a "family" of reduces as those that produce the same symbol and
323   // cover the same range of tokens. These are exactly the set of reductions
324   // whose sequence nodes would be covered by the same ambiguous node.
325   // We wish to process a whole family at a time (to satisfy complication 2),
326   // and can address complication 1 by carefully ordering the families:
327   // - Process families covering fewer tokens first.
328   //   A reduce can't depend on a longer reduce!
329   // - For equal token ranges: if S := T, process T families before S families.
330   //   Parsing T can't depend on an equal-length S, as the grammar is acyclic.
331   //
332   // This isn't quite enough: we don't know the token length of the reduction
333   // until we walk up the stack to perform the pop.
334   // So we perform the pop part upfront, and place the push specification on
335   // priority queues such that we can retrieve a family at a time.
336 
337   // A reduction family is characterized by its token range and symbol produced.
338   // It is used as a key in the priority queues to group pushes by family.
339   struct Family {
340     // The start of the token range of the reduce.
341     Token::Index Start;
342     SymbolID Symbol;
343     // Rule must produce Symbol and can otherwise be arbitrary.
344     // RuleIDs have the topological order based on the acyclic grammar.
345     // FIXME: should SymbolIDs be so ordered instead?
346     RuleID Rule;
347 
348     bool operator==(const Family &Other) const {
349       return Start == Other.Start && Symbol == Other.Symbol;
350     }
351     // The larger Family is the one that should be processed first.
352     bool operator<(const Family &Other) const {
353       if (Start != Other.Start)
354         return Start < Other.Start;
355       if (Symbol != Other.Symbol)
356         return Rule > Other.Rule;
357       assert(*this == Other);
358       return false;
359     }
360   };
361 
362   // A sequence is the ForestNode payloads of the GSS nodes we are reducing.
363   using Sequence = llvm::SmallVector<const ForestNode *, Rule::MaxElements>;
364   // Like ArrayRef<const ForestNode*>, but with the missing operator<.
365   // (Sequences are big to move by value as the collections gets rearranged).
366   struct SequenceRef {
367     SequenceRef(const Sequence &S) : S(S) {}
368     llvm::ArrayRef<const ForestNode *> S;
369     friend bool operator==(SequenceRef A, SequenceRef B) { return A.S == B.S; }
370     friend bool operator<(const SequenceRef &A, const SequenceRef &B) {
371       return std::lexicographical_compare(A.S.begin(), A.S.end(), B.S.begin(),
372                                           B.S.end());
373     }
374   };
375   // Underlying storage for sequences pointed to by stored SequenceRefs.
376   std::deque<Sequence> SequenceStorage;
377   // We don't actually destroy the sequences between calls, to reuse storage.
378   // Everything SequenceStorage[ >=SequenceStorageCount ] is reusable scratch.
379   unsigned SequenceStorageCount;
380 
381   // Halfway through a reduction (after the pop, before the push), we have
382   // collected nodes for the RHS of a rule, and reached a base node.
383   // They specify a sequence ForestNode we may build (but we dedup first).
384   // (The RuleID is not stored here, but rather in the Family).
385   struct PushSpec {
386     // The last node popped before pushing. Its parent is the reduction base(s).
387     // (Base is more fundamental, but this is cheaper to store).
388     const GSS::Node* LastPop = nullptr;
389     Sequence *Seq = nullptr;
390   };
391   KeyedQueue<Family, PushSpec> Sequences; // FIXME: rename => PendingPushes?
392 
393   // We treat Heads as a queue of Pop operations still to be performed.
394   // PoppedHeads is our position within it.
395   std::vector<const GSS::Node *> *Heads;
396   unsigned NextPopHead;
397   SymbolID Lookahead;
398 
399   Sequence TempSequence;
400 public:
401   GLRReduce(const ParseParams &Params, const Language &Lang)
402       : Params(Params), Lang(Lang) {}
403 
404   void operator()(std::vector<const GSS::Node *> &Heads, SymbolID Lookahead) {
405     assert(isToken(Lookahead));
406 
407     NextPopHead = 0;
408     this->Heads = &Heads;
409     this->Lookahead = Lookahead;
410     assert(Sequences.empty());
411     SequenceStorageCount = 0;
412 
413     popPending();
414     while (!Sequences.empty()) {
415       pushNext();
416       popPending();
417     }
418   }
419 
420 private:
421   bool canReduce(ExtensionID GuardID, RuleID RID,
422                  llvm::ArrayRef<const ForestNode *> RHS) const {
423     if (!GuardID)
424       return true;
425     if (auto Guard = Lang.Guards.lookup(GuardID))
426       return Guard(RHS, Params.Code);
427     LLVM_DEBUG(llvm::dbgs()
428                << llvm::formatv("missing guard implementation for rule {0}\n",
429                                 Lang.G.dumpRule(RID)));
430     return true;
431   }
432   // pop walks up the parent chain(s) for a reduction from Head by to Rule.
433   // Once we reach the end, record the bases and sequences.
434   void pop(const GSS::Node *Head, RuleID RID, const Rule &Rule) {
435     LLVM_DEBUG(llvm::dbgs() << "  Pop " << Lang.G.dumpRule(RID) << "\n");
436     Family F{/*Start=*/0, /*Symbol=*/Rule.Target, /*Rule=*/RID};
437     TempSequence.resize_for_overwrite(Rule.Size);
438     auto DFS = [&](const GSS::Node *N, unsigned I, auto &DFS) {
439       TempSequence[Rule.Size - 1 - I] = N->Payload;
440       if (I + 1 == Rule.Size) {
441         F.Start = TempSequence.front()->startTokenIndex();
442         LLVM_DEBUG({
443           for (const auto *B : N->parents())
444             llvm::dbgs() << "    --> base at S" << B->State << "\n";
445         });
446         if (!canReduce(Rule.Guard, RID, TempSequence))
447           return;
448         // Copy the chain to stable storage so it can be enqueued.
449         if (SequenceStorageCount == SequenceStorage.size())
450           SequenceStorage.emplace_back();
451         SequenceStorage[SequenceStorageCount] = TempSequence;
452         Sequence *Seq = &SequenceStorage[SequenceStorageCount++];
453 
454         Sequences.emplace(F, PushSpec{N, Seq});
455         return;
456       }
457       for (const GSS::Node *Parent : N->parents())
458         DFS(Parent, I + 1, DFS);
459     };
460     DFS(Head, 0, DFS);
461   }
462 
463   // popPending pops every available reduction.
464   void popPending() {
465     for (; NextPopHead < Heads->size(); ++NextPopHead) {
466       // In trivial cases, we perform the complete reduce here!
467       if (popAndPushTrivial())
468         continue;
469       for (RuleID RID :
470            Lang.Table.getReduceRules((*Heads)[NextPopHead]->State)) {
471         const auto &Rule = Lang.G.lookupRule(RID);
472         if (Lang.Table.canFollow(Rule.Target, Lookahead))
473           pop((*Heads)[NextPopHead], RID, Rule);
474       }
475     }
476   }
477 
478   // Storage reused by each call to pushNext.
479   std::vector<std::pair</*Goto*/ StateID, const GSS::Node *>> FamilyBases;
480   std::vector<std::pair<RuleID, SequenceRef>> FamilySequences;
481   std::vector<const GSS::Node *> Parents;
482   std::vector<const ForestNode *> SequenceNodes;
483 
484   // Process one push family, forming a forest node.
485   // This produces new GSS heads which may enable more pops.
486   void pushNext() {
487     assert(!Sequences.empty());
488     Family F = Sequences.top().first;
489 
490     LLVM_DEBUG(llvm::dbgs() << "  Push " << Lang.G.symbolName(F.Symbol)
491                             << " from token " << F.Start << "\n");
492 
493     // Grab the sequences and bases for this family.
494     // We don't care which rule yielded each base. If Family.Symbol is S, the
495     // base includes an item X := ... • S ... and since the grammar is
496     // context-free, *all* parses of S are valid here.
497     FamilySequences.clear();
498     FamilyBases.clear();
499     do {
500       const PushSpec &Push = Sequences.top().second;
501       FamilySequences.emplace_back(Sequences.top().first.Rule, *Push.Seq);
502       for (const GSS::Node *Base : Push.LastPop->parents()) {
503         auto NextState = Lang.Table.getGoToState(Base->State, F.Symbol);
504         assert(NextState.hasValue() && "goto must succeed after reduce!");
505         FamilyBases.emplace_back(*NextState, Base);
506       }
507 
508       Sequences.pop();
509     } while (!Sequences.empty() && Sequences.top().first == F);
510     // Build a forest node for each unique sequence.
511     sortAndUnique(FamilySequences);
512     SequenceNodes.clear();
513     for (const auto &SequenceSpec : FamilySequences)
514       SequenceNodes.push_back(&Params.Forest.createSequence(
515           F.Symbol, SequenceSpec.first, SequenceSpec.second.S));
516     // Wrap in an ambiguous node if needed.
517     const ForestNode *Parsed =
518         SequenceNodes.size() == 1
519             ? SequenceNodes.front()
520             : &Params.Forest.createAmbiguous(F.Symbol, SequenceNodes);
521     LLVM_DEBUG(llvm::dbgs() << "    --> " << Parsed->dump(Lang.G) << "\n");
522 
523     // Bases for this family, deduplicate them, and group by the goTo State.
524     sortAndUnique(FamilyBases);
525     // Create a GSS node for each unique goto state.
526     llvm::ArrayRef<decltype(FamilyBases)::value_type> BasesLeft = FamilyBases;
527     while (!BasesLeft.empty()) {
528       StateID NextState = BasesLeft.front().first;
529       Parents.clear();
530       for (const auto &Base : BasesLeft) {
531         if (Base.first != NextState)
532           break;
533         Parents.push_back(Base.second);
534       }
535       BasesLeft = BasesLeft.drop_front(Parents.size());
536       Heads->push_back(Params.GSStack.addNode(NextState, Parsed, Parents));
537     }
538   }
539 
540   // In general we split a reduce into a pop/push, so concurrently-available
541   // reductions can run in the correct order. The data structures are expensive.
542   //
543   // When only one reduction is possible at a time, we can skip this:
544   // we pop and immediately push, as an LR parser (as opposed to GLR) would.
545   // This is valid whenever there's only one concurrent PushSpec.
546   //
547   // This function handles a trivial but common subset of these cases:
548   //  - there must be no pending pushes, and only one poppable head
549   //  - the head must have only one reduction rule
550   //  - the reduction path must be a straight line (no multiple parents)
551   // (Roughly this means there's no local ambiguity, so the LR algorithm works).
552   //
553   // Returns true if we successfully consumed the next unpopped head.
554   bool popAndPushTrivial() {
555     if (!Sequences.empty() || Heads->size() != NextPopHead + 1)
556       return false;
557     const GSS::Node *Head = Heads->back();
558     llvm::Optional<RuleID> RID;
559     for (RuleID R : Lang.Table.getReduceRules(Head->State)) {
560       if (RID.hasValue())
561         return false;
562       RID = R;
563     }
564     if (!RID)
565       return true; // no reductions available, but we've processed the head!
566     const auto &Rule = Lang.G.lookupRule(*RID);
567     if (!Lang.Table.canFollow(Rule.Target, Lookahead))
568       return true; // reduction is not available
569     const GSS::Node *Base = Head;
570     TempSequence.resize_for_overwrite(Rule.Size);
571     for (unsigned I = 0; I < Rule.Size; ++I) {
572       if (Base->parents().size() != 1)
573         return false;
574       TempSequence[Rule.Size - 1 - I] = Base->Payload;
575       Base = Base->parents().front();
576     }
577     if (!canReduce(Rule.Guard, *RID, TempSequence))
578       return true; // reduction is not available
579     const ForestNode *Parsed =
580         &Params.Forest.createSequence(Rule.Target, *RID, TempSequence);
581     auto NextState = Lang.Table.getGoToState(Base->State, Rule.Target);
582     assert(NextState.hasValue() && "goto must succeed after reduce!");
583     Heads->push_back(Params.GSStack.addNode(*NextState, Parsed, {Base}));
584     return true;
585   }
586 };
587 
588 } // namespace
589 
590 const ForestNode &glrParse(const ParseParams &Params, SymbolID StartSymbol,
591                            const Language &Lang) {
592   GLRReduce Reduce(Params, Lang);
593   assert(isNonterminal(StartSymbol) && "Start symbol must be a nonterminal");
594   llvm::ArrayRef<ForestNode> Terminals = Params.Forest.createTerminals(Params.Code);
595   auto &GSS = Params.GSStack;
596 
597   StateID StartState = Lang.Table.getStartState(StartSymbol);
598   // Heads correspond to the parse of tokens [0, I), NextHeads to [0, I+1).
599   std::vector<const GSS::Node *> Heads = {GSS.addNode(/*State=*/StartState,
600                                                       /*ForestNode=*/nullptr,
601                                                       {})};
602   std::vector<const GSS::Node *> NextHeads;
603   auto MaybeGC = [&, Roots(std::vector<const GSS::Node *>{}), I(0u)]() mutable {
604     assert(NextHeads.empty() && "Running GC at the wrong time!");
605     if (++I != 20) // Run periodically to balance CPU and memory usage.
606       return;
607     I = 0;
608 
609     // We need to copy the list: Roots is consumed by the GC.
610     Roots = Heads;
611     GSS.gc(std::move(Roots));
612   };
613   // Each iteration fully processes a single token.
614   for (unsigned I = 0; I < Terminals.size();) {
615     LLVM_DEBUG(llvm::dbgs() << llvm::formatv(
616                    "Next token {0} (id={1})\n",
617                   Lang.G.symbolName(Terminals[I].symbol()), Terminals[I].symbol()));
618     // Consume the token.
619     glrShift(Heads, Terminals[I], Params, Lang, NextHeads);
620 
621     // If we weren't able to consume the token, try to skip over some tokens
622     // so we can keep parsing.
623     if (NextHeads.empty()) {
624       // FIXME: Heads may not be fully reduced, because our reductions were
625       // constrained by lookahead (but lookahead is meaningless to recovery).
626       glrRecover(Heads, I, Params, Lang, NextHeads);
627       if (NextHeads.empty())
628         // FIXME: Ensure the `_ := start-symbol` rules have a fallback
629         // error-recovery strategy attached. Then this condition can't happen.
630         return Params.Forest.createOpaque(StartSymbol, /*Token::Index=*/0);
631     } else
632       ++I;
633 
634     // Form nonterminals containing the token we just consumed.
635     SymbolID Lookahead =
636         I == Terminals.size() ? tokenSymbol(tok::eof) : Terminals[I].symbol();
637     Reduce(NextHeads, Lookahead);
638     // Prepare for the next token.
639     std::swap(Heads, NextHeads);
640     NextHeads.clear();
641     MaybeGC();
642   }
643   LLVM_DEBUG(llvm::dbgs() << llvm::formatv("Reached eof\n"));
644 
645   // The parse was successful if we're in state `_ := start-symbol .`
646   auto AcceptState = Lang.Table.getGoToState(StartState, StartSymbol);
647   assert(AcceptState.hasValue() && "goto must succeed after start symbol!");
648   auto SearchForAccept = [&](llvm::ArrayRef<const GSS::Node *> Heads) {
649     const ForestNode *Result = nullptr;
650     for (const auto *Head : Heads) {
651       if (Head->State == *AcceptState) {
652         assert(Head->Payload->symbol() == StartSymbol);
653         assert(Result == nullptr && "multiple results!");
654         Result = Head->Payload;
655       }
656     }
657     return Result;
658   };
659   if (auto *Result = SearchForAccept(Heads))
660     return *Result;
661   // Failed to parse the input, attempt to run recovery.
662   // FIXME: this awkwardly repeats the recovery in the loop, when shift fails.
663   // More elegant is to include EOF in the token stream, and make the
664   // augmented rule: `_ := translation-unit EOF`. In this way recovery at EOF
665   // would not be a special case: it show up as a failure to shift the EOF
666   // token.
667   unsigned I = Terminals.size();
668   glrRecover(Heads, I, Params, Lang, NextHeads);
669   Reduce(NextHeads, tokenSymbol(tok::eof));
670   if (auto *Result = SearchForAccept(NextHeads))
671     return *Result;
672 
673   // We failed to parse the input, returning an opaque forest node for recovery.
674   // FIXME: as above, we can add fallback error handling so this is impossible.
675   return Params.Forest.createOpaque(StartSymbol, /*Token::Index=*/0);
676 }
677 
678 void glrReduce(std::vector<const GSS::Node *> &Heads, SymbolID Lookahead,
679                const ParseParams &Params, const Language &Lang) {
680   // Create a new GLRReduce each time for tests, performance doesn't matter.
681   GLRReduce{Params, Lang}(Heads, Lookahead);
682 }
683 
684 const GSS::Node *GSS::addNode(LRTable::StateID State, const ForestNode *Symbol,
685 
686                               llvm::ArrayRef<const Node *> Parents) {
687   Node *Result = new (allocate(Parents.size()))
688       Node({State, GCParity, static_cast<uint16_t>(Parents.size())});
689   Alive.push_back(Result);
690   ++NodesCreated;
691   Result->Payload = Symbol;
692   if (!Parents.empty())
693     llvm::copy(Parents, reinterpret_cast<const Node **>(Result + 1));
694   return Result;
695 }
696 
697 GSS::Node *GSS::allocate(unsigned Parents) {
698   if (FreeList.size() <= Parents)
699     FreeList.resize(Parents + 1);
700   auto &SizedList = FreeList[Parents];
701   if (!SizedList.empty()) {
702     auto *Result = SizedList.back();
703     SizedList.pop_back();
704     return Result;
705   }
706   return static_cast<Node *>(
707       Arena.Allocate(sizeof(Node) + Parents * sizeof(Node *), alignof(Node)));
708 }
709 
710 void GSS::destroy(Node *N) {
711   unsigned ParentCount = N->ParentCount;
712   N->~Node();
713   assert(FreeList.size() > ParentCount && "established on construction!");
714   FreeList[ParentCount].push_back(N);
715 }
716 
717 unsigned GSS::gc(std::vector<const Node *> &&Queue) {
718 #ifndef NDEBUG
719   auto ParityMatches = [&](const Node *N) { return N->GCParity == GCParity; };
720   assert("Before GC" && llvm::all_of(Alive, ParityMatches));
721   auto Deferred = llvm::make_scope_exit(
722       [&] { assert("After GC" && llvm::all_of(Alive, ParityMatches)); });
723   assert(llvm::all_of(
724       Queue, [&](const Node *R) { return llvm::is_contained(Alive, R); }));
725 #endif
726   unsigned InitialCount = Alive.size();
727 
728   // Mark
729   GCParity = !GCParity;
730   while (!Queue.empty()) {
731     Node *N = const_cast<Node *>(Queue.back()); // Safe: we created these nodes.
732     Queue.pop_back();
733     if (N->GCParity != GCParity) { // Not seen yet
734       N->GCParity = GCParity;      // Mark as seen
735       for (const Node *P : N->parents()) // And walk parents
736         Queue.push_back(P);
737     }
738   }
739   // Sweep
740   llvm::erase_if(Alive, [&](Node *N) {
741     if (N->GCParity == GCParity) // Walk reached this node.
742       return false;
743     destroy(N);
744     return true;
745   });
746 
747   LLVM_DEBUG(llvm::dbgs() << "GC pruned " << (InitialCount - Alive.size())
748                           << "/" << InitialCount << " GSS nodes\n");
749   return InitialCount - Alive.size();
750 }
751 
752 } // namespace pseudo
753 } // namespace clang
754