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";
}
protected:
- std::unique_ptr<Grammar> G;
+ Grammar G;
ForestArena Arena;
GSS GSStack;
};
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)},
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),
{"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)},
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")),
/*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)},
{/*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,
// 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)},
{/*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,
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"
// 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)},
},
{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"
// 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)},
},
// 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));
}
)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) {
)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) {
// 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) {
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";
}
protected:
- std::unique_ptr<Grammar> G;
+ Grammar G;
std::vector<std::string> Diags;
};
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(";")),
)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) {
_ := 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",
};
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(")"))),
)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"),
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"))),