[pseudo] Grammar::parseBNF returns Grammar not unique_ptr. NFC
authorSam McCall <sam.mccall@gmail.com>
Tue, 28 Jun 2022 14:24:38 +0000 (16:24 +0200)
committerSam McCall <sam.mccall@gmail.com>
Tue, 28 Jun 2022 14:34:21 +0000 (16:34 +0200)
clang-tools-extra/pseudo/benchmarks/Benchmark.cpp
clang-tools-extra/pseudo/fuzzer/Fuzzer.cpp
clang-tools-extra/pseudo/gen/Main.cpp
clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h
clang-tools-extra/pseudo/lib/cxx/CXX.cpp
clang-tools-extra/pseudo/lib/grammar/GrammarBNF.cpp
clang-tools-extra/pseudo/tool/ClangPseudo.cpp
clang-tools-extra/pseudo/unittests/ForestTest.cpp
clang-tools-extra/pseudo/unittests/GLRTest.cpp
clang-tools-extra/pseudo/unittests/GrammarTest.cpp
clang-tools-extra/pseudo/unittests/LRTableTest.cpp

index 6002bad..a06fde7 100644 (file)
@@ -67,7 +67,7 @@ void setupGrammarAndSource() {
   GrammarText = new std::string(ReadFile(GrammarFile));
   SourceText = new std::string(ReadFile(Source));
   std::vector<std::string> Diags;
-  G = Grammar::parseBNF(*GrammarText, Diags).release();
+  G = new Grammar(Grammar::parseBNF(*GrammarText, Diags));
 }
 
 static void parseBNF(benchmark::State &State) {
index 5836783..d56ccd0 100644 (file)
@@ -24,7 +24,7 @@ namespace {
 
 class Fuzzer {
   clang::LangOptions LangOpts = clang::pseudo::genericLangOpts();
-  std::unique_ptr<Grammar> G;
+  Grammar G;
   LRTable T;
   bool Print;
 
@@ -44,7 +44,7 @@ public:
         llvm::errs() << Diag << "\n";
       std::exit(1);
     }
-    T = LRTable::buildSLR(*G);
+    T = LRTable::buildSLR(G);
   }
 
   void operator()(llvm::StringRef Code) {
@@ -59,10 +59,10 @@ public:
     clang::pseudo::ForestArena Arena;
     clang::pseudo::GSS GSS;
     auto &Root =
-        glrParse(ParseableStream, clang::pseudo::ParseParams{*G, T, Arena, GSS},
-                 *G->findNonterminal("translation-unit"));
+        glrParse(ParseableStream, clang::pseudo::ParseParams{G, T, Arena, GSS},
+                 *G.findNonterminal("translation-unit"));
     if (Print)
-      llvm::outs() << Root.dumpRecursive(*G);
+      llvm::outs() << Root.dumpRecursive(G);
   }
 };
 
