• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_VERIFICATION_DEBUG_PARSER_PARSER_H_
17 #define PANDA_VERIFICATION_DEBUG_PARSER_PARSER_H_
18 
19 #include "charset.h"
20 #include "verification/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             if (!result) {
147                 f(action::CANCEL, c, saved, start, end);
148                 start = saved;
149                 return false;
150             }
151             if (!f(action::PARSED, c, saved, start, end)) {
152                 start = saved;
153                 return false;
154             }
155             return true;
156         };
157         return l;
158     }
159 
160     template <typename F>
161     auto operator|=(F f) const ->
162         typename if_type<decltype(f(action::START, ref_to<Context>(), ref_to<Iter>(), val_of<Iter>())), bool,
163                          next<type_prod<op_action, F>>>::type
164     {
165         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
166             auto saved = start;
167             if (!f(action::START, c, start, start)) {
168                 start = saved;
169                 return false;
170             }
171             bool result = p(c, start, end);
172             if (!result) {
173                 f(action::CANCEL, c, saved, start);
174                 start = saved;
175                 return false;
176             }
177             if (!f(action::PARSED, c, saved, start)) {
178                 start = saved;
179                 return false;
180             }
181             return true;
182         };
183         return l;
184     }
185 
186     template <typename F>
187     auto operator|=(F f) const -> typename if_type<decltype(f(action::START, ref_to<Context>(), ref_to<Iter>())), bool,
188                                                    next<type_prod<op_action, F>>>::type
189     {
190         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
191             auto saved = start;
192             if (!f(action::START, c, start)) {
193                 start = saved;
194                 return false;
195             }
196             bool result = p(c, start, end);
197             if (!result) {
198                 f(action::CANCEL, c, saved);
199                 start = saved;
200                 return false;
201             }
202             if (!f(action::PARSED, c, saved)) {
203                 start = saved;
204                 return false;
205             }
206             return true;
207         };
208         return l;
209     }
210 
211     template <typename F>
212     auto operator|=(F f) const ->
213         typename if_type<decltype(f(action::START, ref_to<Context>())), bool, next<type_prod<op_action, F>>>::type
214     {
215         static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) {
216             auto saved = start;
217             if (!f(action::START, c)) {
218                 start = saved;
219                 return false;
220             }
221             bool result = p(c, start, end);
222             if (!result) {
223                 f(action::CANCEL, c);
224                 start = saved;
225                 return false;
226             }
227             if (!f(action::PARSED, c)) {
228                 start = saved;
229                 return false;
230             }
231             return true;
232         };
233         return l;
234     }
235 
236     template <typename P>
237     next<type_prod<op_sequence, typename P::T>> operator>>(P param_p) const
238     {
239         static const auto l = [left = *this, right = param_p](Context &c, Iter &start, Iter end) {
240             auto saved = start;
241             if (left(c, start, end) && right(c, start, end)) {
242                 return true;
243             }
244             start = saved;
245             return false;
246         };
247         return l;
248     }
249 
250     template <typename P>
251     next<type_prod<op_or, typename P::T>> operator|(P param_p) const
252     {
253         static const auto l = [left = *this, right = param_p](Context &c, Iter &start, Iter end) {
254             auto saved = start;
255             if (left(c, start, end)) {
256                 return true;
257             }
258             start = saved;
259             if (right(c, start, end)) {
260                 return true;
261             }
262             start = saved;
263             return false;
264         };
265         return l;
266     }
267 
268     template <typename P>
269     next<type_prod<op_and, typename P::T>> operator&(P param_p) const
270     {
271         static const auto l = [left = *this, right = param_p](Context &c, Iter &start, Iter end) {
272             auto saved = start;
273             if (left(c, start, end)) {
274                 start = saved;
275                 return right(c, start, end);
276             }
277             start = saved;
278             return false;
279         };
280         return l;
281     }
282 
283     template <typename P>
284     next<type_prod<op_lookup, typename P::T>> operator<<(P param_p) const
285     {
286         static const auto l = [left = *this, right = param_p](Context &c, Iter &start, Iter end) {
287             auto saved1 = start;
288             if (left(c, start, end)) {
289                 auto saved2 = start;
290                 if (right(c, start, end)) {
291                     start = saved2;
292                     return true;
293                 }
294             }
295             start = saved1;
296             return false;
297         };
298         return l;
299     }
300 
301     next<op_not> operator!() &&
302     {
303         static const auto l = [p = *this](Context &c, Iter &start, Iter end) {
304             auto saved = start;
305             if (p(c, start, end)) {
306                 start = saved;
307                 return false;
308             }
309             start = saved;
310             return true;
311         };
312         return l;
313     }
314 
315     next<op_not> operator!() const &
316     {
317         static const auto l = [this](Context &c, Iter &start, Iter end) {
318             auto saved = start;
319             if ((*this)(c, start, end)) {
320                 start = saved;
321                 return false;
322             }
323             start = saved;
324             return true;
325         };
326         return l;
327     }
328 
329     next<op_times> operator*() &&
330     {
331         static const auto l = [p = *this](Context &c, Iter &start, Iter end) {
332             while (true) {
333                 auto saved = start;
334                 if (!p(c, start, end)) {
335                     start = saved;
336                     break;
337                 }
338             }
339             return true;
340         };
341         return l;
342     }
343 
344     next<op_times_ref> operator*() const &
345     {
346         static const auto l = [this](Context &c, Iter &start, Iter end) {
347             while (true) {
348                 auto saved = start;
349                 if (!(*this)(c, start, end)) {
350                     start = saved;
351                     break;
352                 }
353             }
354             return true;
355         };
356         return l;
357     }
358 };
359 
360 struct initial;
361 
362 template <typename Context, typename Char, typename Iter>
363 using parser = base_parser<Context, initial, Char, Iter>;
364 
365 }  // namespace panda::parser
366 
367 #endif  // PANDA_VERIFICATION_DEBUG_PARSER_PARSER_H_
368