[clang-tools-extra] 9fbf110 - [pseudo] Eliminate LRTable::Action. NFC

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 5 05:35:55 PDT 2022


Author: Sam McCall
Date: 2022-07-05T14:35:41+02:00
New Revision: 9fbf1107cc763783a82b89953be8a45097ba3390

URL: https://github.com/llvm/llvm-project/commit/9fbf1107cc763783a82b89953be8a45097ba3390
DIFF: https://github.com/llvm/llvm-project/commit/9fbf1107cc763783a82b89953be8a45097ba3390.diff

LOG: [pseudo] Eliminate LRTable::Action. NFC

The last remaining uses are in tests/test builders.
Replace with a builder struct.

Differential Revision: https://reviews.llvm.org/D129093

Added: 
    

Modified: 
    clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h
    clang-tools-extra/pseudo/lib/grammar/LRTable.cpp
    clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp
    clang-tools-extra/pseudo/unittests/GLRTest.cpp
    clang-tools-extra/pseudo/unittests/LRTableTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h
index cd183b552d6f..7575b3271dc2 100644
--- a/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h
+++ b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/LRTable.h
@@ -39,6 +39,7 @@
 #include "clang-pseudo/grammar/Grammar.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/Capacity.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -58,71 +59,15 @@ namespace pseudo {
 // Unlike the typical LR parsing table which allows at most one available action
 // per entry, conflicted actions are allowed in LRTable. The LRTable is designed
 // to be used in nondeterministic LR parsers (e.g. GLR).
