-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.h
More file actions
384 lines (321 loc) · 11.4 KB
/
Copy pathparser.h
File metadata and controls
384 lines (321 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#ifndef _DC_PARSER_HPP_
#define _DC_PARSER_HPP_
#include "../lexer/simple_lexer.hpp"
#include "../lexer/text_info.h"
#include "../lexer/token.h"
#include "parser_error.h"
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <ostream>
#include <set>
#include <tuple>
#include <vector>
using dchar_t = std::shared_ptr<DChar>;
using dctoken_t = std::shared_ptr<LexerToken>;
class NonTerminal : public DChar
{};
using dnonterm_t = std::shared_ptr<NonTerminal>;
size_t GetEOFChar();
struct RuleOption;
enum RuleAssocitive
{
RuleAssocitiveLeft,
RuleAssocitiveRight,
};
struct PushdownStateMapping;
struct PushdownEntry;
class DCParser
{
public:
class DCParserContext
{
private:
DCParser* m_parser;
public:
inline DCParserContext() : m_parser(nullptr) {};
inline DCParserContext(DCParser& parser) : m_parser(&parser)
{}
DCParserContext& operator=(const DCParserContext&) = delete;
DCParserContext(const DCParserContext&) = delete;
inline DCParser* parser()
{
return this->m_parser;
}
virtual ~DCParserContext() = default;
};
using pcontext_t = std::weak_ptr<DCParserContext>;
class DCParserRulePriority
{
private:
friend class DCParser;
size_t m_priority;
DCParserRulePriority() = delete;
DCParserRulePriority(const DCParserRulePriority&) = delete;
DCParserRulePriority& operator=(const DCParserRulePriority&) = delete;
DCParserRulePriority& operator=(DCParserRulePriority&&) = delete;
DCParserRulePriority(size_t priority);
size_t priority() const;
public:
DCParserRulePriority(DCParserRulePriority&&) = default;
;
virtual ~DCParserRulePriority();
};
using priority_t = std::shared_ptr<DCParserRulePriority>;
class RuleDecision
{
public:
virtual bool decide_on_pos(size_t pos) const;
virtual bool decide_on_end() const;
virtual bool decide(pcontext_t context,
const std::vector<dchar_t>& vx,
const std::vector<dchar_t>& charstack) = 0;
virtual ~RuleDecision() = default;
};
using decision_t = std::shared_ptr<RuleDecision>;
using charid_t = size_t;
using ruleid_t = size_t;
using state_t = size_t;
using context_t = std::shared_ptr<DCParserContext>;
using reduce_callback_t =
std::function<dnonterm_t(pcontext_t context, std::vector<dchar_t>& children)>;
class ParserChar
{
private:
DCharInfo _info;
bool _optional;
public:
ParserChar() = delete;
inline ParserChar(DCharInfo info) : _info(info), _optional(false)
{}
inline const char* name() const
{
return _info.name;
}
inline charid_t cid() const
{
return this->_info.id;
}
inline DCharInfo info() const
{
return this->_info;
}
inline bool optional() const
{
return this->_optional;
}
static inline ParserChar beOptional(DCharInfo info)
{
auto c = ParserChar(info);
c._optional = true;
return c;
}
static inline ParserChar beOptional(ParserChar c)
{
c._optional = true;
return c;
}
};
private:
struct RuleInfo
{
charid_t m_lhs;
std::vector<charid_t> m_rhs;
std::vector<bool> m_rhs_optional;
reduce_callback_t m_reduce_callback;
std::shared_ptr<RuleOption> m_rule_option;
};
std::vector<RuleInfo> m_rules;
context_t m_context;
std::set<charid_t> m_nonterms;
std::set<charid_t> m_terms;
std::set<charid_t> m_symbols;
std::set<charid_t> m_start_symbols;
size_t m_priority;
template<typename T>
class SetStateAllocator
{
private:
using setelem = T;
state_t m_next_state;
std::map<std::set<setelem>, state_t> m_state_map;
public:
SetStateAllocator() : m_next_state(0)
{}
SetStateAllocator(const SetStateAllocator&) = delete;
SetStateAllocator& operator=(const SetStateAllocator&) = delete;
SetStateAllocator(SetStateAllocator&&) = delete;
SetStateAllocator& operator=(SetStateAllocator&&) = delete;
const std::map<std::set<setelem>, state_t>& themap() const
{
return this->m_state_map;
}
state_t query(const std::set<setelem>& states)
{
auto it = this->m_state_map.find(states);
if (it != this->m_state_map.end()) {
return it->second;
}
auto new_state = this->m_next_state++;
this->m_state_map[states] = new_state;
return new_state;
}
state_t operator()(const std::set<setelem>& states)
{
return this->query(states);
}
size_t max_state() const
{
return this->m_next_state;
}
};
std::shared_ptr<PushdownEntry>
state_action(std::set<std::pair<ruleid_t, size_t>> state,
bool evaluate_decision,
SetStateAllocator<std::pair<ruleid_t, size_t>>& state_allocator,
std::set<std::set<std::pair<ruleid_t, size_t>>>& new_state_set);
bool m_lookahead_rule_propagation;
std::shared_ptr<PushdownStateMapping> m_pds_mapping;
std::optional<state_t> m_start_state;
std::vector<std::set<std::pair<ruleid_t, size_t>>> h_state2set;
std::map<charid_t, DCharInfo> h_charinfo;
std::shared_ptr<TextInfo> h_textinfo;
std::ostream* h_debug_stream;
void see_dchar(DCharInfo char_);
DCharInfo get_dchar(charid_t id) const;
std::string help_rule2str(ruleid_t rule, size_t pos) const;
std::string help_when_reject_at(state_t state, charid_t token) const;
std::string help_print_state(state_t state, size_t count, char paddingchar) const;
void help_print_unseen_rules_into_debug_stream() const;
std::vector<state_t> p_state_stack;
std::vector<dchar_t> p_char_stack;
std::optional<std::pair<dchar_t, const PushdownEntry*>> p_not_finished;
std::optional<charid_t> m_real_start_symbol;
void setup_real_start_symbol();
void do_shift(state_t state, dchar_t char_);
std::optional<dchar_t> do_reduce(ruleid_t rule_id, dchar_t char_);
std::optional<dchar_t> handle_lookahead(dctoken_t token);
void feed_internal(dchar_t char_);
private:
// Rules for creating that non-terminal
std::map<charid_t, std::vector<ruleid_t>> u_nonterm_epsilon_closure;
// no pratical use
std::map<charid_t, std::set<charid_t>> u_nonterm_possible_next;
void ensure_epsilon_closure();
std::set<std::pair<ruleid_t, size_t>>
stateset_epsilon_closure(const std::set<std::pair<ruleid_t, size_t>>& st);
bool u_possible_prev_next_computed;
void compute_posible_prev_next();
std::map<charid_t, std::set<charid_t>> u_prev_possible_token_of;
std::map<charid_t, std::set<charid_t>> u_next_possible_token_of;
std::set<std::pair<ruleid_t, size_t>>
stateset_move(const std::set<std::pair<ruleid_t, size_t>>& stateset, charid_t symbol) const;
bool is_nonterm(charid_t id) const;
std::set<std::pair<ruleid_t, size_t>> startState() const;
int add_rule_internal(charid_t leftside,
std::vector<charid_t> rightside,
std::vector<bool> optional,
reduce_callback_t reduce_cb,
RuleAssocitive associative,
decision_t decision,
std::set<size_t> positions,
priority_t priority);
using PreAction =
std::function<std::optional<dctoken_t>(const std::vector<dchar_t>& symbolStack, dctoken_t)>;
PreAction m_preAction;
void collect_expected_next_chars(state_t state, std::set<charid_t>& expectedNextTokens) const;
using RecoverFromRejectFn = std::function<std::optional<std::pair<int, size_t>>(
const std::vector<dchar_t>& symbolStack, const std::vector<dctoken_t>& nextNTokens)>;
RecoverFromRejectFn m_recFn;
std::vector<dctoken_t> m_prevSave;
std::optional<ParserRejectTokenError> m_need_recover;
std::optional<bool> recover_from_reject();
public:
DCParser(bool lookahead_rule_propagation = true);
DCParser(const DCParser&) = delete;
DCParser& operator=(const DCParser&) = delete;
DCParser(DCParser&&) = delete;
DCParser& operator=(DCParser&&) = delete;
virtual ~DCParser();
priority_t dec_priority();
inline priority_t __________()
{
return this->dec_priority();
}
inline void setContext(context_t context)
{
this->m_context = context;
}
inline context_t getContext()
{
return this->m_context;
}
inline const context_t getContext() const
{
return this->m_context;
}
void setDebugStream(std::ostream& stream);
void SetTextinfo(std::shared_ptr<TextInfo> info);
void setPreAction(PreAction fn)
{
m_preAction = fn;
}
void setRecoverFn(RecoverFromRejectFn fn)
{
m_recFn = fn;
}
std::set<charid_t> get_expected_chars() const;
void add_rule(DCharInfo leftside,
std::vector<ParserChar> rightside,
reduce_callback_t reduce_cb,
RuleAssocitive associative,
decision_t decision,
priority_t priority);
DCParser& operator()(DCharInfo leftside,
std::vector<ParserChar> rightside,
reduce_callback_t reduce_cb,
RuleAssocitive associative = RuleAssocitiveLeft,
decision_t decision = nullptr,
priority_t priority = nullptr);
void add_start_symbol(charid_t start);
void generate_table();
std::set<charid_t> prev_possible_token_of(charid_t id) const;
std::set<charid_t> next_possible_token_of(charid_t id) const;
DCharInfo query_charinfo(charid_t id) const;
void feed(dctoken_t token);
dnonterm_t end();
template<typename Iterator>
dnonterm_t parse(Iterator begin, Iterator end)
{
assert(m_start_state.has_value());
assert(this->p_state_stack.empty());
for (auto it = begin; it != end; ++it) {
this->feed(*it);
}
return this->end();
}
dnonterm_t parse(ISimpleLexer& lexer);
void reset();
};
using ParserChar = DCParser::ParserChar;
class RuleDecisionFunction : public DCParser::RuleDecision
{
public:
using pcontext_t = typename DCParser::pcontext_t;
using decider_t = std::function<bool(pcontext_t context,
const std::vector<dchar_t>& vx,
const std::vector<dchar_t>& char_stack)>;
private:
decider_t m_decider;
std::set<size_t> m_positions;
bool m_on_end;
public:
RuleDecisionFunction(decider_t decider, std::set<size_t> positions = {}, bool on_end = true);
virtual bool decide_on_pos(size_t pos) const override;
virtual bool decide_on_end() const override;
virtual bool decide(pcontext_t context,
const std::vector<dchar_t>& vx,
const std::vector<dchar_t>& char_stack) override;
};
#endif // _DC_PARSER_HPP_