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 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