annotate osx/include/kj/parse/common.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +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_