index 38cb7f4..5964cc8 100644 (file)
@@ -79,9 +79,9 @@ int main(int argc, char *argv[]) {
 
   switch (Emit) {
   case EmitSymbolList:
-    for (clang::pseudo::SymbolID ID = 0; ID < G->table().Nonterminals.size();
+    for (clang::pseudo::SymbolID ID = 0; ID < G.table().Nonterminals.size();
          ++ID) {
-      std::string Name = G->symbolName(ID).str();
+      std::string Name = G.symbolName(ID).str();
       // translation-unit -> translation_unit
       std::replace(Name.begin(), Name.end(), '-', '_');
       Out.os() << llvm::formatv("NONTERMINAL({0}, {1})\n", Name, ID);
index 8137734..382da41 100644 (file)
@@ -138,12 +138,12 @@ struct GrammarTable;
 // It is a building block for constructing a table-based parser.
 class Grammar {
 public:
+  Grammar() = default; // Creates an invalid dummy grammar.
   explicit Grammar(std::unique_ptr<GrammarTable>);
 
   // Parses grammar from a BNF file.
   // Diagnostics emitted during parsing are stored in Diags.
-  static std::unique_ptr<Grammar> parseBNF(llvm::StringRef BNF,
-                                           std::vector<std::string> &Diags);
+  static Grammar parseBNF(llvm::StringRef BNF, std::vector<std::string> &Diags);
 
   // Returns the SymbolID of the symbol '_'.
   SymbolID underscore() const { return Underscore; };
index bcf350c..88c2e0f 100644 (file)
@@ -19,7 +19,7 @@ static const char *CXXBNF =
 
 const Grammar &getGrammar() {
   static std::vector<std::string> Diags;
-  static Grammar *G = Grammar::parseBNF(CXXBNF, Diags).release();
+  static Grammar *G = new Grammar(Grammar::parseBNF(CXXBNF, Diags));
   assert(Diags.empty());
   return *G;
 }
index bf5d06f..9fbc34d 100644 (file)
@@ -28,7 +28,7 @@ public:
   GrammarBuilder(std::vector<std::string> &Diagnostics)
       : Diagnostics(Diagnostics) {}
 
-  std::unique_ptr<Grammar> build(llvm::StringRef BNF) {
+  Grammar build(llvm::StringRef BNF) {
     auto Specs = eliminateOptional(parse(BNF));
 
     assert(llvm::all_of(Specs,
@@ -122,8 +122,8 @@ public:
         ++End;
       T->Nonterminals[SID].RuleRange = {Start, End};
     }
-    auto G = std::make_unique<Grammar>(std::move(T));
-    diagnoseGrammar(*G);
+    Grammar G(std::move(T));
+    diagnoseGrammar(G);
     return G;
   }
 
@@ -341,8 +341,8 @@ private:
 };
 } // namespace
 
-std::unique_ptr<Grammar>
-Grammar::parseBNF(llvm::StringRef BNF, std::vector<std::string> &Diagnostics) {
+Grammar Grammar::parseBNF(llvm::StringRef BNF,
+                          std::vector<std::string> &Diagnostics) {
   Diagnostics.clear();
   return GrammarBuilder(Diagnostics).build(BNF);
 }
index a9c972a..39ad751 100644 (file)
@@ -105,12 +105,12 @@ int main(int argc, char *argv[]) {
     llvm::outs() << llvm::formatv("grammar file {0} is parsed successfully\n",
                                   Grammar);
     if (PrintGrammar)
-      llvm::outs() << G->dump();
+      llvm::outs() << G.dump();
     if (PrintGraph)
-      llvm::outs() << clang::pseudo::LRGraph::buildLR0(*G).dumpForTests(*G);
-    auto LRTable = clang::pseudo::LRTable::buildSLR(*G);
+      llvm::outs() << clang::pseudo::LRGraph::buildLR0(G).dumpForTests(G);
+    auto LRTable = clang::pseudo::LRTable::buildSLR(G);
     if (PrintTable)
-      llvm::outs() << LRTable.dumpForTests(*G);
+      llvm::outs() << LRTable.dumpForTests(G);
     if (PrintStatistics)
       llvm::outs() << LRTable.dumpStatistics();
 
@@ -118,17 +118,17 @@ int main(int argc, char *argv[]) {
       clang::pseudo::ForestArena Arena;
       clang::pseudo::GSS GSS;
       llvm::Optional<clang::pseudo::SymbolID> StartSymID =
-          G->findNonterminal(StartSymbol);
+          G.findNonterminal(StartSymbol);
       if (!StartSymID) {
         llvm::errs() << llvm::formatv(
             "The start symbol {0} doesn't exit in the grammar!\n", Grammar);
         return 2;
       }
       auto &Root = glrParse(*ParseableStream,
-                            clang::pseudo::ParseParams{*G, LRTable, Arena, GSS},
+                            clang::pseudo::ParseParams{G, LRTable, Arena, GSS},
                             *StartSymID);
       if (PrintForest)
-        llvm::outs() << Root.dumpRecursive(*G, /*Abbreviated=*/true);
+        llvm::outs() << Root.dumpRecursive(G, /*Abbreviated=*/true);
 
       if (PrintStatistics) {
         llvm::outs() << "Forest bytes: " << Arena.bytes()
index f382e07..ae038f9 100644 (file)
@@ -28,19 +28,19 @@ public:
 
   SymbolID symbol(llvm::StringRef Name) const {
     for (unsigned I = 0; I < NumTerminals; ++I)
-      if (G->table().Terminals[I] == Name)
+      if (G.table().Terminals[I] == Name)
         return tokenSymbol(static_cast<tok::TokenKind>(I));
-    for (SymbolID ID = 0; ID < G->table().Nonterminals.size(); ++ID)
-      if (G->table().Nonterminals[ID].Name == Name)
+    for (SymbolID ID = 0; ID < G.table().Nonterminals.size(); ++ID)
+      if (G.table().Nonterminals[ID].Name == Name)
         return ID;
     ADD_FAILURE() << "No such symbol found: " << Name;
     return 0;
   }
 
   RuleID ruleFor(llvm::StringRef NonterminalName) const {
-    auto RuleRange = G->table().Nonterminals[symbol(NonterminalName)].RuleRange;
+    auto RuleRange = G.table().Nonterminals[symbol(NonterminalName)].RuleRange;
     if (RuleRange.End - RuleRange.Start == 1)
-      return G->table().Nonterminals[symbol(NonterminalName)].RuleRange.Start;
+      return G.table().Nonterminals[symbol(NonterminalName)].RuleRange.Start;
     ADD_FAILURE() << "Expected a single rule for " << NonterminalName
                   << ", but it has " << RuleRange.End - RuleRange.Start
                   << " rule!\n";
@@ -48,7 +48,7 @@ public:
   }
 
 protected:
-  std::unique_ptr<Grammar> G;
+  Grammar G;
   std::vector<std::string> Diags;
 };
 
@@ -73,12 +73,12 @@ TEST_F(ForestTest, DumpBasic) {
   const auto *Add =
       &Arena.createSequence(symbol("add-expression"), ruleFor("add-expression"),
                             {Left, &T[1], Right});
-  EXPECT_EQ(Add->dumpRecursive(*G, true),
+  EXPECT_EQ(Add->dumpRecursive(G, true),
             "[  0, end) add-expression := id-expression + id-expression\n"
             "[  0,   1) ├─id-expression~IDENTIFIER := tok[0]\n"
             "[  1,   2) ├─+ := tok[1]\n"
             "[  2, end) └─id-expression~IDENTIFIER := tok[2]\n");
-  EXPECT_EQ(Add->dumpRecursive(*G, false),
+  EXPECT_EQ(Add->dumpRecursive(G, false),
             "[  0, end) add-expression := id-expression + id-expression\n"
             "[  0,   1) ├─id-expression := IDENTIFIER\n"
             "[  0,   1) │ └─IDENTIFIER := tok[0]\n"
@@ -114,7 +114,7 @@ TEST_F(ForestTest, DumpAmbiguousAndRefs) {
       &Arena.createSequence(symbol("type"), /*RuleID=*/4, {EnumType});
   const auto *Type =
       &Arena.createAmbiguous(symbol("type"), {Alternative1, Alternative2});
-  EXPECT_EQ(Type->dumpRecursive(*G),
+  EXPECT_EQ(Type->dumpRecursive(G),
             "[  0, end) type := <ambiguous>\n"
             "[  0, end) ├─type := class-type\n"
             "[  0, end) │ └─class-type := shared-type\n"
index 42e2f0a..846f2db 100644 (file)
@@ -66,19 +66,19 @@ public:
 
   SymbolID id(llvm::StringRef Name) const {
     for (unsigned I = 0; I < NumTerminals; ++I)
-      if (G->table().Terminals[I] == Name)
+      if (G.table().Terminals[I] == Name)
         return tokenSymbol(static_cast<tok::TokenKind>(I));
-    for (SymbolID ID = 0; ID < G->table().Nonterminals.size(); ++ID)
-      if (G->table().Nonterminals[ID].Name == Name)
+    for (SymbolID ID = 0; ID < G.table().Nonterminals.size(); ++ID)
+      if (G.table().Nonterminals[ID].Name == Name)
         return ID;
     ADD_FAILURE() << "No such symbol found: " << Name;
     return 0;
   }
 
   RuleID ruleFor(llvm::StringRef NonterminalName) const {
-    auto RuleRange = G->table().Nonterminals[id(NonterminalName)].RuleRange;
+    auto RuleRange = G.table().Nonterminals[id(NonterminalName)].RuleRange;
     if (RuleRange.End - RuleRange.Start == 1)
-      return G->table().Nonterminals[id(NonterminalName)].RuleRange.Start;
+      return G.table().Nonterminals[id(NonterminalName)].RuleRange.Start;
     ADD_FAILURE() << "Expected a single rule for " << NonterminalName
                   << ", but it has " << RuleRange.End - RuleRange.Start
                   << " rule!\n";
@@ -86,7 +86,7 @@ public:
   }
 
 protected:
-  std::unique_ptr<Grammar> G;
+  Grammar G;
   ForestArena Arena;
   GSS GSStack;
 };
@@ -113,7 +113,7 @@ TEST_F(GLRTest, ShiftMergingHeads) {
 
   buildGrammar({}, {}); // Create a fake empty grammar.
   LRTable T =
-      LRTable::buildForTests(*G, /*Entries=*/
+      LRTable::buildForTests(G, /*Entries=*/
                              {
                                  {1, tokenSymbol(tok::semi), Action::shift(4)},
                                  {2, tokenSymbol(tok::semi), Action::shift(4)},
@@ -123,8 +123,8 @@ TEST_F(GLRTest, ShiftMergingHeads) {
 
   ForestNode &SemiTerminal = Arena.createTerminal(tok::semi, 0);
   std::vector<const GSS::Node *> NewHeads;
-  glrShift({GSSNode1, GSSNode2, GSSNode3}, SemiTerminal,
-           {*G, T, Arena, GSStack}, NewHeads);
+  glrShift({GSSNode1, GSSNode2, GSSNode3}, SemiTerminal, {G, T, Arena, GSStack},
+           NewHeads);
 
   EXPECT_THAT(NewHeads,
               UnorderedElementsAre(AllOf(state(4), parsedSymbol(&SemiTerminal),
@@ -145,7 +145,7 @@ TEST_F(GLRTest, ReduceConflictsSplitting) {
                {"class-name := IDENTIFIER", "enum-name := IDENTIFIER"});
 
   LRTable Table = LRTable::buildForTests(
-      *G,
+      G,
       {
           {/*State=*/0, id("class-name"), Action::goTo(2)},
           {/*State=*/0, id("enum-name"), Action::goTo(3)},
@@ -161,7 +161,7 @@ TEST_F(GLRTest, ReduceConflictsSplitting) {
       GSStack.addNode(1, &Arena.createTerminal(tok::identifier, 0), {GSSNode0});
 
   std::vector<const GSS::Node *> Heads = {GSSNode1};
-  glrReduce(Heads, tokenSymbol(tok::eof), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::eof), {G, Table, Arena, GSStack});
   EXPECT_THAT(Heads, UnorderedElementsAre(
                          GSSNode1,
                          AllOf(state(2), parsedSymbolID(id("class-name")),
@@ -193,7 +193,7 @@ TEST_F(GLRTest, ReduceSplittingDueToMultipleBases) {
       /*Parents=*/{GSSNode2, GSSNode3});
 
   LRTable Table = LRTable::buildForTests(
-      *G,
+      G,
       {
           {/*State=*/2, id("ptr-operator"), Action::goTo(/*NextState=*/5)},
           {/*State=*/3, id("ptr-operator"), Action::goTo(/*NextState=*/6)},
@@ -202,7 +202,7 @@ TEST_F(GLRTest, ReduceSplittingDueToMultipleBases) {
           {/*State=*/4, ruleFor("ptr-operator")},
       });
   std::vector<const GSS::Node *> Heads = {GSSNode4};
-  glrReduce(Heads, tokenSymbol(tok::eof), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::eof), {G, Table, Arena, GSStack});
 
   EXPECT_THAT(Heads, UnorderedElementsAre(
                          GSSNode4,
@@ -247,7 +247,7 @@ TEST_F(GLRTest, ReduceJoiningWithMultipleBases) {
 
   // FIXME: figure out a way to get rid of the hard-coded reduce RuleID!
   LRTable Table = LRTable::buildForTests(
-      *G,
+      G,
       {
           {/*State=*/1, id("type-name"), Action::goTo(/*NextState=*/5)},
           {/*State=*/2, id("type-name"), Action::goTo(/*NextState=*/5)},
@@ -257,7 +257,7 @@ TEST_F(GLRTest, ReduceJoiningWithMultipleBases) {
           {/*State=*/4, /* type-name := enum-name */ 1},
       });
   std::vector<const GSS::Node *> Heads = {GSSNode3, GSSNode4};
-  glrReduce(Heads, tokenSymbol(tok::eof), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::eof), {G, Table, Arena, GSStack});
 
   // Verify that the stack heads are joint at state 5 after reduces.
   EXPECT_THAT(Heads, UnorderedElementsAre(GSSNode3, GSSNode4,
@@ -266,7 +266,7 @@ TEST_F(GLRTest, ReduceJoiningWithMultipleBases) {
                                                 parents({GSSNode1, GSSNode2}))))
       << Heads;
   // Verify that we create an ambiguous ForestNode of two parses of `type-name`.
-  EXPECT_EQ(Heads.back()->Payload->dumpRecursive(*G),
+  EXPECT_EQ(Heads.back()->Payload->dumpRecursive(G),
             "[  1, end) type-name := <ambiguous>\n"
             "[  1, end) ├─type-name := class-name\n"
             "[  1, end) │ └─class-name := <opaque>\n"
@@ -305,7 +305,7 @@ TEST_F(GLRTest, ReduceJoiningWithSameBase) {
 
   // FIXME: figure out a way to get rid of the hard-coded reduce RuleID!
   LRTable Table =
-      LRTable::buildForTests(*G,
+      LRTable::buildForTests(G,
                              {
                                  {/*State=*/0, id("pointer"), Action::goTo(5)},
                              },
@@ -314,14 +314,14 @@ TEST_F(GLRTest, ReduceJoiningWithSameBase) {
                                  {4, /* pointer := enum-name */ 1},
                              });
   std::vector<const GSS::Node *> Heads = {GSSNode3, GSSNode4};
-  glrReduce(Heads, tokenSymbol(tok::eof), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::eof), {G, Table, Arena, GSStack});
 
   EXPECT_THAT(
       Heads, UnorderedElementsAre(GSSNode3, GSSNode4,
                                   AllOf(state(5), parsedSymbolID(id("pointer")),
                                         parents({GSSNode0}))))
       << Heads;
-  EXPECT_EQ(Heads.back()->Payload->dumpRecursive(*G),
+  EXPECT_EQ(Heads.back()->Payload->dumpRecursive(G),
             "[  0, end) pointer := <ambiguous>\n"
             "[  0, end) ├─pointer := class-name *\n"
             "[  0,   1) │ ├─class-name := <opaque>\n"
@@ -335,7 +335,7 @@ TEST_F(GLRTest, ReduceLookahead) {
   // A term can be followed by +, but not by -.
   buildGrammar({"sum", "term"}, {"expr := term + term", "term := IDENTIFIER"});
   LRTable Table =
-      LRTable::buildForTests(*G,
+      LRTable::buildForTests(G,
                              {
                                  {/*State=*/0, id("term"), Action::goTo(2)},
                              },
@@ -352,14 +352,14 @@ TEST_F(GLRTest, ReduceLookahead) {
 
   // When the lookahead is +, reduce is performed.
   std::vector<const GSS::Node *> Heads = {GSSNode1};
-  glrReduce(Heads, tokenSymbol(tok::plus), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::plus), {G, Table, Arena, GSStack});
   EXPECT_THAT(Heads,
               ElementsAre(GSSNode1, AllOf(state(2), parsedSymbolID(id("term")),
                                           parents(Root))));
 
   // When the lookahead is -, reduce is not performed.
   Heads = {GSSNode1};
-  glrReduce(Heads, tokenSymbol(tok::minus), {*G, Table, Arena, GSStack});
+  glrReduce(Heads, tokenSymbol(tok::minus), {G, Table, Arena, GSStack});
   EXPECT_THAT(Heads, ElementsAre(GSSNode1));
 }
 
@@ -382,26 +382,25 @@ TEST_F(GLRTest, PerfectForestNodeSharing) {
   )bnf");
   clang::LangOptions LOptions;
   const TokenStream &Tokens = cook(lex("{ abc", LOptions), LOptions);
-  auto LRTable = LRTable::buildSLR(*G);
+  auto LRTable = LRTable::buildSLR(G);
 
   const ForestNode &Parsed =
-      glrParse(Tokens, {*G, LRTable, Arena, GSStack}, id("test"));
+      glrParse(Tokens, {G, LRTable, Arena, GSStack}, id("test"));
   // Verify that there is no duplicated sequence node of `expr := IDENTIFIER`
   // in the forest, see the `#1` and `=#1` in the dump string.
-  EXPECT_EQ(Parsed.dumpRecursive(*G),
-            "[  0, end) test := <ambiguous>\n"
-            "[  0, end) ├─test := { expr\n"
-            "[  0,   1) │ ├─{ := tok[0]\n"
-            "[  1, end) │ └─expr := IDENTIFIER #1\n"
-            "[  1, end) │   └─IDENTIFIER := tok[1]\n"
-            "[  0, end) ├─test := { IDENTIFIER\n"
-            "[  0,   1) │ ├─{ := tok[0]\n"
-            "[  1, end) │ └─IDENTIFIER := tok[1]\n"
-            "[  0, end) └─test := left-paren expr\n"
-            "[  0,   1)   ├─left-paren := {\n"
-            "[  0,   1)   │ └─{ := tok[0]\n"
-            "[  1, end)   └─expr := IDENTIFIER =#1\n"
-            "[  1, end)     └─IDENTIFIER := tok[1]\n");
+  EXPECT_EQ(Parsed.dumpRecursive(G), "[  0, end) test := <ambiguous>\n"
+                                     "[  0, end) ├─test := { expr\n"
+                                     "[  0,   1) │ ├─{ := tok[0]\n"
+                                     "[  1, end) │ └─expr := IDENTIFIER #1\n"
+                                     "[  1, end) │   └─IDENTIFIER := tok[1]\n"
+                                     "[  0, end) ├─test := { IDENTIFIER\n"
+                                     "[  0,   1) │ ├─{ := tok[0]\n"
+                                     "[  1, end) │ └─IDENTIFIER := tok[1]\n"
+                                     "[  0, end) └─test := left-paren expr\n"
+                                     "[  0,   1)   ├─left-paren := {\n"
+                                     "[  0,   1)   │ └─{ := tok[0]\n"
+                                     "[  1, end)   └─expr := IDENTIFIER =#1\n"
+                                     "[  1, end)     └─IDENTIFIER := tok[1]\n");
 }
 
 TEST_F(GLRTest, GLRReduceOrder) {
@@ -420,17 +419,16 @@ TEST_F(GLRTest, GLRReduceOrder) {
   )bnf");
   clang::LangOptions LOptions;
   const TokenStream &Tokens = cook(lex("IDENTIFIER", LOptions), LOptions);
-  auto LRTable = LRTable::buildSLR(*G);
+  auto LRTable = LRTable::buildSLR(G);
 
   const ForestNode &Parsed =
-      glrParse(Tokens, {*G, LRTable, Arena, GSStack}, id("test"));
-  EXPECT_EQ(Parsed.dumpRecursive(*G),
-            "[  0, end) test := <ambiguous>\n"
-            "[  0, end) ├─test := IDENTIFIER\n"
-            "[  0, end) │ └─IDENTIFIER := tok[0]\n"
-            "[  0, end) └─test := foo\n"
-            "[  0, end)   └─foo := IDENTIFIER\n"
-            "[  0, end)     └─IDENTIFIER := tok[0]\n");
+      glrParse(Tokens, {G, LRTable, Arena, GSStack}, id("test"));
+  EXPECT_EQ(Parsed.dumpRecursive(G), "[  0, end) test := <ambiguous>\n"
+                                     "[  0, end) ├─test := IDENTIFIER\n"
+                                     "[  0, end) │ └─IDENTIFIER := tok[0]\n"
+                                     "[  0, end) └─test := foo\n"
+                                     "[  0, end)   └─foo := IDENTIFIER\n"
+                                     "[  0, end)     └─IDENTIFIER := tok[0]\n");
 }
 
 TEST_F(GLRTest, NoExplicitAccept) {
@@ -445,15 +443,14 @@ TEST_F(GLRTest, NoExplicitAccept) {
   // of the nonterminal `test` when the next token is `eof`, verify that the
   // parser stops at the right state.
   const TokenStream &Tokens = cook(lex("id id", LOptions), LOptions);
-  auto LRTable = LRTable::buildSLR(*G);
+  auto LRTable = LRTable::buildSLR(G);
 
   const ForestNode &Parsed =
-      glrParse(Tokens, {*G, LRTable, Arena, GSStack}, id("test"));
-  EXPECT_EQ(Parsed.dumpRecursive(*G),
-            "[  0, end) test := IDENTIFIER test\n"
-            "[  0,   1) ├─IDENTIFIER := tok[0]\n"
-            "[  1, end) └─test := IDENTIFIER\n"
-            "[  1, end)   └─IDENTIFIER := tok[1]\n");
+      glrParse(Tokens, {G, LRTable, Arena, GSStack}, id("test"));
+  EXPECT_EQ(Parsed.dumpRecursive(G), "[  0, end) test := IDENTIFIER test\n"
+                                     "[  0,   1) ├─IDENTIFIER := tok[0]\n"
+                                     "[  1, end) └─test := IDENTIFIER\n"
+                                     "[  1, end)   └─IDENTIFIER := tok[1]\n");
 }
 
 TEST(GSSTest, GC) {
index 284d91e..3f59539 100644 (file)
@@ -35,19 +35,19 @@ public:
 
   SymbolID id(llvm::StringRef Name) const {
     for (unsigned I = 0; I < NumTerminals; ++I)
-      if (G->table().Terminals[I] == Name)
+      if (G.table().Terminals[I] == Name)
         return tokenSymbol(static_cast<tok::TokenKind>(I));
-    for (SymbolID ID = 0; ID < G->table().Nonterminals.size(); ++ID)
-      if (G->table().Nonterminals[ID].Name == Name)
+    for (SymbolID ID = 0; ID < G.table().Nonterminals.size(); ++ID)
+      if (G.table().Nonterminals[ID].Name == Name)
         return ID;
     ADD_FAILURE() << "No such symbol found: " << Name;
     return 0;
   }
 
   RuleID ruleFor(llvm::StringRef NonterminalName) const {
-    auto RuleRange = G->table().Nonterminals[id(NonterminalName)].RuleRange;
+    auto RuleRange = G.table().Nonterminals[id(NonterminalName)].RuleRange;
     if (RuleRange.End - RuleRange.Start == 1)
-      return G->table().Nonterminals[id(NonterminalName)].RuleRange.Start;
+      return G.table().Nonterminals[id(NonterminalName)].RuleRange.Start;
     ADD_FAILURE() << "Expected a single rule for " << NonterminalName
                   << ", but it has " << RuleRange.End - RuleRange.Start
                   << " rule!\n";
@@ -55,7 +55,7 @@ public:
   }
 
 protected:
-  std::unique_ptr<Grammar> G;
+  Grammar G;
   std::vector<std::string> Diags;
 };
 
@@ -65,19 +65,19 @@ TEST_F(GrammarTest, Basic) {
 
   auto ExpectedRule =
       AllOf(TargetID(id("_")), Sequence(id("IDENTIFIER"), id("+"), id("_")));
-  EXPECT_EQ(G->symbolName(id("_")), "_");
-  EXPECT_THAT(G->rulesFor(id("_")), UnorderedElementsAre(ExpectedRule));
-  const auto &Rule = G->lookupRule(/*RID=*/0);
+  EXPECT_EQ(G.symbolName(id("_")), "_");
+  EXPECT_THAT(G.rulesFor(id("_")), UnorderedElementsAre(ExpectedRule));
+  const auto &Rule = G.lookupRule(/*RID=*/0);
   EXPECT_THAT(Rule, ExpectedRule);
-  EXPECT_THAT(G->symbolName(Rule.seq()[0]), "IDENTIFIER");
-  EXPECT_THAT(G->symbolName(Rule.seq()[1]), "+");
-  EXPECT_THAT(G->symbolName(Rule.seq()[2]), "_");
+  EXPECT_THAT(G.symbolName(Rule.seq()[0]), "IDENTIFIER");
+  EXPECT_THAT(G.symbolName(Rule.seq()[1]), "+");
+  EXPECT_THAT(G.symbolName(Rule.seq()[2]), "_");
 }
 
 TEST_F(GrammarTest, EliminatedOptional) {
   build("_ := CONST_opt INT ;_opt");
   EXPECT_THAT(Diags, IsEmpty());
-  EXPECT_THAT(G->table().Rules,
+  EXPECT_THAT(G.table().Rules,
               UnorderedElementsAre(Sequence(id("INT")),
                                    Sequence(id("CONST"), id("INT")),
                                    Sequence(id("CONST"), id("INT"), id(";")),
@@ -108,11 +108,10 @@ TEST_F(GrammarTest, Annotation) {
 
   )bnf");
   ASSERT_TRUE(Diags.empty());
-  EXPECT_EQ(G->lookupRule(ruleFor("_")).Guard, 0);
-  EXPECT_GT(G->lookupRule(ruleFor("x")).Guard, 0);
-  EXPECT_GT(G->lookupRule(ruleFor("y")).Guard, 0);
-  EXPECT_NE(G->lookupRule(ruleFor("x")).Guard,
-            G->lookupRule(ruleFor("y")).Guard);
+  EXPECT_EQ(G.lookupRule(ruleFor("_")).Guard, 0);
+  EXPECT_GT(G.lookupRule(ruleFor("x")).Guard, 0);
+  EXPECT_GT(G.lookupRule(ruleFor("y")).Guard, 0);
+  EXPECT_NE(G.lookupRule(ruleFor("x")).Guard, G.lookupRule(ruleFor("y")).Guard);
 }
 
 TEST_F(GrammarTest, Diagnostics) {
@@ -130,7 +129,7 @@ TEST_F(GrammarTest, Diagnostics) {
     _ := IDENTIFIER [unknown=value]
   )cpp");
 
-  EXPECT_EQ(G->underscore(), id("_"));
+  EXPECT_EQ(G.underscore(), id("_"));
   EXPECT_THAT(Diags, UnorderedElementsAre(
                          "Rule '_ := ,_opt' has a nullable RHS",
                          "Rule 'null := ' has a nullable RHS",
@@ -160,13 +159,13 @@ term := ( expr )
   };
 
   EXPECT_THAT(
-      ToPairs(firstSets(*G)),
+      ToPairs(firstSets(G)),
       UnorderedElementsAre(
           Pair(id("_"), UnorderedElementsAre(id("IDENTIFIER"), id("("))),
           Pair(id("expr"), UnorderedElementsAre(id("IDENTIFIER"), id("("))),
           Pair(id("term"), UnorderedElementsAre(id("IDENTIFIER"), id("(")))));
   EXPECT_THAT(
-      ToPairs(followSets(*G)),
+      ToPairs(followSets(G)),
       UnorderedElementsAre(
           Pair(id("_"), UnorderedElementsAre(id("EOF"))),
           Pair(id("expr"), UnorderedElementsAre(id("-"), id("EOF"), id(")"))),
@@ -183,7 +182,7 @@ simple-type-specifier := INT
    )bnf");
   ASSERT_TRUE(Diags.empty());
   EXPECT_THAT(
-      ToPairs(firstSets(*G)),
+      ToPairs(firstSets(G)),
       UnorderedElementsAre(
           Pair(id("_"), UnorderedElementsAre(id("INLINE"), id("INT"))),
           Pair(id("decl-specifier-seq"),
@@ -192,7 +191,7 @@ simple-type-specifier := INT
           Pair(id("decl-specifier"),
                UnorderedElementsAre(id("INLINE"), id("INT")))));
   EXPECT_THAT(
-      ToPairs(followSets(*G)),
+      ToPairs(followSets(G)),
       UnorderedElementsAre(
           Pair(id("_"), UnorderedElementsAre(id("EOF"))),
           Pair(id("decl-specifier-seq"), UnorderedElementsAre(id("EOF"))),
index e44be1a..f317bcb 100644 (file)
@@ -24,16 +24,16 @@ using Action = LRTable::Action;
 
 TEST(LRTable, Builder) {
   std::vector<std::string> GrammarDiags;
-  auto G = Grammar::parseBNF(R"bnf(
+  Grammar G = Grammar::parseBNF(R"bnf(
     _ := expr            # rule 0
     expr := term         # rule 1
     expr := expr + term  # rule 2
     term := IDENTIFIER   # rule 3
   )bnf",
-                             GrammarDiags);
+                                GrammarDiags);
   EXPECT_THAT(GrammarDiags, testing::IsEmpty());
 
-  SymbolID Term = *G->findNonterminal("term");
+  SymbolID Term = *G.findNonterminal("term");
   SymbolID Eof = tokenSymbol(tok::eof);
   SymbolID Identifier = tokenSymbol(tok::identifier);
   SymbolID Plus = tokenSymbol(tok::plus);
@@ -53,7 +53,7 @@ TEST(LRTable, Builder) {
       {/*State=*/1, /*Rule=*/2},
       {/*State=*/2, /*Rule=*/1},
   };
-  LRTable T = LRTable::buildForTests(*G, Entries, ReduceEntries);
+  LRTable T = LRTable::buildForTests(G, Entries, ReduceEntries);
   EXPECT_EQ(T.getShiftState(0, Eof), llvm::None);
   EXPECT_THAT(T.getShiftState(0, Identifier), ValueIs(0));
   EXPECT_THAT(T.getReduceRules(0), ElementsAre(0));