annotate osx/include/kj/parse/common.h @ 169:223a55898ab9 tip default

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