annotate osx/include/kj/parse/common.h @ 68:85d5306e114e

Remove subrepo - trying to avoid these now
author Chris Cannam
date Tue, 04 Dec 2018 10:27:12 +0000
parents 0994c39f1e94
children
rev   line source
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_