• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_VERIF_PARSER_H_
17 #define PANDA_VERIF_PARSER_H_
18 
19 #include "charset.h"
20 #include "util/callable.h"
21 
22 namespace panda::parser {
23 
24 template <typename...>
25 struct type_sum;
26 
27 template <typename...>
28 struct type_prod;
29 
30 struct op_next;
31 struct op_end;
32 struct op_optional;
33 struct op_action;
34 struct op_sequence;
35 struct op_or;
36 struct op_and;
37 struct op_lookup;
38 struct op_not;
39 struct op_times;
40 struct op_times_ref;
41 
42 template <typename A, typename B, typename C>
43 struct if_type {
44 };
45 
46 template <typename A, typename C>
47 struct if_type<A, A, C> {
48     using type = C;
49 };
50 
51 template <typename T>
52 T &ref_to();
53 
54 template <typename T>
55 T val_of();
56 
57 enum class action { START, PARSED, CANCEL };
58 
59 template <typename Context, typename Type, typename Char, typename Iter>
60 struct base_parser : public verifier::callable<bool(Context &, Iter &, Iter)> {
61     template <typename F>
62     constexpr base_parser(const F &f) : verifier::callable<bool(Context &, Iter &, Iter)> {f}
63     {
64     }
65 
66     using Ctx = Context;
67     using T = Type;
68 
69     base_parser() = default;
70 
71     template <typename NType>
72     using next = base_parser<Context, type_sum<NType, T>, Char, Iter>;
73 
74     using p = base_parser<Context, type_sum<op_next, T>, Char, Iter>;
75 
76     static next<charset<Char>> of_charset(const charset<Char> &c)
77     {
78         static const auto l = [c](Context &, Iter &start, Iter end) {
79             Iter s = start;
80             while (s != end && c(*s)) {
81                 s++;
82             }
83             bool result = (s != start);
84             if (result) {
85                 start = s;
86             }
87             return result;
88         };
89         return l;
90     }
91 
92     static next<Char *> of_string(Char *str)
93     {
94         static const auto l = [=](Context &, Iter &start, Iter end) {
95             Iter s = start;
96             Iter c = str;
97             while (s != end && *c != 0 && *c == *s) {
98                 ++c;
99                 ++s;
100             }
101             bool result = (*c == 0);
102             if (result) {
103                 start = s;
104             }
105             return result;
106         };
107         return l;
108     }
109 
110     static next<op_end> end()
111     {
112         static const auto l = [](Context &, Iter &start, Iter end) { return start == end; };
113         return l;
114     }
115 
116     next<op_optional> operator~() &&
117     {
118         static const auto l = [p = *this](Context &c, Iter &start, Iter end) {
119             p(c, start, end);
120             return true;
121         };
122         return l;
123     }
124 
125     next<op_optional> operator~() const &
126     {
127         static const auto l = [this](Context &c, Iter &start, Iter end) {
128             (*this)(c, start, end);
129             return true;
130         };
131         return l;
132     }
133 
134     template <typename F>
135     auto operator|=(F f) const ->
136         typename if_type<decltype(f(action::START, ref_to<Context>(), ref_to<Iter>(), val_of<Iter>(), val_of<Iter>())),
137                          bool, next<type_prod<op_action, F>>>::type
138     {
139         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
140             auto saved = start;
141             if (!f(action::START, c, start, start, end)) {
142                 start = saved;
143                 return false;
144             }
145             bool result = p(c, start, end);
146             auto new_saved = saved;
147             if (!result) {
148                 f(action::CANCEL, c, new_saved, start, end);
149                 start = saved;
150                 return false;
151             }
152             if (!f(action::PARSED, c, new_saved, start, end)) {
153                 start = saved;
154                 return false;
155             }
156             return true;
157         };
158         return l;
159     }
160 
161     template <typename F>
162     auto operator|=(F f) const ->
163         typename if_type<decltype(f(action::START, ref_to<Context>(), ref_to<Iter>(), val_of<Iter>())), bool,
164                          next<type_prod<op_action, F>>>::type
165     {
166         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
167             auto saved = start;
168             if (!f(action::START, c, start, start)) {
169                 start = saved;
170                 return false;
171             }
172             bool result = p(c, start, end);
173             auto new_saved = saved;
174             if (!result) {
175                 f(action::CANCEL, c, new_saved, start);
176                 start = saved;
177                 return false;
178             }
179             if (!f(action::PARSED, c, new_saved, start)) {
180                 start = saved;
181                 return false;
182             }
183             return true;
184         };
185         return l;
186     }
187 
188     template <typename F>
189     auto operator|=(F f) const -> typename if_type<decltype(f(action::START, ref_to<Context>(), ref_to<Iter>())), bool,
190                                                    next<type_prod<op_action, F>>>::type
191     {
192         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
193             auto saved = start;
194             if (!f(action::START, c, start)) {
195                 start = saved;
196                 return false;
197             }
198             bool result = p(c, start, end);
199             auto new_saved = saved;
200             if (!result) {
201                 f(action::CANCEL, c, new_saved);
202                 start = saved;
203                 return false;
204             }
205             if (!f(action::PARSED, c, new_saved)) {
206                 start = saved;
207                 return false;
208             }
209             return true;
210         };
211         return l;
212     }
213 
214     template <typename F>
215     auto operator|=(F f) const ->
216         typename if_type<decltype(f(action::START, ref_to<Context>())), bool, next<type_prod<op_action, F>>>::type
217     {
218         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
219             auto saved = start;
220             if (!f(action::START, c)) {
221                 start = saved;
222                 return false;
223             }
224             bool result = p(c, start, end);
225             if (!result) {
226                 f(action::CANCEL, c);
227                 start = saved;
228                 return false;
229             }
230             if (!f(action::PARSED, c)) {
231                 start = saved;
232                 return false;
233             }
234             return true;
235         };
236         return l;
237     }
238 
239     template <typename P>
240     next<type_prod<op_sequence, typename P::T>> operator>>(P pa) const
241     {
242         static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) {
243             auto saved = start;
244             if (left(c, start, end) && right(c, start, end)) {
245                 return true;
246             }
247             start = saved;
248             return false;
249         };
250         return l;
251     }
252 
253     template <typename P>
254     next<type_prod<op_or, typename P::T>> operator|(P pa) const
255     {
256         static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) {
257             auto saved = start;
258             if (left(c, start, end)) {
259                 return true;
260             }
261             start = saved;
262             if (right(c, start, end)) {
263                 return true;
264             }
265             start = saved;
266             return false;
267         };
268         return l;
269     }
270 
271     template <typename P>
272     next<type_prod<op_and, typename P::T>> operator&(P pa) const
273     {
274         static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) {
275             auto saved = start;
276             if (left(c, start, end)) {
277                 start = saved;
278                 return right(c, start, end);
279             }
280             start = saved;
281             return false;
282         };
283         return l;
284     }
285 
286     template <typename P>
287     next<type_prod<op_lookup, typename P::T>> operator<<(P pa) const
288     {
289         static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) {
290             auto saved1 = start;
291             if (left(c, start, end)) {
292                 auto saved2 = start;
293                 if (right(c, start, end)) {
294                     start = saved2;
295                     return true;
296                 }
297             }
298             start = saved1;
299             return false;
300         };
301         return l;
302     }
303 
304     next<op_not> operator!() &&
305     {
306         static const auto l = [p = *this](Context &c, Iter &start, Iter end) {
307             auto saved = start;
308             if (p(c, start, end)) {
309                 start = saved;
310                 return false;
311             }
312             start = saved;
313             return true;
314         };
315         return l;
316     }
317 
318     next<op_not> operator!() const &
319     {
320         static const auto l = [this](Context &c, Iter &start, Iter end) {
321             auto saved = start;
322             if ((*this)(c, start, end)) {
323                 start = saved;
324                 return false;
325             }
326             start = saved;
327             return true;
328         };
329         return l;
330     }
331 
332     next<op_times> operator*() &&
333     {
334         static const auto l = [p = *this](Context &c, Iter &start, Iter end) {
335             while (true) {
336                 auto saved = start;
337                 if (!p(c, start, end)) {
338                     start = saved;
339                     break;
340                 }
341             }
342             return true;
343         };
344         return l;
345     }
346 
347     next<op_times_ref> operator*() const &
348     {
349         static const auto l = [this](Context &c, Iter &start, Iter end) {
350             while (true) {
351                 auto saved = start;
352                 if (!(*this)(c, start, end)) {
353                     start = saved;
354                     break;
355                 }
356             }
357             return true;
358         };
359         return l;
360     }
361 };
362 
363 struct initial;
364 
365 template <typename Context, typename Char, typename Iter>
366 using parser = base_parser<Context, initial, Char, Iter>;
367 
368 }  // namespace panda::parser
369 
370 #endif  //! PANDA_VERIF_PARSER_H_
371