1 | //===--- LRTable.cpp - Parsing table for LR parsers --------------*- 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 "llvm/ADT/ArrayRef.h" |
12 | #include "llvm/ADT/STLExtras.h" |
13 | #include "llvm/ADT/StringExtras.h" |
14 | #include "llvm/Support/FormatVariadic.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | |
17 | namespace clang { |
18 | namespace pseudo { |
19 | |
20 | std::string LRTable::dumpStatistics() const { |
21 | return llvm::formatv(Fmt: R"( |
22 | Statistics of the LR parsing table: |
23 | number of states: {0} |
24 | number of actions: shift={1} goto={2} reduce={3} |
25 | size of the table (bytes): {4} |
26 | )" , |
27 | Vals: numStates(), Vals: Shifts.size(), Vals: Gotos.size(), Vals: Reduces.size(), |
28 | Vals: bytes()) |
29 | .str(); |
30 | } |
31 | |
32 | std::string LRTable::dumpForTests(const Grammar &G) const { |
33 | std::string Result; |
34 | llvm::raw_string_ostream OS(Result); |
35 | OS << "LRTable:\n" ; |
36 | for (StateID S = 0; S < numStates(); ++S) { |
37 | OS << llvm::formatv(Fmt: "State {0}\n" , Vals&: S); |
38 | for (uint16_t Terminal = 0; Terminal < NumTerminals; ++Terminal) { |
39 | SymbolID TokID = tokenSymbol(TK: static_cast<tok::TokenKind>(Terminal)); |
40 | if (auto SS = getShiftState(State: S, Terminal: TokID)) |
41 | OS.indent(NumSpaces: 4) << llvm::formatv(Fmt: "{0}: shift state {1}\n" , |
42 | Vals: G.symbolName(TokID), Vals&: SS); |
43 | } |
44 | for (RuleID R : getReduceRules(State: S)) { |
45 | SymbolID Target = G.lookupRule(RID: R).Target; |
46 | std::vector<llvm::StringRef> Terminals; |
47 | for (unsigned Terminal = 0; Terminal < NumTerminals; ++Terminal) { |
48 | SymbolID TokID = tokenSymbol(TK: static_cast<tok::TokenKind>(Terminal)); |
49 | if (canFollow(Nonterminal: Target, Terminal: TokID)) |
50 | Terminals.push_back(x: G.symbolName(TokID)); |
51 | } |
52 | OS.indent(NumSpaces: 4) << llvm::formatv(Fmt: "{0}: reduce by rule {1} '{2}'\n" , |
53 | Vals: llvm::join(R&: Terminals, Separator: " " ), Vals&: R, |
54 | Vals: G.dumpRule(R)); |
55 | } |
56 | for (SymbolID NontermID = 0; NontermID < G.table().Nonterminals.size(); |
57 | ++NontermID) { |
58 | if (auto GS = getGoToState(State: S, Nonterminal: NontermID)) { |
59 | OS.indent(NumSpaces: 4) << llvm::formatv(Fmt: "{0}: go to state {1}\n" , |
60 | Vals: G.symbolName(NontermID), Vals&: *GS); |
61 | } |
62 | } |
63 | } |
64 | return OS.str(); |
65 | } |
66 | |
67 | LRTable::StateID LRTable::getStartState(SymbolID Target) const { |
68 | assert(llvm::is_sorted(StartStates) && "StartStates must be sorted!" ); |
69 | auto It = llvm::partition_point( |
70 | Range: StartStates, P: [Target](const std::pair<SymbolID, StateID> &X) { |
71 | return X.first < Target; |
72 | }); |
73 | assert(It != StartStates.end() && It->first == Target && |
74 | "target symbol doesn't have a start state!" ); |
75 | return It->second; |
76 | } |
77 | |
78 | } // namespace pseudo |
79 | } // namespace clang |
80 | |