mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-03-01 08:13:52 +08:00
bring over phonelibs minus frida-gum and qsml
This commit is contained in:
361
phonelibs/capnp-cpp/mac/include/kj/parse/char.h
Normal file
361
phonelibs/capnp-cpp/mac/include/kj/parse/char.h
Normal file
@@ -0,0 +1,361 @@
|
||||
// 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.
|
||||
|
||||
// This file contains parsers useful for character stream inputs, including parsers to parse
|
||||
// common kinds of tokens like identifiers, numbers, and quoted strings.
|
||||
|
||||
#ifndef KJ_PARSE_CHAR_H_
|
||||
#define KJ_PARSE_CHAR_H_
|
||||
|
||||
#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "../string.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace kj {
|
||||
namespace parse {
|
||||
|
||||
// =======================================================================================
|
||||
// Exact char/string.
|
||||
|
||||
class ExactString_ {
|
||||
public:
|
||||
constexpr inline ExactString_(const char* str): str(str) {}
|
||||
|
||||
template <typename Input>
|
||||
Maybe<Tuple<>> operator()(Input& input) const {
|
||||
const char* ptr = str;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (input.atEnd() || input.current() != *ptr) return nullptr;
|
||||
input.next();
|
||||
++ptr;
|
||||
}
|
||||
|
||||
return Tuple<>();
|
||||
}
|
||||
|
||||
private:
|
||||
const char* str;
|
||||
};
|
||||
|
||||
constexpr inline ExactString_ exactString(const char* str) {
|
||||
return ExactString_(str);
|
||||
}
|
||||
|
||||
template <char c>
|
||||
constexpr ExactlyConst_<char, c> exactChar() {
|
||||
// Returns a parser that matches exactly the character given by the template argument (returning
|
||||
// no result).
|
||||
return ExactlyConst_<char, c>();
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Char ranges / sets
|
||||
|
||||
class CharGroup_ {
|
||||
public:
|
||||
constexpr inline CharGroup_(): bits{0, 0, 0, 0} {}
|
||||
|
||||
constexpr inline CharGroup_ orRange(unsigned char first, unsigned char last) const {
|
||||
return CharGroup_(bits[0] | (oneBits(last + 1) & ~oneBits(first )),
|
||||
bits[1] | (oneBits(last - 63) & ~oneBits(first - 64)),
|
||||
bits[2] | (oneBits(last - 127) & ~oneBits(first - 128)),
|
||||
bits[3] | (oneBits(last - 191) & ~oneBits(first - 192)));
|
||||
}
|
||||
|
||||
constexpr inline CharGroup_ orAny(const char* chars) const {
|
||||
return *chars == 0 ? *this : orChar(*chars).orAny(chars + 1);
|
||||
}
|
||||
|
||||
constexpr inline CharGroup_ orChar(unsigned char c) const {
|
||||
return CharGroup_(bits[0] | bit(c),
|
||||
bits[1] | bit(c - 64),
|
||||
bits[2] | bit(c - 128),
|
||||
bits[3] | bit(c - 256));
|
||||
}
|
||||
|
||||
constexpr inline CharGroup_ orGroup(CharGroup_ other) const {
|
||||
return CharGroup_(bits[0] | other.bits[0],
|
||||
bits[1] | other.bits[1],
|
||||
bits[2] | other.bits[2],
|
||||
bits[3] | other.bits[3]);
|
||||
}
|
||||
|
||||
constexpr inline CharGroup_ invert() const {
|
||||
return CharGroup_(~bits[0], ~bits[1], ~bits[2], ~bits[3]);
|
||||
}
|
||||
|
||||
constexpr inline bool contains(unsigned char c) const {
|
||||
return (bits[c / 64] & (1ll << (c % 64))) != 0;
|
||||
}
|
||||
|
||||
template <typename Input>
|
||||
Maybe<char> operator()(Input& input) const {
|
||||
if (input.atEnd()) return nullptr;
|
||||
unsigned char c = input.current();
|
||||
if (contains(c)) {
|
||||
input.next();
|
||||
return c;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef unsigned long long Bits64;
|
||||
|
||||
constexpr inline CharGroup_(Bits64 a, Bits64 b, Bits64 c, Bits64 d): bits{a, b, c, d} {}
|
||||
Bits64 bits[4];
|
||||
|
||||
static constexpr inline Bits64 oneBits(int count) {
|
||||
return count <= 0 ? 0ll : count >= 64 ? -1ll : ((1ll << count) - 1);
|
||||
}
|
||||
static constexpr inline Bits64 bit(int index) {
|
||||
return index < 0 ? 0 : index >= 64 ? 0 : (1ll << index);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr inline CharGroup_ charRange(char first, char last) {
|
||||
// Create a parser which accepts any character in the range from `first` to `last`, inclusive.
|
||||
// For example: `charRange('a', 'z')` matches all lower-case letters. The parser's result is the
|
||||
// character matched.
|
||||
//
|
||||
// The returned object has methods which can be used to match more characters. The following
|
||||
// produces a parser which accepts any letter as well as '_', '+', '-', and '.'.
|
||||
//
|
||||
// charRange('a', 'z').orRange('A', 'Z').orChar('_').orAny("+-.")
|
||||
//
|
||||
// You can also use `.invert()` to match the opposite set of characters.
|
||||
|
||||
return CharGroup_().orRange(first, last);
|
||||
}
|
||||
|
||||
#if _MSC_VER
|
||||
#define anyOfChars(chars) CharGroup_().orAny(chars)
|
||||
// TODO(msvc): MSVC ICEs on the proper definition of `anyOfChars()`, which in turn prevents us from
|
||||
// building the compiler or schema parser. We don't know why this happens, but Harris found that
|
||||
// this horrible, horrible hack makes things work. This is awful, but it's better than nothing.
|
||||
// Hopefully, MSVC will get fixed soon and we'll be able to remove this.
|
||||
#else
|
||||
constexpr inline CharGroup_ anyOfChars(const char* chars) {
|
||||
// Returns a parser that accepts any of the characters in the given string (which should usually
|
||||
// be a literal). The returned parser is of the same type as returned by `charRange()` -- see
|
||||
// that function for more info.
|
||||
|
||||
return CharGroup_().orAny(chars);
|
||||
}
|
||||
#endif
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
struct ArrayToString {
|
||||
inline String operator()(const Array<char>& arr) const {
|
||||
return heapString(arr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename SubParser>
|
||||
constexpr inline auto charsToString(SubParser&& subParser)
|
||||
-> decltype(transform(kj::fwd<SubParser>(subParser), _::ArrayToString())) {
|
||||
// Wraps a parser that returns Array<char> such that it returns String instead.
|
||||
return parse::transform(kj::fwd<SubParser>(subParser), _::ArrayToString());
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Basic character classes.
|
||||
|
||||
constexpr auto alpha = charRange('a', 'z').orRange('A', 'Z');
|
||||
constexpr auto digit = charRange('0', '9');
|
||||
constexpr auto alphaNumeric = alpha.orGroup(digit);
|
||||
constexpr auto nameStart = alpha.orChar('_');
|
||||
constexpr auto nameChar = alphaNumeric.orChar('_');
|
||||
constexpr auto hexDigit = charRange('0', '9').orRange('a', 'f').orRange('A', 'F');
|
||||
constexpr auto octDigit = charRange('0', '7');
|
||||
constexpr auto whitespaceChar = anyOfChars(" \f\n\r\t\v");
|
||||
constexpr auto controlChar = charRange(0, 0x1f).invert().orGroup(whitespaceChar).invert();
|
||||
|
||||
constexpr auto whitespace = many(anyOfChars(" \f\n\r\t\v"));
|
||||
|
||||
constexpr auto discardWhitespace = discard(many(discard(anyOfChars(" \f\n\r\t\v"))));
|
||||
// Like discard(whitespace) but avoids some memory allocation.
|
||||
|
||||
// =======================================================================================
|
||||
// Identifiers
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
struct IdentifierToString {
|
||||
inline String operator()(char first, const Array<char>& rest) const {
|
||||
String result = heapString(rest.size() + 1);
|
||||
result[0] = first;
|
||||
memcpy(result.begin() + 1, rest.begin(), rest.size());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
constexpr auto identifier = transform(sequence(nameStart, many(nameChar)), _::IdentifierToString());
|
||||
// Parses an identifier (e.g. a C variable name).
|
||||
|
||||
// =======================================================================================
|
||||
// Integers
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
inline char parseDigit(char c) {
|
||||
if (c < 'A') return c - '0';
|
||||
if (c < 'a') return c - 'A' + 10;
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
|
||||
template <uint base>
|
||||
struct ParseInteger {
|
||||
inline uint64_t operator()(const Array<char>& digits) const {
|
||||
return operator()('0', digits);
|
||||
}
|
||||
uint64_t operator()(char first, const Array<char>& digits) const {
|
||||
uint64_t result = parseDigit(first);
|
||||
for (char digit: digits) {
|
||||
result = result * base + parseDigit(digit);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
constexpr auto integer = sequence(
|
||||
oneOf(
|
||||
transform(sequence(exactChar<'0'>(), exactChar<'x'>(), oneOrMore(hexDigit)), _::ParseInteger<16>()),
|
||||
transform(sequence(exactChar<'0'>(), many(octDigit)), _::ParseInteger<8>()),
|
||||
transform(sequence(charRange('1', '9'), many(digit)), _::ParseInteger<10>())),
|
||||
notLookingAt(alpha.orAny("_.")));
|
||||
|
||||
// =======================================================================================
|
||||
// Numbers (i.e. floats)
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
struct ParseFloat {
|
||||
double operator()(const Array<char>& digits,
|
||||
const Maybe<Array<char>>& fraction,
|
||||
const Maybe<Tuple<Maybe<char>, Array<char>>>& exponent) const;
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
constexpr auto number = transform(
|
||||
sequence(
|
||||
oneOrMore(digit),
|
||||
optional(sequence(exactChar<'.'>(), many(digit))),
|
||||
optional(sequence(discard(anyOfChars("eE")), optional(anyOfChars("+-")), many(digit))),
|
||||
notLookingAt(alpha.orAny("_."))),
|
||||
_::ParseFloat());
|
||||
|
||||
// =======================================================================================
|
||||
// Quoted strings
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
struct InterpretEscape {
|
||||
char operator()(char c) const {
|
||||
switch (c) {
|
||||
case 'a': return '\a';
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
case 'n': return '\n';
|
||||
case 'r': return '\r';
|
||||
case 't': return '\t';
|
||||
case 'v': return '\v';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ParseHexEscape {
|
||||
inline char operator()(char first, char second) const {
|
||||
return (parseDigit(first) << 4) | parseDigit(second);
|
||||
}
|
||||
};
|
||||
|
||||
struct ParseHexByte {
|
||||
inline byte operator()(char first, char second) const {
|
||||
return (parseDigit(first) << 4) | parseDigit(second);
|
||||
}
|
||||
};
|
||||
|
||||
struct ParseOctEscape {
|
||||
inline char operator()(char first, Maybe<char> second, Maybe<char> third) const {
|
||||
char result = first - '0';
|
||||
KJ_IF_MAYBE(digit1, second) {
|
||||
result = (result << 3) | (*digit1 - '0');
|
||||
KJ_IF_MAYBE(digit2, third) {
|
||||
result = (result << 3) | (*digit2 - '0');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
constexpr auto escapeSequence =
|
||||
sequence(exactChar<'\\'>(), oneOf(
|
||||
transform(anyOfChars("abfnrtv'\"\\\?"), _::InterpretEscape()),
|
||||
transform(sequence(exactChar<'x'>(), hexDigit, hexDigit), _::ParseHexEscape()),
|
||||
transform(sequence(octDigit, optional(octDigit), optional(octDigit)),
|
||||
_::ParseOctEscape())));
|
||||
// A parser that parses a C-string-style escape sequence (starting with a backslash). Returns
|
||||
// a char.
|
||||
|
||||
constexpr auto doubleQuotedString = charsToString(sequence(
|
||||
exactChar<'\"'>(),
|
||||
many(oneOf(anyOfChars("\\\n\"").invert(), escapeSequence)),
|
||||
exactChar<'\"'>()));
|
||||
// Parses a C-style double-quoted string.
|
||||
|
||||
constexpr auto singleQuotedString = charsToString(sequence(
|
||||
exactChar<'\''>(),
|
||||
many(oneOf(anyOfChars("\\\n\'").invert(), escapeSequence)),
|
||||
exactChar<'\''>()));
|
||||
// Parses a C-style single-quoted string.
|
||||
|
||||
constexpr auto doubleQuotedHexBinary = sequence(
|
||||
exactChar<'0'>(), exactChar<'x'>(), exactChar<'\"'>(),
|
||||
oneOrMore(transform(sequence(discardWhitespace, hexDigit, hexDigit), _::ParseHexByte())),
|
||||
discardWhitespace,
|
||||
exactChar<'\"'>());
|
||||
// Parses a double-quoted hex binary literal. Returns Array<byte>.
|
||||
|
||||
} // namespace parse
|
||||
} // namespace kj
|
||||
|
||||
#endif // KJ_PARSE_CHAR_H_
|
||||
824
phonelibs/capnp-cpp/mac/include/kj/parse/common.h
Normal file
824
phonelibs/capnp-cpp/mac/include/kj/parse/common.h
Normal file
@@ -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_
|
||||
Reference in New Issue
Block a user