MyLang
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
myparser_rule.hpp
Go to the documentation of this file.
1 #ifndef MYPARSER_RULE_HPP
2 #define MYPARSER_RULE_HPP
3 
4 #include "myparser_str.hpp"
5 #include "myparser_ast_plus.hpp"
6 
7 namespace myparser {
8 
9 using BuiltinRoot = MP_STR("root", 4);
10 using BuiltinSpace = MP_STR("space", 5);
11 using BuiltinKeyword = MP_STR("keyword", 7);
12 using BuiltinError = MP_STR("error", 5);
13 
14 using ErrorList = MP_STR("Nothing matched", 15);
15 using ErrorRegex = MP_STR("Regex not matched", 17);
16 using ErrorChecking = MP_STR("Match not accepted", 18);
17 using ErrorKeyword = MP_STR("Bad keyword", 11);
18 
19 template <size_t L, size_t M>
20 class Tag {
21 public:
22  static const size_t least = L;
23  static const size_t most = M;
24 };
29 
30 class Rule {
31 protected:
32  inline Rule() {} // force singleton
33 
34  // virtual ~Rule() {}
35 };
36 
37 template <class N>
38 class RuleNamed: public Rule {
39 protected:
40  inline RuleNamed(): Rule() {}
41 
42  // virtual ~RuleNamed() {}
43 };
44 
45 // need specialization
46 template <class N>
47 class RuleDef: public RuleNamed<N> {
48 public:
49  static std::pair<Node *, Node *> parse(
50  Input &input, const Input &end
51  );
52 };
53 
54 template <>
55 class RuleDef<BuiltinError>: public RuleNamed<BuiltinError> {};
56 
58 
59 template <class N, class... RL>
60 class RuleList: public RuleNamed<N> {
61 private:
62  template <size_t I, class R, class... Rx>
63  static MYPARSER_INLINE std::pair<Node *, Node *> runRule(
64  Input &input, const Input &end
65  ) {
66  using Member =
67  typename R
68  ::template Helper<N, I>;
69 
70  Input input_rev = input;
71 
72  auto current = Member::parse(input, end);
73 
74  if (current.first) {
75  return current;
76  } else {
77  input = input_rev;
78 
79  auto next = runRule<I + 1, Rx...>(input, end);
80 
81  if (!next.second) {
82  return {next.first, current.second};
83  } else {
84  return {
85  next.first,
86  next.second->challengeLonger(current.second)
87  };
88  }
89  }
90  }
91 
92  template <size_t I> // iteration finished
93  static MYPARSER_INLINE std::pair<Node *, Node *> runRule(
94  Input &input, const Input &end
95  ) {
96  (void) end;
97 
98  return {
99  nullptr,
101  };
102  }
103 
104 protected:
106 
107  // virtual ~RuleList() {}
108 
109 public:
110  static std::pair<Node *, Node *> parse(
111  Input &input, const Input &end
112  ) {
113  return runRule<0, RL...>(input, end);
114  }
115 };
116 
117 template <class N, class RX>
118 class RuleRegex: public RuleNamed<N> {
119 private:
120  static MYPARSER_INLINE std::pair<Node *, Node *> runRegex(
121  Input &input, const Input &end
122  ) {
123  #if defined(MYPARSER_BOOST_XPRESSIVE)
124  static const regex_lib::basic_regex<Input> re =
125  regex_lib::basic_regex<Input>::compile<Input>(
126  RX::getStr().cbegin(),
127  RX::getStr().cend()
128  );
129  #else
130  static const regex_lib::regex re(
131  RX::getStr()
132  );
133  #endif
134 
135  regex_lib::match_results<Input> mdata;
136 
137  if (
138  regex_lib::regex_search(
139  input, end, mdata, re,
140  regex_lib::regex_constants::match_continuous
141  )
142  ) {
143  std::string str = mdata.str();
144  input += str.size();
145 
146  NodeTextTyped<N> *result =
147  new NodeTextTyped<N>(input, std::move(str));
148 
149  if (result->accepted()) {
150  return {result, nullptr};
151  } else {
152  delete result;
153 
154  return {
155  nullptr,
157  };
158  }
159  } else {
160  return {
161  nullptr,
163  };
164  }
165  }
166 
167 protected:
169 
170  // virtual ~RuleRegex() {}
171 
172 public:
173  static std::pair<Node *, Node *> parse(
174  Input &input, const Input &end
175  ) {
176  return runRegex(input, end);
177  }
178 };
179 
181 
182 template <class N = BuiltinSpace, class TAG = TagNormal>
183 class RuleItemSpace: public TAG {
184 public:
185  static MYPARSER_INLINE std::pair<Node *, Node *> parse(
186  Input &input, const Input &end
187  ) {
188  return RuleDef<N>::parse(input, end);
189  }
190 };
191 
192 template <class KW, class N = BuiltinKeyword, class TAG = TagNormal>
193 class RuleItemKeyword: public TAG {
194 public:
195  static MYPARSER_INLINE std::pair<Node *, Node *> parse(
196  Input &input, const Input &end
197  ) {
198  auto current = RuleDef<N>::parse(input, end);
199 
200  if (
201  current.first
202  &&
203  current.first->getFullText() == KW::getStr()
204  ) {
205  return current;
206  } else {
207  if (current.first) {
208  current.first->free();
209  }
210 
211  return {
212  nullptr,
214  ->challengeLonger(current.second)
215  };
216  }
217  }
218 };
219 
220 template <class N, class TAG = TagNormal>
221 class RuleItemRef: public TAG {
222 public:
223  static MYPARSER_INLINE std::pair<Node *, Node *> parse(
224  Input &input, const Input &end
225  ) {
226  return RuleDef<N>::parse(input, end);
227  }
228 };
229 
230 template <class E, class TAG = TagNormal>
231 class RuleItemError: public TAG {
232 public:
233  static MYPARSER_INLINE std::pair<Node *, Node *> parse(
234  Input &input, const Input &end
235  ) {
236  (void) end;
237 
238  return {
239  nullptr,
241  };
242  }
243 };
244 
246 
247 template <class... RL>
248 class RuleLine {
249 public:
250  template <class N, size_t I>
251  class Helper {
252  private:
253  template <class R, class... Rx>
255  NodeListTyped<N, I> *&result, Node *&err, size_t &errpos,
256  Input &input, const Input &end
257  ) {
258  for (size_t i = 0; i < R::most; ++i) {
259  auto current = R::parse(input, end);
260 
261  if (current.second) {
262  err = current.second->challengeLonger(err);
263 
264  // if err updated
265  if (err == current.second) {
266  errpos = result->getChildren().size();
267  }
268  }
269 
270  if (!current.first) {
271  if (i < R::least) {
272  return false;
273  } else {
274  break;
275  }
276  } else {
277  result->putChild(current.first);
278  }
279  }
280 
281  return runRule<Rx...>(result, err, errpos, input, end);
282  }
283 
284  template <std::nullptr_t P = nullptr> // iteration finished
286  NodeListTyped<N, I> *&result, Node *&err, size_t &errpos,
287  Input &input, const Input &end
288  ) {
289  (void) result;
290  (void) err;
291  (void) errpos;
292  (void) input;
293  (void) end;
294 
295  return true;
296  }
297 
298  public:
299  static MYPARSER_INLINE std::pair<Node *, Node *> parse(
300  Input &input, const Input &end
301  ) {
302  NodeListTyped<N, I> *result = new NodeListTyped<N, I>(input);
303  NodeListTyped<N, I> *result_err = new NodeListTyped<N, I>(input);
304  Node *err = nullptr;
305  size_t errpos = 0;
306 
307  bool succeed = runRule<RL...>(result, err, errpos, input, end);
308 
309  result->bind(result_err, errpos);
310  result_err->bind(result, errpos);
311 
312  if (err) {
313  for (size_t i = 0; i < errpos; ++i) {
314  result_err->putChild(result->getChildren()[i]);
315  }
316  result_err->putChild(err);
317  } else {
318  result_err->free();
319  result_err = nullptr;
320  }
321 
322  if (!succeed) {
323  result->free();
324  result = nullptr;
325  }
326 
327  return {result, result_err};
328  }
329  };
330 };
331 
332 template <class N = BuiltinRoot>
333 class Parser {
334 public:
335  static inline Node *parse(Input &input, const Input &end) {
336  auto current = RuleDef<N>::parse(input, end);
337 
338  if (current.first) {
339  if (current.second) {
340  current.second->free();
341  }
342 
343  return current.first;
344  } else {
345  return current.second;
346  }
347  }
348 
349  static inline Node *parse(const std::string input) {
350  Input iter = input.cbegin();
351 
352  return parse(iter, input.cend());
353  }
354 
355  static inline Node *parse(std::string &&input) {
356  Input iter = input.cbegin();
357 
358  return parse(iter, input.cend());
359  }
360 };
361 
362 }
363 
364 #endif
static MYPARSER_INLINE std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:299
Definition: myparser_rule.hpp:60
Definition: myparser_rule.hpp:231
Definition: myparser_ast.hpp:229
Definition: myparser_rule.hpp:248
Definition: myparser_rule.hpp:221
static Node * parse(std::string &&input)
Definition: myparser_rule.hpp:355
MP_STR("Match not accepted", 18) ErrorChecking
Definition: myparser_rule.hpp:16
static const size_t least
Definition: myparser_rule.hpp:22
Definition: myparser_ast.hpp:10
Definition: myparser_rule.hpp:183
static const size_t most
Definition: myparser_rule.hpp:23
MYPARSER_INLINE RuleList()
Definition: myparser_rule.hpp:105
static MYPARSER_INLINE std::pair< Node *, Node * > runRule(Input &input, const Input &end)
Definition: myparser_rule.hpp:63
Definition: myparser_rule.hpp:118
static MYPARSER_INLINE std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:223
RuleNamed()
Definition: myparser_rule.hpp:40
Rule()
Definition: myparser_rule.hpp:32
MP_STR("error", 5) BuiltinError
Definition: myparser_rule.hpp:12
Node * challengeLonger(Node *target)
Definition: myparser_ast.hpp:52
static MYPARSER_INLINE std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:185
static MYPARSER_INLINE std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:233
static MYPARSER_INLINE bool runRule(NodeListTyped< N, I > *&result, Node *&err, size_t &errpos, Input &input, const Input &end)
Definition: myparser_rule.hpp:254
#define MP_STR(str, len)
Definition: myparser_str.hpp:9
static MYPARSER_INLINE bool runRule(NodeListTyped< N, I > *&result, Node *&err, size_t &errpos, Input &input, const Input &end)
Definition: myparser_rule.hpp:285
static std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:173
MYPARSER_INLINE RuleRegex()
Definition: myparser_rule.hpp:168
static MYPARSER_INLINE std::pair< Node *, Node * > runRegex(Input &input, const Input &end)
Definition: myparser_rule.hpp:120
Definition: myparser_rule.hpp:251
MP_STR("space", 5) BuiltinSpace
Definition: myparser_rule.hpp:10
static MYPARSER_INLINE std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:195
MP_STR("Nothing matched", 15) ErrorList
Definition: myparser_rule.hpp:14
static std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:193
MP_STR("Regex not matched", 17) ErrorRegex
Definition: myparser_rule.hpp:15
static std::pair< Node *, Node * > parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:110
static MYPARSER_INLINE std::pair< Node *, Node * > runRule(Input &input, const Input &end)
Definition: myparser_rule.hpp:93
MP_STR("root", 4) BuiltinRoot
Definition: myparser_rule.hpp:9
MP_STR("Bad keyword", 11) ErrorKeyword
Definition: myparser_rule.hpp:17
Definition: myparser_rule.hpp:30
static Node * parse(Input &input, const Input &end)
Definition: myparser_rule.hpp:335
Definition: myparser_rule.hpp:20
std::string::const_iterator Input
Definition: myparser_ast.hpp:8
static Node * parse(const std::string input)
Definition: myparser_rule.hpp:349
MP_STR("keyword", 7) BuiltinKeyword
Definition: myparser_rule.hpp:11
#define MYPARSER_INLINE
Definition: myparser_common.hpp:50
Definition: myparser_rule.hpp:333
Definition: myparser_rule.hpp:47
Definition: myparser_rule.hpp:38