+//
+// There are no "accept" actions in the LRTable, instead the stack is inspected
+// after parsing completes: is the state goto(StartState, StartSymbol)?
 class LRTable {
 public:
   // StateID is only 13 bits wide.
   using StateID = uint16_t;
   static constexpr unsigned StateBits = 13;
 
-  // Action represents the terminal and nonterminal actions, it combines the
-  // entry of the ACTION and GOTO tables from the LR literature.
-  //
-  // FIXME: as we move away from a homogeneous table structure shared between
-  // action types, this class becomes less useful. Remove it.
-  class Action {
-  public:
-    enum Kind : uint8_t {
-      Sentinel = 0,
-      // Terminal actions, corresponding to entries of ACTION table.
-
-      // Shift to state n: move forward with the lookahead, and push state n
-      // onto the state stack.
-      // A shift is a forward transition, and the value n is the next state that
-      // the parser is to enter.
-      Shift,
-
-      // NOTE: there are no typical accept actions in the LRtable, accept
-      // actions are handled specifically in the parser -- if the parser
-      // reaches to a target state (which is goto(StartState, StartSymbol)) at
-      // the EOF token after a reduce, this indicates the input has been parsed
-      // as the StartSymbol successfully.
-
-      // Nonterminal actions, corresponding to entry of GOTO table.
-
-      // Go to state n: push state n onto the state stack.
-      // Similar to Shift, but it is a nonterminal forward transition.
-      GoTo,
-    };
-
-    static Action goTo(StateID S) { return Action(GoTo, S); }
-    static Action shift(StateID S) { return Action(Shift, S); }
-    static Action sentinel() { return Action(Sentinel, 0); }
-
-    StateID getShiftState() const {
-      assert(kind() == Shift);
-      return Value;
-    }
-    StateID getGoToState() const {
-      assert(kind() == GoTo);
-      return Value;
-    }
-    Kind kind() const { return static_cast<Kind>(K); }
-
-    bool operator==(const Action &L) const { return opaque() == L.opaque(); }
-    uint16_t opaque() const { return K << ValueBits | Value; };
-
-  private:
-    Action(Kind K1, unsigned Value) : K(K1), Value(Value) {}
-    static constexpr unsigned ValueBits = StateBits;
-    static constexpr unsigned KindBits = 3;
-    static_assert(ValueBits >= RuleBits, "Value must be able to store RuleID");
-    static_assert(KindBits + ValueBits <= 16,
-                  "Must be able to store kind and value efficiently");
-    uint16_t K : KindBits;
-    // Either StateID or RuleID, depending on the Kind.
-    uint16_t Value : ValueBits;
-  };
-
   // Returns the state after we reduce a nonterminal.
   // Expected to be called by LR parsers.
   // If the nonterminal is invalid here, returns None.
@@ -184,20 +129,27 @@ class LRTable {
   // Build a SLR(1) parsing table.
   static LRTable buildSLR(const Grammar &G);
 
-  struct Builder;
-  // Represents an entry in the table, used for building the LRTable.
-  struct Entry {
-    StateID State;
-    SymbolID Symbol;
-    Action Act;
-  };
-  struct ReduceEntry {
-    StateID State;
-    RuleID Rule;
+  // Helper for building a table with specified actions/states.
+  struct Builder {
+    Builder() = default;
+    Builder(const Grammar &G) {
+      NumNonterminals = G.table().Nonterminals.size();
+      FollowSets = followSets(G);
+    }
+
+    unsigned int NumNonterminals = 0;
+    // States representing `_ := . start` for various start symbols.
+    std::vector<std::pair<SymbolID, StateID>> StartStates;
+    // State transitions `X := ABC . D EFG` => `X := ABC D . EFG`.
+    // Key is (initial state, D), value is final state.
+    llvm::DenseMap<std::pair<StateID, SymbolID>, StateID> Transition;
+    // Reductions available in a given state.
+    llvm::DenseMap<StateID, llvm::SmallSet<RuleID, 4>> Reduce;
+    // FollowSets[NT] is the set of terminals that can follow the nonterminal.
+    std::vector<llvm::DenseSet<SymbolID>> FollowSets;
+
+    LRTable build() &&;
   };
-  // Build a specifid table for testing purposes.
-  static LRTable buildForTests(const Grammar &G, llvm::ArrayRef<Entry>,
-                               llvm::ArrayRef<ReduceEntry>);
 
 private:
   unsigned numStates() const { return ReduceOffset.size() - 1; }
@@ -300,7 +252,6 @@ class LRTable {
   // as an index: Nonterminal * NUM_TOKENS + Token.
   llvm::BitVector FollowSets;
 };
-llvm::raw_ostream &operator<<(llvm::raw_ostream &, const LRTable::Action &);
 
 } // namespace pseudo
 } // namespace clang

diff  --git a/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp b/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp
index 058970be5d60..6a68f1489d57 100644
--- a/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp
+++ b/clang-tools-extra/pseudo/lib/grammar/LRTable.cpp
@@ -11,25 +11,12 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace clang {
 namespace pseudo {
 
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LRTable::Action &A) {
-  switch (A.kind()) {
-  case LRTable::Action::Shift:
-    return OS << llvm::formatv("shift state {0}", A.getShiftState());
-  case LRTable::Action::GoTo:
-    return OS << llvm::formatv("go to state {0}", A.getGoToState());
-  case LRTable::Action::Sentinel:
-    llvm_unreachable("unexpected Sentinel action kind!");
-  }
-  llvm_unreachable("unexpected action kind!");
-}
-
 std::string LRTable::dumpStatistics() const {
   return llvm::formatv(R"(
 Statistics of the LR parsing table:

diff  --git a/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp b/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp
index 77eabfdd39a3..15b66ceea75e 100644
--- a/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp
+++ b/clang-tools-extra/pseudo/lib/grammar/LRTableBuild.cpp
@@ -13,109 +13,67 @@
 #include "llvm/ADT/SmallSet.h"
 #include <cstdint>
 
-namespace llvm {
-template <> struct DenseMapInfo<clang::pseudo::LRTable::Entry> {
-  using Entry = clang::pseudo::LRTable::Entry;
-  static inline Entry getEmptyKey() {
-    static Entry E{static_cast<clang::pseudo::SymbolID>(-1), 0,
-                   clang::pseudo::LRTable::Action::sentinel()};
-    return E;
-  }
-  static inline Entry getTombstoneKey() {
-    static Entry E{static_cast<clang::pseudo::SymbolID>(-2), 0,
-                   clang::pseudo::LRTable::Action::sentinel()};
-    return E;
-  }
-  static unsigned getHashValue(const Entry &I) {
-    return llvm::hash_combine(I.State, I.Symbol, I.Act.opaque());
-  }
-  static bool isEqual(const Entry &LHS, const Entry &RHS) {
-    return LHS.State == RHS.State && LHS.Symbol == RHS.Symbol &&
-           LHS.Act == RHS.Act;
-  }
-};
-} // namespace llvm
-
 namespace clang {
 namespace pseudo {
 
-struct LRTable::Builder {
-  std::vector<std::pair<SymbolID, StateID>> StartStates;
-  llvm::DenseSet<Entry> Entries;
-  llvm::DenseMap<StateID, llvm::SmallSet<RuleID, 4>> Reduces;
-  std::vector<llvm::DenseSet<SymbolID>> FollowSets;
+LRTable LRTable::Builder::build() && {
+  assert(NumNonterminals != 0 && "Set NumNonterminals or init with grammar");
+  LRTable Table;
 
-  LRTable build(unsigned NumStates, unsigned NumNonterminals) && {
-    LRTable Table;
-    Table.StartStates = std::move(StartStates);
+  // Count number of states: every state has to be reachable somehow.
+  StateID MaxState = 0;
+  for (const auto &Entry : StartStates)
+    MaxState = std::max(MaxState, Entry.second);
+  for (const auto &Entry : Transition)
+    MaxState = std::max(MaxState, Entry.second);
+  unsigned NumStates = MaxState + 1;
 
-    // Compile the goto and shift actions into transition tables.
-    llvm::DenseMap<unsigned, SymbolID> Gotos;
-    llvm::DenseMap<unsigned, SymbolID> Shifts;
-    for (const auto &E : Entries) {
-      if (E.Act.kind() == Action::Shift)
-        Shifts.try_emplace(shiftIndex(E.State, E.Symbol, NumStates),
-                           E.Act.getShiftState());
-      else if (E.Act.kind() == Action::GoTo)
-        Gotos.try_emplace(gotoIndex(E.State, E.Symbol, NumStates),
-                          E.Act.getGoToState());
-    }
-    Table.Shifts = TransitionTable(Shifts, NumStates * NumTerminals);
-    Table.Gotos = TransitionTable(Gotos, NumStates * NumNonterminals);
+  Table.StartStates = std::move(StartStates);
 
-    // Compile the follow sets into a bitmap.
-    Table.FollowSets.resize(tok::NUM_TOKENS * FollowSets.size());
-    for (SymbolID NT = 0; NT < FollowSets.size(); ++NT)
-      for (SymbolID Follow : FollowSets[NT])
-        Table.FollowSets.set(NT * tok::NUM_TOKENS + symbolToToken(Follow));
+  // Compile the goto and shift actions into transition tables.
+  llvm::DenseMap<unsigned, SymbolID> Gotos;
+  llvm::DenseMap<unsigned, SymbolID> Shifts;
+  for (const auto &E : Transition) {
+    if (isToken(E.first.second))
+      Shifts.try_emplace(shiftIndex(E.first.first, E.first.second, NumStates),
+                         E.second);
+    else
+      Gotos.try_emplace(gotoIndex(E.first.first, E.first.second, NumStates),
+                        E.second);
+  }
+  Table.Shifts = TransitionTable(Shifts, NumStates * NumTerminals);
+  Table.Gotos = TransitionTable(Gotos, NumStates * NumNonterminals);
 
-    // Store the reduce actions in a vector partitioned by state.
-    Table.ReduceOffset.reserve(NumStates + 1);
-    std::vector<RuleID> StateRules;
-    for (StateID S = 0; S < NumStates; ++S) {
-      Table.ReduceOffset.push_back(Table.Reduces.size());
-      auto It = Reduces.find(S);
-      if (It == Reduces.end())
-        continue;
-      Table.Reduces.insert(Table.Reduces.end(), It->second.begin(),
-                           It->second.end());
-      std::sort(Table.Reduces.begin() + Table.ReduceOffset.back(),
-                Table.Reduces.end());
-    }
-    Table.ReduceOffset.push_back(Table.Reduces.size());
+  // Compile the follow sets into a bitmap.
+  Table.FollowSets.resize(tok::NUM_TOKENS * FollowSets.size());
+  for (SymbolID NT = 0; NT < FollowSets.size(); ++NT)
+    for (SymbolID Follow : FollowSets[NT])
+      Table.FollowSets.set(NT * tok::NUM_TOKENS + symbolToToken(Follow));
 
-    return Table;
+  // Store the reduce actions in a vector partitioned by state.
+  Table.ReduceOffset.reserve(NumStates + 1);
+  std::vector<RuleID> StateRules;
+  for (StateID S = 0; S < NumStates; ++S) {
+    Table.ReduceOffset.push_back(Table.Reduces.size());
+    auto It = Reduce.find(S);
+    if (It == Reduce.end())
+      continue;
+    Table.Reduces.insert(Table.Reduces.end(), It->second.begin(),
+                         It->second.end());
+    std::sort(Table.Reduces.begin() + Table.ReduceOffset.back(),
+              Table.Reduces.end());
   }
-};
+  Table.ReduceOffset.push_back(Table.Reduces.size());
 
-LRTable LRTable::buildForTests(const Grammar &G, llvm::ArrayRef<Entry> Entries,
-                               llvm::ArrayRef<ReduceEntry> Reduces) {
-  StateID MaxState = 0;
-  for (const auto &Entry : Entries) {
-    MaxState = std::max(MaxState, Entry.State);
-    if (Entry.Act.kind() == LRTable::Action::Shift)
-      MaxState = std::max(MaxState, Entry.Act.getShiftState());
-    if (Entry.Act.kind() == LRTable::Action::GoTo)
-      MaxState = std::max(MaxState, Entry.Act.getGoToState());
-  }
-  Builder Build;
-  Build.Entries.insert(Entries.begin(), Entries.end());
-  for (const ReduceEntry &E : Reduces)
-    Build.Reduces[E.State].insert(E.Rule);
-  Build.FollowSets = followSets(G);
-  return std::move(Build).build(/*NumStates=*/MaxState + 1,
-                                G.table().Nonterminals.size());
+  return Table;
 }
 
 LRTable LRTable::buildSLR(const Grammar &G) {
   auto Graph = LRGraph::buildLR0(G);
-  Builder Build;
+  Builder Build(G);
   Build.StartStates = Graph.startStates();
-  for (const auto &T : Graph.edges()) {
-    Action Act = isToken(T.Label) ? Action::shift(T.Dst) : Action::goTo(T.Dst);
-    Build.Entries.insert({T.Src, T.Label, Act});
-  }
-  Build.FollowSets = followSets(G);
+  for (const auto &T : Graph.edges())
+    Build.Transition.try_emplace({T.Src, T.Label}, T.Dst);
   assert(Graph.states().size() <= (1 << StateBits) &&
          "Graph states execceds the maximum limit!");
   // Add reduce actions.
@@ -129,11 +87,10 @@ LRTable LRTable::buildSLR(const Grammar &G) {
       if (!I.hasNext())
         // If we've reached the end of a rule A := ..., then we can reduce if
         // the next token is in the follow set of A.
-        Build.Reduces[SID].insert(I.rule());
+        Build.Reduce[SID].insert(I.rule());
     }
   }
-  return std::move(Build).build(Graph.states().size(),
-                                G.table().Nonterminals.size());
+  return std::move(Build).build();
 }
 
 } // namespace pseudo

diff  --git a/clang-tools-extra/pseudo/unittests/GLRTest.cpp b/clang-tools-extra/pseudo/unittests/GLRTest.cpp
index 6c5cd22bb73e..8dc0939b9bd9 100644
--- a/clang-tools-extra/pseudo/unittests/GLRTest.cpp
+++ b/clang-tools-extra/pseudo/unittests/GLRTest.cpp
@@ -30,7 +30,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
 
 namespace {
 
-using Action = LRTable::Action;
+using StateID = LRTable::StateID;
 using testing::AllOf;
 using testing::ElementsAre;
 using testing::UnorderedElementsAre;
@@ -122,13 +122,11 @@ TEST_F(GLRTest, ShiftMergingHeads) {
                                    /*Parents=*/{GSSNode0});
 
   buildGrammar({}, {}); // Create a fake empty grammar.
-  TestLang.Table =
-      LRTable::buildForTests(TestLang.G, /*Entries=*/{
-                                 {1, tokenSymbol(tok::semi), Action::shift(4)},
-                                 {2, tokenSymbol(tok::semi), Action::shift(4)},
-                                 {3, tokenSymbol(tok::semi), Action::shift(5)},
-                             },
-                             {});
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{1}, tokenSymbol(tok::semi)}] = StateID{4};
+  B.Transition[{StateID{2}, tokenSymbol(tok::semi)}] = StateID{4};
+  B.Transition[{StateID{3}, tokenSymbol(tok::semi)}] = StateID{5};
+  TestLang.Table = std::move(B).build();
 
   ForestNode &SemiTerminal = Arena.createTerminal(tok::semi, 0);
   std::vector<const GSS::Node *> NewHeads;
@@ -152,17 +150,12 @@ TEST_F(GLRTest, ReduceConflictsSplitting) {
   //    └--3(enum-name)     // 3 is goto(0, enum-name)
   buildGrammar({"class-name", "enum-name"},
                {"class-name := IDENTIFIER", "enum-name := IDENTIFIER"});
-
-  TestLang.Table = LRTable::buildForTests(
-      TestLang.G,
-      {
-          {/*State=*/0, id("class-name"), Action::goTo(2)},
-          {/*State=*/0, id("enum-name"), Action::goTo(3)},
-      },
-      {
-          {/*State=*/1, ruleFor("class-name")},
-          {/*State=*/1, ruleFor("enum-name")},
-      });
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{0}, id("class-name")}] = StateID{2};
+  B.Transition[{StateID{0}, id("enum-name")}] = StateID{3};
+  B.Reduce[StateID{1}].insert(ruleFor("class-name"));
+  B.Reduce[StateID{1}].insert(ruleFor("enum-name"));
+  TestLang.Table = std::move(B).build();
 
   const auto *GSSNode0 =
       GSStack.addNode(/*State=*/0, /*ForestNode=*/nullptr, /*Parents=*/{});
@@ -202,15 +195,12 @@ TEST_F(GLRTest, ReduceSplittingDueToMultipleBases) {
       /*State=*/4, &Arena.createTerminal(tok::star, /*TokenIndex=*/1),
       /*Parents=*/{GSSNode2, GSSNode3});
 
-  TestLang.Table = LRTable::buildForTests(
-      TestLang.G,
-      {
-          {/*State=*/2, id("ptr-operator"), Action::goTo(/*NextState=*/5)},
-          {/*State=*/3, id("ptr-operator"), Action::goTo(/*NextState=*/6)},
-      },
-      {
-          {/*State=*/4, ruleFor("ptr-operator")},
-      });
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{2}, id("ptr-operator")}] = StateID{5};
+  B.Transition[{StateID{3}, id("ptr-operator")}] = StateID{6};
+  B.Reduce[StateID{4}].insert(ruleFor("ptr-operator"));
+  TestLang.Table = std::move(B).build();
+
   std::vector<const GSS::Node *> Heads = {GSSNode4};
   glrReduce(Heads, tokenSymbol(tok::eof), {TestLang.G, TestLang.Table, Arena, GSStack});
 
@@ -256,16 +246,13 @@ TEST_F(GLRTest, ReduceJoiningWithMultipleBases) {
                       /*Parents=*/{GSSNode2});
 
   // FIXME: figure out a way to get rid of the hard-coded reduce RuleID!
-  TestLang.Table = LRTable::buildForTests(
-      TestLang.G,
-      {
-          {/*State=*/1, id("type-name"), Action::goTo(/*NextState=*/5)},
-          {/*State=*/2, id("type-name"), Action::goTo(/*NextState=*/5)},
-      },
-      {
-          {/*State=*/3, /* type-name := class-name */ 0},
-          {/*State=*/4, /* type-name := enum-name */ 1},
-      });
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{1}, id("type-name")}] = StateID{5};
+  B.Transition[{StateID{2}, id("type-name")}] = StateID{5};
+  B.Reduce[StateID{3}].insert(/* type-name := class-name */ RuleID{0});
+  B.Reduce[StateID{4}].insert(/* type-name := enum-name */ RuleID{1});
+  TestLang.Table = std::move(B).build();
+
   std::vector<const GSS::Node *> Heads = {GSSNode3, GSSNode4};
   glrReduce(Heads, tokenSymbol(tok::eof), {TestLang.G, TestLang.Table, Arena, GSStack});
 
