diff osx/include/kj/parse/common.h @ 62:0994c39f1e94

Cap'n Proto v0.6 + build for OSX
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 22 May 2017 10:01:37 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osx/include/kj/parse/common.h	Mon May 22 10:01:37 2017 +0100
@@ -0,0 +1,824 @@
+// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
+// Licensed under the MIT License:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Parser combinator framework!
+//
+// This file declares several functions which construct parsers, usually taking other parsers as
+// input, thus making them parser combinators.
+//
+// A valid parser is any functor which takes a reference to an input cursor (defined below) as its
+// input and returns a Maybe.  The parser returns null on parse failure, or returns the parsed
+// result on success.
+//
+// An "input cursor" is any type which implements the same interface as IteratorInput, below.  Such
+// a type acts as a pointer to the current input location.  When a parser returns successfully, it
+// will have updated the input cursor to point to the position just past the end of what was parsed.
+// On failure, the cursor position is unspecified.
+
+#ifndef KJ_PARSE_COMMON_H_
+#define KJ_PARSE_COMMON_H_
+
+#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
+#pragma GCC system_header
+#endif
+
+#include "../common.h"
+#include "../memory.h"
+#include "../array.h"
+#include "../tuple.h"
+#include "../vector.h"
+#if _MSC_VER
+#include <type_traits>  // result_of_t
+#endif
+
+namespace kj {
+namespace parse {
+
+template <typename Element, typename Iterator>
+class IteratorInput {
+  // A parser input implementation based on an iterator range.
+
+public:
+  IteratorInput(Iterator begin, Iterator end)
+      : parent(nullptr), pos(begin), end(end), best(begin) {}
+  explicit IteratorInput(IteratorInput& parent)
+      : parent(&parent), pos(parent.pos), end(parent.end), best(parent.pos) {}
+  ~IteratorInput() {
+    if (parent != nullptr) {
+      parent->best = kj::max(kj::max(pos, best), parent->best);
+    }
+  }
+  KJ_DISALLOW_COPY(IteratorInput);
+
+  void advanceParent() {
+    parent->pos = pos;
+  }
+  void forgetParent() {
+    parent = nullptr;
+  }
+
+  bool atEnd() { return pos == end; }
+  auto current() -> decltype(*instance<Iterator>()) {
+    KJ_IREQUIRE(!atEnd());
+    return *pos;
+  }
+  auto consume() -> decltype(*instance<Iterator>()) {
+    KJ_IREQUIRE(!atEnd());
+    return *pos++;
+  }
+  void next() {
+    KJ_IREQUIRE(!atEnd());
+    ++pos;
+  }
+
+  Iterator getBest() { return kj::max(pos, best); }
+
+  Iterator getPosition() { return pos; }
+
+private:
+  IteratorInput* parent;
+  Iterator pos;
+  Iterator end;
+  Iterator best;  // furthest we got with any sub-input
+};
+
+template <typename T> struct OutputType_;
+template <typename T> struct OutputType_<Maybe<T>> { typedef T Type; };
+template <typename Parser, typename Input>
+using OutputType = typename OutputType_<
+#if _MSC_VER
+    std::result_of_t<Parser(Input)>
+    // The instance<T&>() based version below results in:
+    //   C2064: term does not evaluate to a function taking 1 arguments
+#else
+    decltype(instance<Parser&>()(instance<Input&>()))
+#endif
+    >::Type;
+// Synonym for the output type of a parser, given the parser type and the input type.
+
+// =======================================================================================
+
+template <typename Input, typename Output>
+class ParserRef {
+  // Acts as a reference to some other parser, with simplified type.  The referenced parser
+  // is polymorphic by virtual call rather than templates.  For grammars of non-trivial size,
+  // it is important to inject refs into the grammar here and there to prevent the parser types
+  // from becoming ridiculous.  Using too many of them can hurt performance, though.
+
+public:
+  ParserRef(): parser(nullptr), wrapper(nullptr) {}
+  ParserRef(const ParserRef&) = default;
+  ParserRef(ParserRef&&) = default;
+  ParserRef& operator=(const ParserRef& other) = default;
+  ParserRef& operator=(ParserRef&& other) = default;
+
+  template <typename Other>
+  constexpr ParserRef(Other&& other)
+      : parser(&other), wrapper(&WrapperImplInstance<Decay<Other>>::instance) {
+    static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary.");
+  }
+
+  template <typename Other>
+  inline ParserRef& operator=(Other&& other) {
+    static_assert(kj::isReference<Other>(), "ParserRef should not be assigned to a temporary.");
+    parser = &other;
+    wrapper = &WrapperImplInstance<Decay<Other>>::instance;
+    return *this;
+  }
+
+  KJ_ALWAYS_INLINE(Maybe<Output> operator()(Input& input) const) {
+    // Always inline in the hopes that this allows branch prediction to kick in so the virtual call
+    // doesn't hurt so much.
+    return wrapper->parse(parser, input);
+  }
+
+private:
+  struct Wrapper {
+    virtual Maybe<Output> parse(const void* parser, Input& input) const = 0;
+  };
+  template <typename ParserImpl>
+  struct WrapperImpl: public Wrapper {
+    Maybe<Output> parse(const void* parser, Input& input) const override {
+      return (*reinterpret_cast<const ParserImpl*>(parser))(input);
+    }
+  };
+  template <typename ParserImpl>
+  struct WrapperImplInstance {
+#if _MSC_VER
+    // TODO(msvc): MSVC currently fails to initialize vtable pointers for constexpr values so
+    //   we have to make this just const instead.
+    static const WrapperImpl<ParserImpl> instance;
+#else
+    static constexpr WrapperImpl<ParserImpl> instance = WrapperImpl<ParserImpl>();
+#endif
+  };
+
+  const void* parser;
+  const Wrapper* wrapper;
+};
+
+template <typename Input, typename Output>
+template <typename ParserImpl>
+#if _MSC_VER
+const typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl>
+ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance = WrapperImpl<ParserImpl>();
+#else
+constexpr typename ParserRef<Input, Output>::template WrapperImpl<ParserImpl>
+ParserRef<Input, Output>::WrapperImplInstance<ParserImpl>::instance;
+#endif
+
+template <typename Input, typename ParserImpl>
+constexpr ParserRef<Input, OutputType<ParserImpl, Input>> ref(ParserImpl& impl) {
+  // Constructs a ParserRef.  You must specify the input type explicitly, e.g.
+  // `ref<MyInput>(myParser)`.
+
+  return ParserRef<Input, OutputType<ParserImpl, Input>>(impl);
+}
+
+// -------------------------------------------------------------------
+// any
+// Output = one token
+
+class Any_ {
+public:
+  template <typename Input>
+  Maybe<Decay<decltype(instance<Input>().consume())>> operator()(Input& input) const {
+    if (input.atEnd()) {
+      return nullptr;
+    } else {
+      return input.consume();
+    }
+  }
+};
+
+constexpr Any_ any = Any_();
+// A parser which matches any token and simply returns it.
+
+// -------------------------------------------------------------------
+// exactly()
+// Output = Tuple<>
+
+template <typename T>
+class Exactly_ {
+public:
+  explicit constexpr Exactly_(T&& expected): expected(expected) {}
+
+  template <typename Input>
+  Maybe<Tuple<>> operator()(Input& input) const {
+    if (input.atEnd() || input.current() != expected) {
+      return nullptr;
+    } else {
+      input.next();
+      return Tuple<>();
+    }
+  }
+
+private:
+  T expected;
+};
+
+template <typename T>
+constexpr Exactly_<T> exactly(T&& expected) {
+  // Constructs a parser which succeeds when the input is exactly the token specified.  The
+  // result is always the empty tuple.
+
+  return Exactly_<T>(kj::fwd<T>(expected));
+}
+
+// -------------------------------------------------------------------
+// exactlyConst()
+// Output = Tuple<>
+
+template <typename T, T expected>
+class ExactlyConst_ {
+public:
+  explicit constexpr ExactlyConst_() {}
+
+  template <typename Input>
+  Maybe<Tuple<>> operator()(Input& input) const {
+    if (input.atEnd() || input.current() != expected) {
+      return nullptr;
+    } else {
+      input.next();
+      return Tuple<>();
+    }
+  }
+};
+
+template <typename T, T expected>
+constexpr ExactlyConst_<T, expected> exactlyConst() {
+  // Constructs a parser which succeeds when the input is exactly the token specified.  The
+  // result is always the empty tuple.  This parser is templated on the token value which may cause
+  // it to perform better -- or worse.  Be sure to measure.
+
+  return ExactlyConst_<T, expected>();
+}
+
+// -------------------------------------------------------------------
+// constResult()
+
+template <typename SubParser, typename Result>
+class ConstResult_ {
+public:
+  explicit constexpr ConstResult_(SubParser&& subParser, Result&& result)
+      : subParser(kj::fwd<SubParser>(subParser)), result(kj::fwd<Result>(result)) {}
+
+  template <typename Input>
+  Maybe<Result> operator()(Input& input) const {
+    if (subParser(input) == nullptr) {
+      return nullptr;
+    } else {
+      return result;
+    }
+  }
+
+private:
+  SubParser subParser;
+  Result result;
+};
+
+template <typename SubParser, typename Result>
+constexpr ConstResult_<SubParser, Result> constResult(SubParser&& subParser, Result&& result) {
+  // Constructs a parser which returns exactly `result` if `subParser` is successful.
+  return ConstResult_<SubParser, Result>(kj::fwd<SubParser>(subParser), kj::fwd<Result>(result));
+}
+
+template <typename SubParser>
+constexpr ConstResult_<SubParser, Tuple<>> discard(SubParser&& subParser) {
+  // Constructs a parser which wraps `subParser` but discards the result.
+  return constResult(kj::fwd<SubParser>(subParser), Tuple<>());
+}
+
+// -------------------------------------------------------------------
+// sequence()
+// Output = Flattened Tuple of outputs of sub-parsers.
+
+template <typename... SubParsers> class Sequence_;
+
+template <typename FirstSubParser, typename... SubParsers>
+class Sequence_<FirstSubParser, SubParsers...> {
+public:
+  template <typename T, typename... U>
+  explicit constexpr Sequence_(T&& firstSubParser, U&&... rest)
+      : first(kj::fwd<T>(firstSubParser)), rest(kj::fwd<U>(rest)...) {}
+
+  // TODO(msvc): The trailing return types on `operator()` and `parseNext()` expose at least two
+  //   bugs in MSVC:
+  //
+  //     1. An ICE.
+  //     2. 'error C2672: 'operator __surrogate_func': no matching overloaded function found)',
+  //        which crops up in numerous places when trying to build the capnp command line tools.
+  //
+  //   The only workaround I found for both bugs is to omit the trailing return types and instead
+  //   rely on C++14's return type deduction.
+
+  template <typename Input>
+  auto operator()(Input& input) const
+#ifndef _MSC_VER
+      -> Maybe<decltype(tuple(
+          instance<OutputType<FirstSubParser, Input>>(),
+          instance<OutputType<SubParsers, Input>>()...))>
+#endif
+  {
+    return parseNext(input);
+  }
+
+  template <typename Input, typename... InitialParams>
+  auto parseNext(Input& input, InitialParams&&... initialParams) const
+#ifndef _MSC_VER
+      -> Maybe<decltype(tuple(
+          kj::fwd<InitialParams>(initialParams)...,
+          instance<OutputType<FirstSubParser, Input>>(),
+          instance<OutputType<SubParsers, Input>>()...))>
+#endif
+  {
+    KJ_IF_MAYBE(firstResult, first(input)) {
+      return rest.parseNext(input, kj::fwd<InitialParams>(initialParams)...,
+                            kj::mv(*firstResult));
+    } else {
+      // TODO(msvc): MSVC depends on return type deduction to compile this function, so we need to
+      //   help it deduce the right type on this code path.
+      return Maybe<decltype(tuple(
+          kj::fwd<InitialParams>(initialParams)...,
+          instance<OutputType<FirstSubParser, Input>>(),
+          instance<OutputType<SubParsers, Input>>()...))>{nullptr};
+    }
+  }
+
+private:
+  FirstSubParser first;
+  Sequence_<SubParsers...> rest;
+};
+
+template <>
+class Sequence_<> {
+public:
+  template <typename Input>
+  Maybe<Tuple<>> operator()(Input& input) const {
+    return parseNext(input);
+  }
+
+  template <typename Input, typename... Params>
+  auto parseNext(Input& input, Params&&... params) const ->
+      Maybe<decltype(tuple(kj::fwd<Params>(params)...))> {
+    return tuple(kj::fwd<Params>(params)...);
+  }
+};
+
+template <typename... SubParsers>
+constexpr Sequence_<SubParsers...> sequence(SubParsers&&... subParsers) {
+  // Constructs a parser that executes each of the parameter parsers in sequence and returns a
+  // tuple of their results.
+
+  return Sequence_<SubParsers...>(kj::fwd<SubParsers>(subParsers)...);
+}
+
+// -------------------------------------------------------------------
+// many()
+// Output = Array of output of sub-parser, or just a uint count if the sub-parser returns Tuple<>.
+
+template <typename SubParser, bool atLeastOne>
+class Many_ {
+  template <typename Input, typename Output = OutputType<SubParser, Input>>
+  struct Impl;
+public:
+  explicit constexpr Many_(SubParser&& subParser)
+      : subParser(kj::fwd<SubParser>(subParser)) {}
+
+  template <typename Input>
+  auto operator()(Input& input) const
+      -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input));
+
+private:
+  SubParser subParser;
+};
+
+template <typename SubParser, bool atLeastOne>
+template <typename Input, typename Output>
+struct Many_<SubParser, atLeastOne>::Impl {
+  static Maybe<Array<Output>> apply(const SubParser& subParser, Input& input) {
+    typedef Vector<OutputType<SubParser, Input>> Results;
+    Results results;
+
+    while (!input.atEnd()) {
+      Input subInput(input);
+
+      KJ_IF_MAYBE(subResult, subParser(subInput)) {
+        subInput.advanceParent();
+        results.add(kj::mv(*subResult));
+      } else {
+        break;
+      }
+    }
+
+    if (atLeastOne && results.empty()) {
+      return nullptr;
+    }
+
+    return results.releaseAsArray();
+  }
+};
+
+template <typename SubParser, bool atLeastOne>
+template <typename Input>
+struct Many_<SubParser, atLeastOne>::Impl<Input, Tuple<>> {
+  // If the sub-parser output is Tuple<>, just return a count.
+
+  static Maybe<uint> apply(const SubParser& subParser, Input& input) {
+    uint count = 0;
+
+    while (!input.atEnd()) {
+      Input subInput(input);
+
+      KJ_IF_MAYBE(subResult, subParser(subInput)) {
+        subInput.advanceParent();
+        ++count;
+      } else {
+        break;
+      }
+    }
+
+    if (atLeastOne && count == 0) {
+      return nullptr;
+    }
+
+    return count;
+  }
+};
+
+template <typename SubParser, bool atLeastOne>
+template <typename Input>
+auto Many_<SubParser, atLeastOne>::operator()(Input& input) const
+    -> decltype(Impl<Input>::apply(instance<const SubParser&>(), input)) {
+  return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, input);
+}
+
+template <typename SubParser>
+constexpr Many_<SubParser, false> many(SubParser&& subParser) {
+  // Constructs a parser that repeatedly executes the given parser until it fails, returning an
+  // Array of the results (or a uint count if `subParser` returns an empty tuple).
+  return Many_<SubParser, false>(kj::fwd<SubParser>(subParser));
+}
+
+template <typename SubParser>
+constexpr Many_<SubParser, true> oneOrMore(SubParser&& subParser) {
+  // Like `many()` but the parser must parse at least one item to be successful.
+  return Many_<SubParser, true>(kj::fwd<SubParser>(subParser));
+}
+
+// -------------------------------------------------------------------
+// times()
+// Output = Array of output of sub-parser, or Tuple<> if sub-parser returns Tuple<>.
+
+template <typename SubParser>
+class Times_ {
+  template <typename Input, typename Output = OutputType<SubParser, Input>>
+  struct Impl;
+public:
+  explicit constexpr Times_(SubParser&& subParser, uint count)
+      : subParser(kj::fwd<SubParser>(subParser)), count(count) {}
+
+  template <typename Input>
+  auto operator()(Input& input) const
+      -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input));
+
+private:
+  SubParser subParser;
+  uint count;
+};
+
+template <typename SubParser>
+template <typename Input, typename Output>
+struct Times_<SubParser>::Impl {
+  static Maybe<Array<Output>> apply(const SubParser& subParser, uint count, Input& input) {
+    auto results = heapArrayBuilder<OutputType<SubParser, Input>>(count);
+
+    while (results.size() < count) {
+      if (input.atEnd()) {
+        return nullptr;
+      } else KJ_IF_MAYBE(subResult, subParser(input)) {
+        results.add(kj::mv(*subResult));
+      } else {
+        return nullptr;
+      }
+    }
+
+    return results.finish();
+  }
+};
+
+template <typename SubParser>
+template <typename Input>
+struct Times_<SubParser>::Impl<Input, Tuple<>> {
+  // If the sub-parser output is Tuple<>, just return a count.
+
+  static Maybe<Tuple<>> apply(const SubParser& subParser, uint count, Input& input) {
+    uint actualCount = 0;
+
+    while (actualCount < count) {
+      if (input.atEnd()) {
+        return nullptr;
+      } else KJ_IF_MAYBE(subResult, subParser(input)) {
+        ++actualCount;
+      } else {
+        return nullptr;
+      }
+    }
+
+    return tuple();
+  }
+};
+
+template <typename SubParser>
+template <typename Input>
+auto Times_<SubParser>::operator()(Input& input) const
+    -> decltype(Impl<Input>::apply(instance<const SubParser&>(), instance<uint>(), input)) {
+  return Impl<Input, OutputType<SubParser, Input>>::apply(subParser, count, input);
+}
+
+template <typename SubParser>
+constexpr Times_<SubParser> times(SubParser&& subParser, uint count) {
+  // Constructs a parser that repeats the subParser exactly `count` times.
+  return Times_<SubParser>(kj::fwd<SubParser>(subParser), count);
+}
+
+// -------------------------------------------------------------------
+// optional()
+// Output = Maybe<output of sub-parser>
+
+template <typename SubParser>
+class Optional_ {
+public:
+  explicit constexpr Optional_(SubParser&& subParser)
+      : subParser(kj::fwd<SubParser>(subParser)) {}
+
+  template <typename Input>
+  Maybe<Maybe<OutputType<SubParser, Input>>> operator()(Input& input) const {
+    typedef Maybe<OutputType<SubParser, Input>> Result;
+
+    Input subInput(input);
+    KJ_IF_MAYBE(subResult, subParser(subInput)) {
+      subInput.advanceParent();
+      return Result(kj::mv(*subResult));
+    } else {
+      return Result(nullptr);
+    }
+  }
+
+private:
+  SubParser subParser;
+};
+
+template <typename SubParser>
+constexpr Optional_<SubParser> optional(SubParser&& subParser) {
+  // Constructs a parser that accepts zero or one of the given sub-parser, returning a Maybe
+  // of the sub-parser's result.
+  return Optional_<SubParser>(kj::fwd<SubParser>(subParser));
+}
+
+// -------------------------------------------------------------------
+// oneOf()
+// All SubParsers must have same output type, which becomes the output type of the
+// OneOfParser.
+
+template <typename... SubParsers>
+class OneOf_;
+
+template <typename FirstSubParser, typename... SubParsers>
+class OneOf_<FirstSubParser, SubParsers...> {
+public:
+  explicit constexpr OneOf_(FirstSubParser&& firstSubParser, SubParsers&&... rest)
+      : first(kj::fwd<FirstSubParser>(firstSubParser)), rest(kj::fwd<SubParsers>(rest)...) {}
+
+  template <typename Input>
+  Maybe<OutputType<FirstSubParser, Input>> operator()(Input& input) const {
+    {
+      Input subInput(input);
+      Maybe<OutputType<FirstSubParser, Input>> firstResult = first(subInput);
+
+      if (firstResult != nullptr) {
+        subInput.advanceParent();
+        return kj::mv(firstResult);
+      }
+    }
+
+    // Hoping for some tail recursion here...
+    return rest(input);
+  }
+
+private:
+  FirstSubParser first;
+  OneOf_<SubParsers...> rest;
+};
+
+template <>
+class OneOf_<> {
+public:
+  template <typename Input>
+  decltype(nullptr) operator()(Input& input) const {
+    return nullptr;
+  }
+};
+
+template <typename... SubParsers>
+constexpr OneOf_<SubParsers...> oneOf(SubParsers&&... parsers) {
+  // Constructs a parser that accepts one of a set of options.  The parser behaves as the first
+  // sub-parser in the list which returns successfully.  All of the sub-parsers must return the
+  // same type.
+  return OneOf_<SubParsers...>(kj::fwd<SubParsers>(parsers)...);
+}
+
+// -------------------------------------------------------------------
+// transform()
+// Output = Result of applying transform functor to input value.  If input is a tuple, it is
+// unpacked to form the transformation parameters.
+
+template <typename Position>
+struct Span {
+public:
+  inline const Position& begin() const { return begin_; }
+  inline const Position& end() const { return end_; }
+
+  Span() = default;
+  inline constexpr Span(Position&& begin, Position&& end): begin_(mv(begin)), end_(mv(end)) {}
+
+private:
+  Position begin_;
+  Position end_;
+};
+
+template <typename Position>
+constexpr Span<Decay<Position>> span(Position&& start, Position&& end) {
+  return Span<Decay<Position>>(kj::fwd<Position>(start), kj::fwd<Position>(end));
+}
+
+template <typename SubParser, typename TransformFunc>
+class Transform_ {
+public:
+  explicit constexpr Transform_(SubParser&& subParser, TransformFunc&& transform)
+      : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {}
+
+  template <typename Input>
+  Maybe<decltype(kj::apply(instance<TransformFunc&>(),
+                           instance<OutputType<SubParser, Input>&&>()))>
+      operator()(Input& input) const {
+    KJ_IF_MAYBE(subResult, subParser(input)) {
+      return kj::apply(transform, kj::mv(*subResult));
+    } else {
+      return nullptr;
+    }
+  }
+
+private:
+  SubParser subParser;
+  TransformFunc transform;
+};
+
+template <typename SubParser, typename TransformFunc>
+class TransformOrReject_ {
+public:
+  explicit constexpr TransformOrReject_(SubParser&& subParser, TransformFunc&& transform)
+      : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {}
+
+  template <typename Input>
+  decltype(kj::apply(instance<TransformFunc&>(), instance<OutputType<SubParser, Input>&&>()))
+      operator()(Input& input) const {
+    KJ_IF_MAYBE(subResult, subParser(input)) {
+      return kj::apply(transform, kj::mv(*subResult));
+    } else {
+      return nullptr;
+    }
+  }
+
+private:
+  SubParser subParser;
+  TransformFunc transform;
+};
+
+template <typename SubParser, typename TransformFunc>
+class TransformWithLocation_ {
+public:
+  explicit constexpr TransformWithLocation_(SubParser&& subParser, TransformFunc&& transform)
+      : subParser(kj::fwd<SubParser>(subParser)), transform(kj::fwd<TransformFunc>(transform)) {}
+
+  template <typename Input>
+  Maybe<decltype(kj::apply(instance<TransformFunc&>(),
+                           instance<Span<Decay<decltype(instance<Input&>().getPosition())>>>(),
+                           instance<OutputType<SubParser, Input>&&>()))>
+      operator()(Input& input) const {
+    auto start = input.getPosition();
+    KJ_IF_MAYBE(subResult, subParser(input)) {
+      return kj::apply(transform, Span<decltype(start)>(kj::mv(start), input.getPosition()),
+                       kj::mv(*subResult));
+    } else {
+      return nullptr;
+    }
+  }
+
+private:
+  SubParser subParser;
+  TransformFunc transform;
+};
+
+template <typename SubParser, typename TransformFunc>
+constexpr Transform_<SubParser, TransformFunc> transform(
+    SubParser&& subParser, TransformFunc&& functor) {
+  // Constructs a parser which executes some other parser and then transforms the result by invoking
+  // `functor` on it.  Typically `functor` is a lambda.  It is invoked using `kj::apply`,
+  // meaning tuples will be unpacked as arguments.
+  return Transform_<SubParser, TransformFunc>(
+      kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor));
+}
+
+template <typename SubParser, typename TransformFunc>
+constexpr TransformOrReject_<SubParser, TransformFunc> transformOrReject(
+    SubParser&& subParser, TransformFunc&& functor) {
+  // Like `transform()` except that `functor` returns a `Maybe`.  If it returns null, parsing fails,
+  // otherwise the parser's result is the content of the `Maybe`.
+  return TransformOrReject_<SubParser, TransformFunc>(
+      kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor));
+}
+
+template <typename SubParser, typename TransformFunc>
+constexpr TransformWithLocation_<SubParser, TransformFunc> transformWithLocation(
+    SubParser&& subParser, TransformFunc&& functor) {
+  // Like `transform` except that `functor` also takes a `Span` as its first parameter specifying
+  // the location of the parsed content.  The span's position type is whatever the parser input's
+  // getPosition() returns.
+  return TransformWithLocation_<SubParser, TransformFunc>(
+      kj::fwd<SubParser>(subParser), kj::fwd<TransformFunc>(functor));
+}
+
+// -------------------------------------------------------------------
+// notLookingAt()
+// Fails if the given parser succeeds at the current location.
+
+template <typename SubParser>
+class NotLookingAt_ {
+public:
+  explicit constexpr NotLookingAt_(SubParser&& subParser)
+      : subParser(kj::fwd<SubParser>(subParser)) {}
+
+  template <typename Input>
+  Maybe<Tuple<>> operator()(Input& input) const {
+    Input subInput(input);
+    subInput.forgetParent();
+    if (subParser(subInput) == nullptr) {
+      return Tuple<>();
+    } else {
+      return nullptr;
+    }
+  }
+
+private:
+  SubParser subParser;
+};
+
+template <typename SubParser>
+constexpr NotLookingAt_<SubParser> notLookingAt(SubParser&& subParser) {
+  // Constructs a parser which fails at any position where the given parser succeeds.  Otherwise,
+  // it succeeds without consuming any input and returns an empty tuple.
+  return NotLookingAt_<SubParser>(kj::fwd<SubParser>(subParser));
+}
+
+// -------------------------------------------------------------------
+// endOfInput()
+// Output = Tuple<>, only succeeds if at end-of-input
+
+class EndOfInput_ {
+public:
+  template <typename Input>
+  Maybe<Tuple<>> operator()(Input& input) const {
+    if (input.atEnd()) {
+      return Tuple<>();
+    } else {
+      return nullptr;
+    }
+  }
+};
+
+constexpr EndOfInput_ endOfInput = EndOfInput_();
+// A parser that succeeds only if it is called with no input.
+
+}  // namespace parse
+}  // namespace kj
+
+#endif  // KJ_PARSE_COMMON_H_