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