1 //===--- LRTableTest.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/grammar/LRTable.h"
10 #include "clang-pseudo/grammar/Grammar.h"
11 #include "clang/Basic/TokenKinds.h"
12 #include "llvm/Testing/Support/SupportHelpers.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 #include <vector>
16 
17 namespace clang {
18 namespace pseudo {
19 namespace {
20 
21 using llvm::ValueIs;
22 using testing::ElementsAre;
23 using StateID = LRTable::StateID;
24 
TEST(LRTable,Builder)25 TEST(LRTable, Builder) {
26   std::vector<std::string> GrammarDiags;
27   Grammar G = Grammar::parseBNF(R"bnf(
28     _ := expr            # rule 0
29     expr := term         # rule 1
30     expr := expr + term  # rule 2
31     term := IDENTIFIER   # rule 3
32   )bnf",
33                                 GrammarDiags);
34   EXPECT_THAT(GrammarDiags, testing::IsEmpty());
35 
36   SymbolID Term = *G.findNonterminal("term");
37   SymbolID Eof = tokenSymbol(tok::eof);
38   SymbolID Identifier = tokenSymbol(tok::identifier);
39   SymbolID Plus = tokenSymbol(tok::plus);
40 
41   LRTable::Builder B(G);
42   //           eof  IDENT   term
43   // +-------+----+-------+------+
44   // |state0 |    | s0    |      |
45   // |state1 |    |       | g3   |
46   // |state2 |    |       |      |
47   // +-------+----+-------+------+-------
48   B.Transition[{StateID{0}, Identifier}] = StateID{0};
49   B.Transition[{StateID{1}, Term}] = StateID{3};
50   B.Reduce[StateID{0}].insert(RuleID{0});
51   B.Reduce[StateID{1}].insert(RuleID{2});
52   B.Reduce[StateID{2}].insert(RuleID{1});
53   LRTable T = std::move(B).build();
54 
55   EXPECT_EQ(T.getShiftState(0, Eof), llvm::None);
56   EXPECT_THAT(T.getShiftState(0, Identifier), ValueIs(0));
57   EXPECT_THAT(T.getReduceRules(0), ElementsAre(0));
58 
59   EXPECT_EQ(T.getShiftState(1, Eof), llvm::None);
60   EXPECT_EQ(T.getShiftState(1, Identifier), llvm::None);
61   EXPECT_THAT(T.getGoToState(1, Term), ValueIs(3));
62   EXPECT_THAT(T.getReduceRules(1), ElementsAre(2));
63 
64   // Verify the behaivor for other non-available-actions terminals.
65   SymbolID Int = tokenSymbol(tok::kw_int);
66   EXPECT_EQ(T.getShiftState(2, Int), llvm::None);
67 
68   // Check follow sets.
69   EXPECT_TRUE(T.canFollow(Term, Plus));
70   EXPECT_TRUE(T.canFollow(Term, Eof));
71   EXPECT_FALSE(T.canFollow(Term, Int));
72 }
73 
74 } // namespace
75 } // namespace pseudo
76 } // namespace clang
77