bux API Reference 1.9.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
GLR.cpp
Go to the documentation of this file.
1#include "GLR.h"
2#include "StrUtil.h" // HRTN()
3#include <format> // std::format()
4
5namespace bux {
6namespace GLR {
7
8//
9// Implement Classes
10//
12{
13 return false;
14}
15
16bool I_ParserPolicy::getTokenName(T_LexID, std::string &) const
17{
18 return false;
19}
20
21std::string I_ParserPolicy::printToken(T_LexID token) const
22{
23 std::string name;
24 if (getTokenName(token, name))
25 return name;
26
27 switch (token)
28 {
29 case TID_EOF:
30 return "bux::TID_EOF";
31 case ROOT_NID:
32 return "<@> aka bux::ROOT_NID";
33 default:
34 if (token >= TOKENGEN_LB)
35 return std::format("bux::TOKENGEN_LB+{}", token - TOKENGEN_LB);
36
37 auto out = std::format("0x{:x}", token);
38 if (isascii(int(token)))
39 out.append(" or \'").append(asciiLiteral(token)) += '\'';
40
41 return out;
42 }
43}
44
45C_Parser::C_Parser(const I_ParserPolicy &policy): m_policy(policy)
46{
47}
48
49C_Parser::C_Parser(C_Parser &root, const C_StateLR1Ptr &nestedTop):
50 m_policy(root.m_policy),
51 m_userData(root.m_userData)
52{
53 m_curTops.emplace_back(nestedTop);
54}
55
56void C_Parser::add(T_LexID token, unsigned line, unsigned col, I_LexAttr *unownedAttr)
57{
58 C_LexInfo info;
59 info.m_attr.reset(unownedAttr);
60 info.m_pos.m_Source = m_srcPath;
61 info.m_pos.m_Line = line;
62 info.m_pos.m_Col = col;
63
64 if (!m_accepted.empty())
65 onError(info, "Already accepted");
66
67 std::vector<std::pair<C_StateLR1Ptr,F_OncePostShift>> reduced;
68 C_StateLR1Ptrs nextTops;
69Again:
70 C_StateLR1Ptrs curTops{m_curTops};
71 while (!reduced.empty() || !curTops.empty() || !m_added)
72 {
73 m_added = true;
74
75 C_StateLR1Ptr iTop;
76 F_OncePostShift iPostShift;
77 if (!reduced.empty())
78 {
79 std::tie(iTop,iPostShift) = reduced.back();
80 reduced.pop_back();
81 }
82 else if (!curTops.empty())
83 {
84 iTop = curTops.back();
85 curTops.pop_back();
86 }
87 const auto fromState = state(iTop);
88 for (auto j: m_policy.action(fromState, token))
89 switch (j)
90 {
91 case ACTION_SHIFT:
92 {
93 C_StateLR1Ptr t{new C_StateLR1};
94 t->m_prev = iTop;
95 t->m_StateID = m_policy.nextState(fromState, token);
96 t->m_TokenID = token;
97 static_cast<C_LexInfo&>(*t) = info;
98 if (!iPostShift)
99 nextTops.emplace_back(t);
100 else
101 {
102 C_Parser nestedGLR{*this, t};
103 iPostShift(nestedGLR);
104 nextTops.insert(nextTops.end(), nestedGLR.m_curTops.begin(), nestedGLR.m_curTops.end());
105 m_accepted.insert(m_accepted.end(), nestedGLR.m_accepted.begin(), nestedGLR.m_accepted.end());
106 }
107 }
108 break;
109 case ACTION_ACCEPT:
110 if (!iPostShift)
111 {
112 if (auto ret = reduceOn(m_policy.getAcceptId(), iTop, info))
113 m_accepted.push_back(ret->first); // ret->second not checked
114 else
115 onError(info, "Reduction error on acception");
116 }
117 else
118 {
119 C_Parser nestedGLR{*this, iTop};
120 iPostShift(nestedGLR);
121 for (auto &k: nestedGLR.m_curTops)
122 m_accepted.push_back(k);
123
124 if (!nestedGLR.m_accepted.empty())
125 onError(info, "Doubly accepted");
126 }
127 break;
128 default:
129 if (j >= ACTION_REDUCE_MIN)
130 {
131 const size_t prodId = j - ACTION_REDUCE_MIN;
132 if (auto ret = reduceOn(prodId, iTop, info))
133 {
134 if (ret->second)
135 reduced.emplace_back(*ret);
136 else
137 curTops.emplace_back(ret->first);
138 }
139 else
140 onError(info, "Reduction error on production "+std::to_string(prodId));
141 }
142 else
143 onError(info, "Unknown action id "+std::to_string(j));
144 }
145 }
146 if (nextTops.empty() && m_accepted.empty())
147 // No action - Try recovery coups or claim error
148 {
149 if (m_policy.changeToken(token, info.m_attr))
150 goto Again;
151
152 auto out = "Syntax error on token=" + m_policy.printToken(token);
153 if (auto *attr = info.m_attr.get())
154 out.append(" of attr type ").append(HRTN(*attr));
155 else
156 out += " with null attr";
157
158 if (const auto n = m_curTops.size())
159 {
160 out += "\nStack dump";
161 if (n > 1)
162 out += std::format(" on {} paths", n);
163
164 out += ':';
165 size_t ind{};
166 for (auto i: m_curTops)
167 {
168 out += std::format("\nPath[{}]:", ind++);
169 while (i)
170 {
171 out += std::format("\n({},{})\t", i->m_pos.m_Line, i->m_pos.m_Col);
172 if (i->m_attr)
173 out += HRTN(*i->m_attr);
174
175 out += std::format("\ts={}\tt={}", i->m_StateID, m_policy.printToken(i->m_TokenID));
176 i = i->m_prev;
177 }
178 }
179 }
180 return onError(info, out);
181 }
182 m_curTops.swap(nextTops);
183}
184
185void C_Parser::eachAccepted(std::function<void(C_LexPtr &)> apply)
186{
187 for (auto &i: m_accepted)
188 apply(i->m_attr);
189}
190
191void C_Parser::onError(const C_SourcePos &pos, std::string_view message)
192{
193 m_policy.onError(*this, pos, message);
194}
195
196auto C_Parser::reduceOn(size_t id, C_StateLR1Ptr iTop, const C_SourcePos &pos) -> std::optional<T_Reduced>
197{
199 m_policy.getReduceInfo(id, ri);
200 C_StateLR1Ptrs arr;
201 const size_t size = ri.m_PopLength;
202 while (arr.size() < size)
203 {
204 if (!iTop)
205 return {};
206
207 arr.emplace_back(iTop);
208 iTop = iTop->m_prev;
209 }
210
211 C_StateLR1Ptr r{new C_StateLR1};
213 if (ri.m_Reduce)
214 ri.m_Reduce(*this, [&](size_t n)->C_LexInfo& {
215 if (n >= size)
216 onError(pos, "Production["+std::to_string(id)+"] out of range "+std::to_string(n)+'/'+std::to_string(size));
217
218 return *arr.rbegin()[int(n)];
219 }, r->m_attr, ps);
220
221 r->m_pos = size? arr.back()->m_pos: pos;
222 r->m_prev = iTop;
223 const auto curStateId = state(iTop);
224 r->m_StateID = ri.m_ResultID != ROOT_NID? m_policy.nextState(curStateId, ri.m_ResultID): curStateId;
225 r->m_TokenID = ri.m_ResultID;
226 return std::optional<T_Reduced>{std::in_place, r, ps};
227}
228
229std::string_view C_Parser::setSource(std::string_view src)
230{
231 const auto ret = m_srcPath;
232 m_srcPath = src;
233 return ret;
234}
235
236T_StateID C_Parser::state(C_StateLR1Ptr &p)
237{
238 return p? p->m_StateID: decltype(p->m_StateID){};
239}
240
241C_Parser::C_StateLR1::C_StateLR1(C_StateLR1 &another):
242 C_LexInfo(another),
243 m_StateID(another.m_StateID),
244 m_TokenID(another.m_TokenID)
245{
246}
247
248void C_Parser::C_StateLR1::operator=(C_StateLR1 &another)
249{
250 C_LexInfo::operator=(another);
251 m_StateID =another.m_StateID;
252 m_TokenID =another.m_TokenID;
253}
254
255} // namespace GLR
256} // namespace bux
#define HRTN(t)
Definition StrUtil.h:22
std::string_view setSource(std::string_view src) override
Definition GLR.cpp:229
C_Parser(const I_ParserPolicy &policy)
Definition GLR.cpp:45
const I_ParserPolicy & m_policy
Definition GLR.h:63
void onError(const C_SourcePos &pos, std::string_view message)
Definition GLR.cpp:191
void eachAccepted(std::function< void(C_LexPtr &)> apply)
Definition GLR.cpp:185
void add(T_LexID token, unsigned line, unsigned col, I_LexAttr *unownedAttr) override
Definition GLR.cpp:56
C_LexInfoT< const I_LexAttr, std::shared_ptr > C_LexInfo
Definition GLR.h:26
std::function< void(C_Parser &parser)> F_OncePostShift
Definition GLR.h:30
std::shared_ptr< const I_LexAttr > C_LexPtr
Definition GLR.h:25
@ ACTION_SHIFT
Definition GLR.h:16
@ ACTION_ACCEPT
Definition GLR.h:17
@ ACTION_REDUCE_MIN
Definition GLR.h:18
THE common namespace of bux library.
Definition AtomiX.cpp:3
@ TOKENGEN_LB
Definition LexBase.h:29
@ TID_EOF
Definition LexBase.h:25
@ ROOT_NID
Definition LexBase.h:26
std::string asciiLiteral(uint32_t utf32)
Definition LexBase.cpp:98
uint32_t T_LexID
Definition LexBase.h:35
unsigned T_StateID
Definition ParserBase.h:17
C_LexInfoT & operator=(C_LexInfoT &another)
Definition LexBase.h:61
C_SourcePos m_pos
Definition LexBase.h:56
C_Ptr< T > m_attr
Definition LexBase.h:55
unsigned m_Col
Definition LexBase.h:42
std::string_view m_Source
Definition LexBase.h:40
unsigned m_Line
Definition LexBase.h:41
std::string printToken(T_LexID token) const
Definition GLR.cpp:21
virtual bool getTokenName(T_LexID token, std::string &name) const
Definition GLR.cpp:16
virtual std::vector< T_ActionId > action(T_StateID state, T_LexID token) const =0
virtual size_t getAcceptId() const =0
virtual void onError(C_Parser &parser, const C_SourcePos &pos, std::string_view message) const =0
virtual T_StateID nextState(T_StateID state, T_LexID lex) const =0
virtual bool changeToken(T_LexID &token, C_LexPtr &attr) const
Definition GLR.cpp:11