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 Action = LRTable::Action; 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 // eof IDENT term 42 // +-------+----+-------+------+ 43 // |state0 | | s0 | | 44 // |state1 | | | g3 | 45 // |state2 | | | | 46 // +-------+----+-------+------+------- 47 std::vector<LRTable::Entry> Entries = { 48 {/* State */ 0, Identifier, Action::shift(0)}, 49 {/* State */ 1, Term, Action::goTo(3)}, 50 }; 51 std::vector<LRTable::ReduceEntry> ReduceEntries = { 52 {/*State=*/0, /*Rule=*/0}, 53 {/*State=*/1, /*Rule=*/2}, 54 {/*State=*/2, /*Rule=*/1}, 55 }; 56 LRTable T = LRTable::buildForTests(G, Entries, ReduceEntries); 57 EXPECT_EQ(T.getShiftState(0, Eof), llvm::None); 58 EXPECT_THAT(T.getShiftState(0, Identifier), ValueIs(0)); 59 EXPECT_THAT(T.getReduceRules(0), ElementsAre(0)); 60 61 EXPECT_EQ(T.getShiftState(1, Eof), llvm::None); 62 EXPECT_EQ(T.getShiftState(1, Identifier), llvm::None); 63 EXPECT_EQ(T.getGoToState(1, Term), 3); 64 EXPECT_THAT(T.getReduceRules(1), ElementsAre(2)); 65 66 // Verify the behaivor for other non-available-actions terminals. 67 SymbolID Int = tokenSymbol(tok::kw_int); 68 EXPECT_EQ(T.getShiftState(2, Int), llvm::None); 69 70 // Check follow sets. 71 EXPECT_TRUE(T.canFollow(Term, Plus)); 72 EXPECT_TRUE(T.canFollow(Term, Eof)); 73 EXPECT_FALSE(T.canFollow(Term, Int)); 74 } 75 76 } // namespace 77 } // namespace pseudo 78 } // namespace clang 79