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