@@ -314,15 +301,12 @@ TEST_F(GLRTest, ReduceJoiningWithSameBase) {
                       /*Parents=*/{GSSNode2});
 
   // FIXME: figure out a way to get rid of the hard-coded reduce RuleID!
-  TestLang.Table =
-      LRTable::buildForTests(TestLang.G,
-                             {
-                                 {/*State=*/0, id("pointer"), Action::goTo(5)},
-                             },
-                             {
-                                 {3, /* pointer := class-name */ 0},
-                                 {4, /* pointer := enum-name */ 1},
-                             });
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{0}, id("pointer")}] = StateID{5};
+  B.Reduce[StateID{3}].insert(/* pointer := class-name */ RuleID{0});
+  B.Reduce[StateID{4}].insert(/* pointer := enum-name */ RuleID{1});
+  TestLang.Table = std::move(B).build();
+
   std::vector<const GSS::Node *> Heads = {GSSNode3, GSSNode4};
   glrReduce(Heads, tokenSymbol(tok::eof),
             {TestLang.G, TestLang.Table, Arena, GSStack});
@@ -345,14 +329,10 @@ TEST_F(GLRTest, ReduceJoiningWithSameBase) {
 TEST_F(GLRTest, ReduceLookahead) {
   // A term can be followed by +, but not by -.
   buildGrammar({"sum", "term"}, {"expr := term + term", "term := IDENTIFIER"});
-  TestLang.Table =
-      LRTable::buildForTests(TestLang.G,
-                             {
-                                 {/*State=*/0, id("term"), Action::goTo(2)},
-                             },
-                             {
-                                 {/*State=*/1, 0},
-                             });
+  LRTable::Builder B(TestLang.G);
+  B.Transition[{StateID{0}, id("term")}] = StateID{2};
+  B.Reduce[StateID{1}].insert(RuleID{0});
+  TestLang.Table = std::move(B).build();
 
   auto *Identifier = &Arena.createTerminal(tok::identifier, /*Start=*/0);
 

diff  --git a/clang-tools-extra/pseudo/unittests/LRTableTest.cpp b/clang-tools-extra/pseudo/unittests/LRTableTest.cpp
index 061bf7ddd5f4..f56178a8582b 100644
--- a/clang-tools-extra/pseudo/unittests/LRTableTest.cpp
+++ b/clang-tools-extra/pseudo/unittests/LRTableTest.cpp
@@ -20,7 +20,7 @@ namespace {
 
 using llvm::ValueIs;
 using testing::ElementsAre;
-using Action = LRTable::Action;
+using StateID = LRTable::StateID;
 
 TEST(LRTable, Builder) {
   std::vector<std::string> GrammarDiags;
@@ -38,22 +38,20 @@ TEST(LRTable, Builder) {
   SymbolID Identifier = tokenSymbol(tok::identifier);
   SymbolID Plus = tokenSymbol(tok::plus);
 
+  LRTable::Builder B(G);
   //           eof  IDENT   term
   // +-------+----+-------+------+
   // |state0 |    | s0    |      |
   // |state1 |    |       | g3   |
   // |state2 |    |       |      |
   // +-------+----+-------+------+-------
-  std::vector<LRTable::Entry> Entries = {
-      {/* State */ 0, Identifier, Action::shift(0)},
-      {/* State */ 1, Term, Action::goTo(3)},
-  };
-  std::vector<LRTable::ReduceEntry> ReduceEntries = {
-      {/*State=*/0, /*Rule=*/0},
-      {/*State=*/1, /*Rule=*/2},
-      {/*State=*/2, /*Rule=*/1},
-  };
-  LRTable T = LRTable::buildForTests(G, Entries, ReduceEntries);
+  B.Transition[{StateID{0}, Identifier}] = StateID{0};
+  B.Transition[{StateID{1}, Term}] = StateID{3};
+  B.Reduce[StateID{0}].insert(RuleID{0});
+  B.Reduce[StateID{1}].insert(RuleID{2});
+  B.Reduce[StateID{2}].insert(RuleID{1});
+  LRTable T = std::move(B).build();
+
   EXPECT_EQ(T.getShiftState(0, Eof), llvm::None);
   EXPECT_THAT(T.getShiftState(0, Identifier), ValueIs(0));
   EXPECT_THAT(T.getReduceRules(0), ElementsAre(0));


        


More information about the cfe-commits mailing list