Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/parse/common.h @ 62:0994c39f1e94
Cap'n Proto v0.6 + build for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 22 May 2017 10:01:37 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
61:d101c4099725 | 62:0994c39f1e94 |
---|---|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 // Parser combinator framework! | |
23 // | |
24 // This file declares several functions which construct parsers, usually taking other parsers as | |
25 // input, thus making them parser combinators. | |
26 // | |
27 // A valid parser is any functor which takes a reference to an input cursor (defined below) as its | |
28 // input and returns a Maybe. The parser returns null on parse failure, or returns the parsed | |
29 // result on success. | |
30 // | |
31 // An "input cursor" is any type which implements the same interface as IteratorInput, below. Such | |
32 // a type acts as a pointer to the current input location. When a parser returns successfully, it | |
33 // will have updated the input cursor to point to the position just past the end of what was parsed. | |
34 // On failure, the cursor position is unspecified. | |
35 | |
36 #ifndef KJ_PARSE_COMMON_H_ | |
37 #define KJ_PARSE_COMMON_H_ | |
38 | |
39 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | |
40 #pragma GCC system_header | |
41 #endif | |
42 | |
43 #include "../common.h" | |
44 #include "../memory.h" | |
45 #include "../array.h" | |
46 #include "../tuple.h" | |
47 #include "../vector.h" | |
48 #if _MSC_VER | |
49 #include <type_traits> // result_of_t | |
50 #endif | |
51 | |
52 namespace kj { | |
53 namespace parse { | |
54 | |
55 template <typename Element, typename Iterator> | |
56 class IteratorInput { | |
57 // A parser input implementation based on an iterator range. | |
58 | |
59 public: | |
60 IteratorInput(Iterator begin, Iterator end) | |
61 : parent(nullptr), pos(begin), end(end), best(begin) {} | |
62 explicit IteratorInput(IteratorInput& parent) | |
63 : parent(&parent), pos(parent.pos), end(parent.end), best(parent.pos) {} | |
64 ~IteratorInput() { | |
65 if (parent != nullptr) { | |
66 parent->best = kj::max(kj::max(pos, best), parent->best); | |
67 } | |
68 } | |
69 KJ_DISALLOW_COPY(IteratorInput); | |
70 | |
71 void advanceParent() { | |
72 parent->pos = pos; | |
73 } | |
74 void forgetParent() { | |
75 parent = nullptr; | |
76 } | |
77 | |
78 bool atEnd() { return pos == end; } | |
79 auto current() -> decltype(*instance<Iterator>()) { | |
80 KJ_IREQUIRE(!atEnd()); | |
81 return *pos; | |
82 } | |
83 auto consume() -> decltype(*instance<Iterator>()) { | |
84 KJ_IREQUIRE(!atEnd()); | |
85 return *pos++; | |
86 } | |
87 void next() { | |
88 KJ_IREQUIRE(!atEnd()); | |
89 ++pos; | |
90 } | |
91 | |
92 Iterator getBest() { return kj::max(pos, best); } | |
93 | |
94 Iterator getPosition() { return pos; } | |
95 | |
96 private: | |
97 IteratorInput* parent; | |
98 Iterator pos; | |
99 Iterator end; | |
100 Iterator best; // furthest we got with any sub-input | |
101 }; | |
102 | |
103 template <typename T> struct OutputType_; | |
104 template <typename T> struct OutputType_<Maybe<T>> { typedef T Type; }; | |
105 template <typename Parser, typename Input> | |
106 using OutputType = typename OutputType_< | |
107 #if _MSC_VER | |
108 std::result_of_t<Parser(Input)> | |
109 // The instance<T&>() based version below results in: | |
110 // C2064: term does not evaluate to a function taking 1 arguments | |
111 #else | |
112 decltype(instance<Parser&>()(instance<Input&>())) | |
113 #endif | |
114 >::Type; | |
115 // Synonym for the output type of a parser, given the parser type and the input type. | |
116 | |
117 // ======================================================================================= | |
118 | |
119 template <typename Input, typename Output> | |
120 class ParserRef { | |
121 // Acts as a reference to some other parser, with simplified type. The referenced parser | |
122 // is polymorphic by virtual call rather than templates. For grammars of non-trivial size, | |
123 // it is important to inject refs into the grammar here and there to prevent the parser types | |
124 // from becoming ridiculous. Using too many of them can hurt performance, though. | |
125 | |
126 public: | |
127 ParserRef(): parser(nullptr), wrapper(nullptr) {} | |
128 ParserRef(const ParserRef&) = default; | |
129 ParserRef(ParserRef&&) = default; | |
130 ParserRef& operator=(const ParserRef& other) = default; | |
131 ParserRef& operator=(ParserRef&& other) = default; | |
132 | |
133 template <typename Other> | |
134 constexpr ParserRef(Other&& other) | |
135 : parser(&other), wrapper(&WrapperImplInstance<Decay<Other>>::instance) { | |
136 static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary."); | |
137 } | |
138 | |
139 template <typename Other> | |
140 inline ParserRef& operator=(Other&& other) { | |
141 static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary."); | |
142 parser = &other; | |
143 wrapper = &WrapperImplInstance<Decay<Other>>::instance; | |
144 return *this; | |
145 } | |
146 | |
147 KJ_ALWAYS_INLINE(Maybe<Output> operator()(Input& input) const) { | |
148 // Always inline in the hopes that this allows branch prediction to kick in so the virtual call | |
149 // doesn't hurt so much. | |
150 return wrapper->parse(parser, input); | |
151 } | |
152 | |
153 private: | |
154 struct Wrapper { | |
155 virtual Maybe<Output> parse(const void* parser, Input& input) const = 0; | |
156 }; | |
157 template <typename ParserImpl> | |
158 struct WrapperImpl: public Wrapper { | |
159 Maybe<Output> parse(const void* parser, Input& input) const override { | |
160 return (*reinterpret_cast<const ParserImpl*>(parser))(input); | |
161 } | |
162 }; | |
163 template <typename ParserImpl> | |
164 struct WrapperImplInstance { | |
165 #if _MSC_VER | |
166 // TODO(msvc): MSVC currently fails to initialize vtable pointers for constexpr values so | |
167 // we have to make this just const instead. | |
168 static const WrapperImpl<ParserImpl> instance; | |
169 #else | |
170 static constexpr WrapperImpl<ParserImpl> instance = WrapperImpl<ParserImpl>(); | |
171 #endif | |
172 }; | |
173 | |
174 const void* parser; | |
175 const Wrapper* wrapper; | |
176 }; | |
177 | |
178 template <typename Input, typename Output> | |
179 template <typename ParserImpl> | |
180 #if _MSC_VER | |
181 const typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl> | |
182 ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance = WrapperImpl<ParserImpl>(); | |
183 #else | |
184 constexpr typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl> | |
185 ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance; | |
186 #endif | |
187 | |
188 template <typename Input, typename ParserImpl> | |
189 constexpr ParserRef<Input, OutputType<ParserImpl, Input>> ref(ParserImpl& impl) { | |
190 // Constructs a ParserRef. You must specify the input type explicitly, e.g. | |
191 // `ref<MyInput>(myParser)`. | |
192 | |
193 return ParserRef<Input, OutputType<ParserImpl, Input>>(impl); | |
194 } | |
195 | |
196 // ------------------------------------------------------------------- | |
197 // any | |
198 // Output = one token | |
199 | |
200 class Any_ { | |
201 public: | |
202 template <typename Input> | |
203 Maybe<Decay<decltype(instance<Input>().consume())>> operator()(Input& input) const { | |
204 if (input.atEnd()) { | |
205 return nullptr; | |
206 } else { | |
207 return input.consume(); | |
208 } | |
209 } | |
210 }; | |
211 | |
212 constexpr Any_ any = Any_(); | |
213 // A parser which matches any token and simply returns it. | |
214 | |
215 // ------------------------------------------------------------------- | |
216 // exactly() | |
217 // Output = Tuple<> | |
218 | |
219 template <typename T> | |
220 class Exactly_ { | |
221 public: | |
222 explicit constexpr Exactly_(T&& expected): expected(expected) {} | |
223 | |
224 template <typename Input> | |
225 Maybe<Tuple<>> operator()(Input& input) const { | |
226 if (input.atEnd() || input.current() != expected) { | |
227 return nullptr; | |
228 } else { | |
229 input.next(); | |
230 return Tuple<>(); | |
231 } | |
232 } | |
233 | |
234 private: | |
235 T expected; | |
236 }; | |
237 | |
238 template <typename T> | |
239 constexpr Exactly_<T> exactly(T&& expected) { | |
240 // Constructs a parser which succeeds when the input is exactly the token specified. The | |
241 // result is always the empty tuple. | |
242 | |
243 return Exactly_<T>(kj::fwd<T>(expected)); | |
244 } | |
245 | |
246 // ------------------------------------------------------------------- | |
247 // exactlyConst() | |
248 // Output = Tuple<> | |
249 | |
250 template <typename T, T expected> | |
251 class ExactlyConst_ { | |
252 public: | |
253 explicit constexpr ExactlyConst_() {} | |
254 | |
255 template <typename Input> | |
256 Maybe<Tuple<>> operator()(Input& input) const { | |
257 if (input.atEnd() || input.current() != expected) { | |
258 return nullptr; | |
259 } else { | |
260 input.next(); | |
261 return Tuple<>(); | |
262 } | |
263 } | |
264 }; | |
265 | |
266 template <typename T, T expected> | |
267 constexpr ExactlyConst_<T, expected> exactlyConst() { | |
268 // Constructs a parser which succeeds when the input is exactly the token specified. The | |
269 // result is always the empty tuple. This parser is templated on the token value which may cause | |
270 // it to perform better -- or worse. Be sure to measure. | |
271 | |
272 return ExactlyConst_<T, expected>(); | |
273 } | |
274 | |
275 // ------------------------------------------------------------------- | |
276 // constResult() | |
277 | |
278 template <typename SubParser, typename Result> | |
279 class ConstResult_ { | |
280 public: | |
281 explicit constexpr ConstResult_(SubParser&& subParser, Result&& result) | |
282 : subParser(kj::fwd<SubParser>(subParser)), result(kj::fwd<Result>(result)) {} | |
283 | |
284 template <typename Input> | |
285 Maybe<Result> operator()(Input& input) const { | |
286 if (subParser(input) == nullptr) { | |
287 return nullptr; | |
288 } else { | |
289 return result; | |
290 } | |
291 } | |
292 | |
293 private: | |
294 SubParser subParser; | |
295 Result result; | |
296 }; | |
297 | |
298 template <typename SubParser, typename Result> | |
299 constexpr ConstResult_<SubParser, Result> constResult(SubParser&& subParser, Result&& result) { | |
300 // Constructs a parser which returns exactly `result` if `subParser` is successful. | |
301 return ConstResult_<SubParser, Result>(kj::fwd<SubParser>(subParser), kj::fwd<Result>(result)); | |
302 } | |
303 | |
304 template <typename SubParser> | |
305 constexpr ConstResult_<SubParser, Tuple<>> discard(SubParser&& subParser) { | |
306 // Constructs a parser which wraps `subParser` but discards the result. | |
307 return constResult(kj::fwd<SubParser>(subParser), Tuple<>()); | |
308 } | |
309 | |
310 // ------------------------------------------------------------------- | |
311 // sequence() | |
312 // Output = Flattened Tuple of outputs of sub-parsers. | |
313 | |
314 template <typename... SubParsers> class Sequence_; | |
315 | |
316 template <typename FirstSubParser, typename... SubParsers> | |
317 class Sequence_<FirstSubParser, SubParsers...> { | |
318 public: | |
319 template <typename T, typename... U> | |
320 explicit constexpr Sequence_(T&& firstSubParser, U&&... rest) | |
321 : first(kj::fwd<T>(firstSubParser)), rest(kj::fwd<U>(rest)...) {} | |
322 | |
323 // TODO(msvc): The trailing return types on `operator()` and `parseNext()` expose at least two | |
324 // bugs in MSVC: | |
325 // | |
326 // 1. An ICE. | |
327 // 2. 'error C2672: 'operator __surrogate_func': no matching overloaded function found)', | |
328 // which crops up in numerous places when trying to build the capnp command line tools. | |
329 // | |
330 // The only workaround I found for both bugs is to omit the trailing return types and instead | |
331 // rely on C++14's return type deduction. | |
332 | |
333 template <typename Input> | |
334 auto operator()(Input& input) const | |
335 #ifndef _MSC_VER | |
336 -> Maybe<decltype(tuple( | |
337 instance<OutputType<FirstSubParser, Input>>(), | |
338 instance<OutputType<SubParsers, Input>>()...))> | |
339 #endif | |
340 { | |
341 return parseNext(input); | |
342 } | |
343 | |
344 template <typename Input, typename... InitialParams> | |
345 auto parseNext(Input& input, InitialParams&&... initialParams) const | |
346 #ifndef _MSC_VER | |
347 -> Maybe<decltype(tuple( | |
348 kj::fwd<InitialParams>(initialParams)..., | |
349 instance<OutputType<FirstSubParser, Input>>(), | |
350 instance<OutputType<SubParsers, Input>>()...))> | |
351 #endif | |
352 { | |
353 KJ_IF_MAYBE(firstResult, first(input)) { | |
354 return rest.parseNext(input, kj::fwd<InitialParams>(initialParams)..., | |
355 kj::mv(*firstResult)); | |
356 } else { | |
357 // TODO(msvc): MSVC depends on return type deduction to compile this function, so we need to | |
358 // help it deduce the right type on this code path. | |
359 return Maybe<decltype(tuple( | |
360 kj::fwd<InitialParams>(initialParams)..., | |
361 instance<OutputType<FirstSubParser, Input>>(), | |
362 instance<OutputType<SubParsers, Input>>()...))>{nullptr}; | |
363 } | |
364 } | |
365 | |
366 private: | |
367 FirstSubParser first; | |
368 Sequence_<SubParsers...> rest; | |
369 }; | |
370 | |
371 template <> | |
372 class Sequence_<> { | |
373 public: | |
374 template <typename Input> | |
375 Maybe<Tuple<>> operator()(Input& input) const { | |
376 return parseNext(input); | |
377 } | |
378 | |
379 template <typename Input, typename... Params> | |
380 auto parseNext(Input& input, Params&&... params) const -> | |
381 Maybe<decltype(tuple(kj::fwd<Params>(params)...))> { | |
382 return tuple(kj::fwd<Params>(params)...); | |
383 } | |
384 }; | |
385 | |
386 template <typename... SubParsers> | |
387 constexpr Sequence_<SubParsers...> sequence(SubParsers&&... subParsers) { | |
388 // Constructs a parser that executes each of the parameter parsers in sequence and returns a | |
389 // tuple of their results. | |
390 | |
391 return Sequence_<SubParsers...>(kj::fwd<SubParsers>(subParsers)...); | |
392 } | |
393 | |
394 // ------------------------------------------------------------------- | |
395 // many() | |
396 // Output = Array of output of sub-parser, or just a uint count if the sub-parser returns Tuple<>. | |
397 | |
398 template <typename SubParser, bool atLeastOne> | |
399 class Many_ { | |
400 template <typename Input, typename Output = OutputType<SubParser, Input>> | |
401 struct Impl; | |
402 public: | |
403 explicit constexpr Many_(SubParser&& subParser) | |
404 : subParser(kj::fwd<SubParser>(subParser)) {} | |
405 | |
406 template <typename Input> | |
407 auto operator()(Input& input) const | |
408 -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input)); | |
409 | |
410 private: | |
411 SubParser subParser; | |
412 }; | |
413 | |
414 template <typename SubParser, bool atLeastOne> | |
415 template <typename Input, typename Output> | |
416 struct Many_<SubParser, atLeastOne>::Impl { | |
417 static Maybe<Array<Output>> apply(const SubParser& subParser, Input& input) { | |
418 typedef Vector<OutputType<SubParser, Input>> Results; | |
419 Results results; | |
420 | |
421 while (!input.atEnd()) { | |
422 Input subInput(input); | |
423 | |
424 KJ_IF_MAYBE(subResult, subParser(subInput)) { | |
425 subInput.advanceParent(); | |
426 results.add(kj::mv(*subResult)); | |
427 } else { | |
428 break; | |
429 } | |
430 } | |
431 | |
432 if (atLeastOne && results.empty()) { | |
433 return nullptr; | |
434 } | |
435 | |
436 return results.releaseAsArray(); | |
437 } | |
438 }; | |
439 | |
440 template <typename SubParser, bool atLeastOne> | |
441 template <typename Input> | |
442 struct Many_<SubParser, atLeastOne>::Impl<Input, Tuple<>> { | |
443 // If the sub-parser output is Tuple<>, just return a count. | |
444 | |
445 static Maybe<uint> apply(const SubParser& subParser, Input& input) { | |
446 uint count = 0; | |
447 | |
448 while (!input.atEnd()) { | |
449 Input subInput(input); | |
450 | |
451 KJ_IF_MAYBE(subResult, subParser(subInput)) { | |
452 subInput.advanceParent(); | |
453 ++count; | |
454 } else { | |
455 break; | |
456 } | |
457 } | |
458 | |
459 if (atLeastOne && count == 0) { | |
460 return nullptr; | |
461 } | |
462 | |
463 return count; | |
464 } | |
465 }; | |
466 | |
467 template <typename SubParser, bool atLeastOne> | |
468 template <typename Input> | |
469 auto Many_<SubParser, atLeastOne>::operator()(Input& input) const | |
470 -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input)) { | |
471 return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, input); | |
472 } | |
473 | |
474 template <typename SubParser> | |
475 constexpr Many_<SubParser, false> many(SubParser&& subParser) { | |
476 // Constructs a parser that repeatedly executes the given parser until it fails, returning an | |
477 // Array of the results (or a uint count if `subParser` returns an empty tuple). | |
478 return Many_<SubParser, false>(kj::fwd<SubParser>(subParser)); | |
479 } | |
480 | |
481 template <typename SubParser> | |
482 constexpr Many_<SubParser, true> oneOrMore(SubParser&& subParser) { | |
483 // Like `many()` but the parser must parse at least one item to be successful. | |
484 return Many_<SubParser, true>(kj::fwd<SubParser>(subParser)); | |
485 } | |
486 | |
487 // ------------------------------------------------------------------- | |
488 // times() | |
489 // Output = Array of output of sub-parser, or Tuple<> if sub-parser returns Tuple<>. | |
490 | |
491 template <typename SubParser> | |
492 class Times_ { | |
493 template <typename Input, typename Output = OutputType<SubParser, Input>> | |
494 struct Impl; | |
495 public: | |
496 explicit constexpr Times_(SubParser&& subParser, uint count) | |
497 : subParser(kj::fwd<SubParser>(subParser)), count(count) {} | |
498 | |
499 template <typename Input> | |
500 auto operator()(Input& input) const | |
501 -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input)); | |
502 | |
503 private: | |
504 SubParser subParser; | |
505 uint count; | |
506 }; | |
507 | |
508 template <typename SubParser> | |
509 template <typename Input, typename Output> | |
510 struct Times_<SubParser>::Impl { | |
511 static Maybe<Array<Output>> apply(const SubParser& subParser, uint count, Input& input) { | |
512 auto results = heapArrayBuilder<OutputType<SubParser, Input>>(count); | |
513 | |
514 while (results.size() < count) { | |
515 if (input.atEnd()) { | |
516 return nullptr; | |
517 } else KJ_IF_MAYBE(subResult, subParser(input)) { | |
518 results.add(kj::mv(*subResult)); | |
519 } else { | |
520 return nullptr; | |
521 } | |
522 } | |
523 | |
524 return results.finish(); | |
525 } | |
526 }; | |
527 | |
528 template <typename SubParser> | |
529 template <typename Input> | |
530 struct Times_<SubParser>::Impl<Input, Tuple<>> { | |
531 // If the sub-parser output is Tuple<>, just return a count. | |
532 | |
533 static Maybe<Tuple<>> apply(const SubParser& subParser, uint count, Input& input) { | |
534 uint actualCount = 0; | |
535 | |
536 while (actualCount < count) { | |
537 if (input.atEnd()) { | |
538 return nullptr; | |
539 } else KJ_IF_MAYBE(subResult, subParser(input)) { | |
540 ++actualCount; | |
541 } else { | |
542 return nullptr; | |
543 } | |
544 } | |
545 | |
546 return tuple(); | |
547 } | |
548 }; | |
549 | |
550 template <typename SubParser> | |
551 template <typename Input> | |
552 auto Times_<SubParser>::operator()(Input& input) const | |
553 -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input)) { | |
554 return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, count, input); | |
555 } | |
556 | |
557 template <typename SubParser> | |
558 constexpr Times_<SubParser> times(SubParser&& subParser, uint count) { | |
559 // Constructs a parser that repeats the subParser exactly `count` times. | |
560 return Times_<SubParser>(kj::fwd<SubParser>(subParser), count); | |
561 } | |
562 | |
563 // ------------------------------------------------------------------- | |
564 // optional() | |
565 // Output = Maybe<output of sub-parser> | |
566 | |
567 template <typename SubParser> | |
568 class Optional_ { | |
569 public: | |
570 explicit constexpr Optional_(SubParser&& subParser) | |
571 : subParser(kj::fwd<SubParser>(subParser)) {} | |
572 | |
573 template <typename Input> | |
574 Maybe<Maybe<OutputType<SubParser, Input>>> operator()(Input& input) const { | |
575 typedef Maybe<OutputType<SubParser, Input>> Result; | |
576 | |
577 Input subInput(input); | |
578 KJ_IF_MAYBE(subResult, subParser(subInput)) { | |
579 subInput.advanceParent(); | |
580 return Result(kj::mv(*subResult)); | |
581 } else { | |
582 return Result(nullptr); | |
583 } | |
584 } | |
585 | |
586 private: | |
587 SubParser subParser; | |
588 }; | |
589 | |
590 template <typename SubParser> | |
591 constexpr Optional_<SubParser> optional(SubParser&& subParser) { | |
592 // Constructs a parser that accepts zero or one of the given sub-parser, returning a Maybe | |
593 // of the sub-parser's result. | |
594 return Optional_<SubParser>(kj::fwd<SubParser>(subParser)); | |
595 } | |
596 | |
597 // ------------------------------------------------------------------- | |
598 // oneOf() | |
599 // All SubParsers must have same output type, which becomes the output type of the | |
600 // OneOfParser. | |
601 | |
602 template <typename... SubParsers> | |
603 class OneOf_; | |
604 | |
605 template <typename FirstSubParser, typename... SubParsers> | |
606 class OneOf_<FirstSubParser, SubParsers...> { | |
607 public: | |
608 explicit constexpr OneOf_(FirstSubParser&& firstSubParser, SubParsers&&... rest) | |
609 : first(kj::fwd<FirstSubParser>(firstSubParser)), rest(kj::fwd<SubParsers>(rest)...) {} | |
610 | |
611 template <typename Input> | |
612 Maybe<OutputType<FirstSubParser, Input>> operator()(Input& input) const { | |
613 { | |
614 Input subInput(input); | |
615 Maybe<OutputType<FirstSubParser, Input>> firstResult = first(subInput); | |
616 | |
617 if (firstResult != nullptr) { | |
618 subInput.advanceParent(); | |
619 return kj::mv(firstResult); | |
620 } | |
621 } | |
622 | |
623 // Hoping for some tail recursion here... | |
624 return rest(input); | |
625 } | |
626 | |
627 private: | |
628 FirstSubParser first; | |
629 OneOf_<SubParsers...> rest; | |
630 }; | |
631 | |
632 template <> | |
633 class OneOf_<> { | |
634 public: | |
635 template <typename Input> | |
636 decltype(nullptr) operator()(Input& input) const { | |
637 return nullptr; | |
638 } | |
639 }; | |
640 | |
641 template <typename... SubParsers> | |
642 constexpr OneOf_<SubParsers...> oneOf(SubParsers&&... parsers) { | |
643 // Constructs a parser that accepts one of a set of options. The parser behaves as the first | |
644 // sub-parser in the list which returns successfully. All of the sub-parsers must return the | |
645 // same type. | |
646 return OneOf_<SubParsers...>(kj::fwd<SubParsers>(parsers)...); | |
647 } | |
648 | |
649 // ------------------------------------------------------------------- | |
650 // transform() | |
651 // Output = Result of applying transform functor to input value. If input is a tuple, it is | |
652 // unpacked to form the transformation parameters. | |
653 | |
654 template <typename Position> | |
655 struct Span { | |
656 public: | |
657 inline const Position& begin() const { return begin_; } | |
658 inline const Position& end() const { return end_; } | |
659 | |
660 Span() = default; | |
661 inline constexpr Span(Position&& begin, Position&& end): begin_(mv(begin)), end_(mv(end)) {} | |
662 | |
663 private: | |
664 Position begin_; | |
665 Position end_; | |
666 }; | |
667 | |
668 template <typename Position> | |
669 constexpr Span<Decay<Position>> span(Position&& start, Position&& end) { | |
670 return Span<Decay<Position>>(kj::fwd<Position>(start), kj::fwd<Position>(end)); | |
671 } | |
672 | |
673 template <typename SubParser, typename TransformFunc> | |
674 class Transform_ { | |
675 public: | |
676 explicit constexpr Transform_(SubParser&& subParser, TransformFunc&& transform) | |
677 : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | |
678 | |
679 template <typename Input> | |
680 Maybe<decltype(kj::apply(instance<TransformFunc&>(), | |
681 instance<OutputType<SubParser, Input>&&>()))> | |
682 operator()(Input& input) const { | |
683 KJ_IF_MAYBE(subResult, subParser(input)) { | |
684 return kj::apply(transform, kj::mv(*subResult)); | |
685 } else { | |
686 return nullptr; | |
687 } | |
688 } | |
689 | |
690 private: | |
691 SubParser subParser; | |
692 TransformFunc transform; | |
693 }; | |
694 | |
695 template <typename SubParser, typename TransformFunc> | |
696 class TransformOrReject_ { | |
697 public: | |
698 explicit constexpr TransformOrReject_(SubParser&& subParser, TransformFunc&& transform) | |
699 : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | |
700 | |
701 template <typename Input> | |
702 decltype(kj::apply(instance<TransformFunc&>(), instance<OutputType<SubParser, Input>&&>())) | |
703 operator()(Input& input) const { | |
704 KJ_IF_MAYBE(subResult, subParser(input)) { | |
705 return kj::apply(transform, kj::mv(*subResult)); | |
706 } else { | |
707 return nullptr; | |
708 } | |
709 } | |
710 | |
711 private: | |
712 SubParser subParser; | |
713 TransformFunc transform; | |
714 }; | |
715 | |
716 template <typename SubParser, typename TransformFunc> | |
717 class TransformWithLocation_ { | |
718 public: | |
719 explicit constexpr TransformWithLocation_(SubParser&& subParser, TransformFunc&& transform) | |
720 : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {} | |
721 | |
722 template <typename Input> | |
723 Maybe<decltype(kj::apply(instance<TransformFunc&>(), | |
724 instance<Span<Decay<decltype(instance<Input&>().getPosition())>>>(), | |
725 instance<OutputType<SubParser, Input>&&>()))> | |
726 operator()(Input& input) const { | |
727 auto start = input.getPosition(); | |
728 KJ_IF_MAYBE(subResult, subParser(input)) { | |
729 return kj::apply(transform, Span<decltype(start)>(kj::mv(start), input.getPosition()), | |
730 kj::mv(*subResult)); | |
731 } else { | |
732 return nullptr; | |
733 } | |
734 } | |
735 | |
736 private: | |
737 SubParser subParser; | |
738 TransformFunc transform; | |
739 }; | |
740 | |
741 template <typename SubParser, typename TransformFunc> | |
742 constexpr Transform_<SubParser, TransformFunc> transform( | |
743 SubParser&& subParser, TransformFunc&& functor) { | |
744 // Constructs a parser which executes some other parser and then transforms the result by invoking | |
745 // `functor` on it. Typically `functor` is a lambda. It is invoked using `kj::apply`, | |
746 // meaning tuples will be unpacked as arguments. | |
747 return Transform_<SubParser, TransformFunc>( | |
748 kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | |
749 } | |
750 | |
751 template <typename SubParser, typename TransformFunc> | |
752 constexpr TransformOrReject_<SubParser, TransformFunc> transformOrReject( | |
753 SubParser&& subParser, TransformFunc&& functor) { | |
754 // Like `transform()` except that `functor` returns a `Maybe`. If it returns null, parsing fails, | |
755 // otherwise the parser's result is the content of the `Maybe`. | |
756 return TransformOrReject_<SubParser, TransformFunc>( | |
757 kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | |
758 } | |
759 | |
760 template <typename SubParser, typename TransformFunc> | |
761 constexpr TransformWithLocation_<SubParser, TransformFunc> transformWithLocation( | |
762 SubParser&& subParser, TransformFunc&& functor) { | |
763 // Like `transform` except that `functor` also takes a `Span` as its first parameter specifying | |
764 // the location of the parsed content. The span's position type is whatever the parser input's | |
765 // getPosition() returns. | |
766 return TransformWithLocation_<SubParser, TransformFunc>( | |
767 kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor)); | |
768 } | |
769 | |
770 // ------------------------------------------------------------------- | |
771 // notLookingAt() | |
772 // Fails if the given parser succeeds at the current location. | |
773 | |
774 template <typename SubParser> | |
775 class NotLookingAt_ { | |
776 public: | |
777 explicit constexpr NotLookingAt_(SubParser&& subParser) | |
778 : subParser(kj::fwd<SubParser>(subParser)) {} | |
779 | |
780 template <typename Input> | |
781 Maybe<Tuple<>> operator()(Input& input) const { | |
782 Input subInput(input); | |
783 subInput.forgetParent(); | |
784 if (subParser(subInput) == nullptr) { | |
785 return Tuple<>(); | |
786 } else { | |
787 return nullptr; | |
788 } | |
789 } | |
790 | |
791 private: | |
792 SubParser subParser; | |
793 }; | |
794 | |
795 template <typename SubParser> | |
796 constexpr NotLookingAt_<SubParser> notLookingAt(SubParser&& subParser) { | |
797 // Constructs a parser which fails at any position where the given parser succeeds. Otherwise, | |
798 // it succeeds without consuming any input and returns an empty tuple. | |
799 return NotLookingAt_<SubParser>(kj::fwd<SubParser>(subParser)); | |
800 } | |
801 | |
802 // ------------------------------------------------------------------- | |
803 // endOfInput() | |
804 // Output = Tuple<>, only succeeds if at end-of-input | |
805 | |
806 class EndOfInput_ { | |
807 public: | |
808 template <typename Input> | |
809 Maybe<Tuple<>> operator()(Input& input) const { | |
810 if (input.atEnd()) { | |
811 return Tuple<>(); | |
812 } else { | |
813 return nullptr; | |
814 } | |
815 } | |
816 }; | |
817 | |
818 constexpr EndOfInput_ endOfInput = EndOfInput_(); | |
819 // A parser that succeeds only if it is called with no input. | |
820 | |
821 } // namespace parse | |
822 } // namespace kj | |
823 | |
824 #endif // KJ_PARSE_COMMON_H_ |