@@ -19,6 +19,7 @@ namespace {
1919using testing::AllOf;
2020using testing::ElementsAre;
2121using testing::IsEmpty;
22+ using testing::Pair;
2223using testing::UnorderedElementsAre;
2324
2425MATCHER_P (TargetID, SID, " " ) { return arg.Target == SID; }
@@ -33,7 +34,7 @@ class GrammarTest : public ::testing::Test {
3334 G = Grammar::parseBNF (BNF, Diags);
3435 }
3536
36- SymbolID lookup (llvm::StringRef Name) const {
37+ SymbolID id (llvm::StringRef Name) const {
3738 for (unsigned I = 0 ; I < NumTerminals; ++I)
3839 if (G->table ().Terminals [I] == Name)
3940 return tokenSymbol (static_cast <tok::TokenKind>(I));
@@ -50,31 +51,28 @@ class GrammarTest : public ::testing::Test {
5051};
5152
5253TEST_F (GrammarTest, Basic) {
53- build (" expression := IDENTIFIER + expression # comment" );
54+ build (" _ := IDENTIFIER + _ # comment" );
5455 EXPECT_THAT (Diags, IsEmpty ());
5556
5657 auto ExpectedRule =
57- AllOf (TargetID (lookup (" expression" )),
58- Sequence (lookup (" IDENTIFIER" ), lookup (" +" ), lookup (" expression" )));
59- auto ExpressionID = lookup (" expression" );
60- EXPECT_EQ (G->symbolName (ExpressionID), " expression" );
61- EXPECT_THAT (G->rulesFor (ExpressionID), UnorderedElementsAre (ExpectedRule));
58+ AllOf (TargetID (id (" _" )), Sequence (id (" IDENTIFIER" ), id (" +" ), id (" _" )));
59+ EXPECT_EQ (G->symbolName (id (" _" )), " _" );
60+ EXPECT_THAT (G->rulesFor (id (" _" )), UnorderedElementsAre (ExpectedRule));
6261 const auto &Rule = G->lookupRule (/* RID=*/ 0 );
6362 EXPECT_THAT (Rule, ExpectedRule);
6463 EXPECT_THAT (G->symbolName (Rule.seq ()[0 ]), " IDENTIFIER" );
6564 EXPECT_THAT (G->symbolName (Rule.seq ()[1 ]), " +" );
66- EXPECT_THAT (G->symbolName (Rule.seq ()[2 ]), " expression " );
65+ EXPECT_THAT (G->symbolName (Rule.seq ()[2 ]), " _ " );
6766}
6867
6968TEST_F (GrammarTest, EliminatedOptional) {
7069 build (" _ := CONST_opt INT ;_opt" );
7170 EXPECT_THAT (Diags, IsEmpty ());
7271 EXPECT_THAT (G->table ().Rules ,
73- UnorderedElementsAre (
74- Sequence (lookup (" INT" )),
75- Sequence (lookup (" CONST" ), lookup (" INT" )),
76- Sequence (lookup (" CONST" ), lookup (" INT" ), lookup (" ;" )),
77- Sequence (lookup (" INT" ), lookup (" ;" ))));
72+ UnorderedElementsAre (Sequence (id (" INT" )),
73+ Sequence (id (" CONST" ), id (" INT" )),
74+ Sequence (id (" CONST" ), id (" INT" ), id (" ;" )),
75+ Sequence (id (" INT" ), id (" ;" ))));
7876}
7977
8078TEST_F (GrammarTest, Diagnostics) {
@@ -87,6 +85,7 @@ TEST_F(GrammarTest, Diagnostics) {
8785 invalid
8886 )cpp" );
8987
88+ EXPECT_EQ (G->startSymbol (), id (" _" ));
9089 EXPECT_THAT (Diags, UnorderedElementsAre (
9190 " Rule '_ := ,_opt' has a nullable RHS" ,
9291 " Rule 'null := ' has a nullable RHS" ,
@@ -96,6 +95,66 @@ TEST_F(GrammarTest, Diagnostics) {
9695 " No rules for nonterminal: IDENFIFIE" ));
9796}
9897
98+ TEST_F (GrammarTest, FirstAndFollowSets) {
99+ build (
100+ R"bnf(
101+ _ := expr
102+ expr := expr - term
103+ expr := term
104+ term := IDENTIFIER
105+ term := ( expr )
106+ )bnf" );
107+ ASSERT_TRUE (Diags.empty ());
108+ auto ToPairs = [](std::vector<llvm::DenseSet<SymbolID>> Input) {
109+ std::vector<std::pair<SymbolID, llvm::DenseSet<SymbolID>>> Sets;
110+ for (SymbolID ID = 0 ; ID < Input.size (); ++ID)
111+ Sets.emplace_back (ID, std::move (Input[ID]));
112+ return Sets;
113+ };
114+
115+ EXPECT_THAT (
116+ ToPairs (firstSets (*G)),
117+ UnorderedElementsAre (
118+ Pair (id (" _" ), UnorderedElementsAre (id (" IDENTIFIER" ), id (" (" ))),
119+ Pair (id (" expr" ), UnorderedElementsAre (id (" IDENTIFIER" ), id (" (" ))),
120+ Pair (id (" term" ), UnorderedElementsAre (id (" IDENTIFIER" ), id (" (" )))));
121+ EXPECT_THAT (
122+ ToPairs (followSets (*G)),
123+ UnorderedElementsAre (
124+ Pair (id (" _" ), UnorderedElementsAre (id (" EOF" ))),
125+ Pair (id (" expr" ), UnorderedElementsAre (id (" -" ), id (" EOF" ), id (" )" ))),
126+ Pair (id (" term" ), UnorderedElementsAre (id (" -" ), id (" EOF" ), id (" )" )))));
127+
128+ build (R"bnf(
129+ # A simplfied C++ decl-specifier-seq.
130+ _ := decl-specifier-seq
131+ decl-specifier-seq := decl-specifier decl-specifier-seq
132+ decl-specifier-seq := decl-specifier
133+ decl-specifier := simple-type-specifier
134+ decl-specifier := INLINE
135+ simple-type-specifier := INT
136+ )bnf" );
137+ ASSERT_TRUE (Diags.empty ());
138+ EXPECT_THAT (
139+ ToPairs (firstSets (*G)),
140+ UnorderedElementsAre (
141+ Pair (id (" _" ), UnorderedElementsAre (id (" INLINE" ), id (" INT" ))),
142+ Pair (id (" decl-specifier-seq" ),
143+ UnorderedElementsAre (id (" INLINE" ), id (" INT" ))),
144+ Pair (id (" simple-type-specifier" ), UnorderedElementsAre (id (" INT" ))),
145+ Pair (id (" decl-specifier" ),
146+ UnorderedElementsAre (id (" INLINE" ), id (" INT" )))));
147+ EXPECT_THAT (
148+ ToPairs (followSets (*G)),
149+ UnorderedElementsAre (
150+ Pair (id (" _" ), UnorderedElementsAre (id (" EOF" ))),
151+ Pair (id (" decl-specifier-seq" ), UnorderedElementsAre (id (" EOF" ))),
152+ Pair (id (" decl-specifier" ),
153+ UnorderedElementsAre (id (" INLINE" ), id (" INT" ), id (" EOF" ))),
154+ Pair (id (" simple-type-specifier" ),
155+ UnorderedElementsAre (id (" INLINE" ), id (" INT" ), id (" EOF" )))));
156+ }
157+
99158} // namespace
100159} // namespace pseudo
101160} // namespace syntax
0 commit comments