Skip to content

Customize the PEGTL parse_tree implementation #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ endfunction()

find_package(Threads MODULE REQUIRED)

find_package(pegtl 3.2.0 QUIET CONFIG)
find_package(pegtl 3.2.6 QUIET CONFIG)
if(NOT pegtl_FOUND)
# If a compatible version of PEGTL is not already installed, build and install it from the submodule directory.
set(PEGTL_BUILD_TESTS OFF CACHE BOOL "Disable PEGTL tests")
Expand Down
2 changes: 1 addition & 1 deletion PEGTL
Submodule PEGTL updated 391 files
2 changes: 1 addition & 1 deletion cmake/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.4.0
4.4.1
96 changes: 18 additions & 78 deletions include/graphqlservice/internal/SyntaxTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,10 @@ namespace graphql::peg {
using namespace tao::graphqlpeg;
namespace peginternal = tao::graphqlpeg::internal;

class [[nodiscard]] ast_node
class [[nodiscard]] ast_node : public parse_tree::basic_node<ast_node>
{
public:
// Must be default constructible
ast_node() = default;

// Nodes are always owned/handled by a std::unique_ptr
// and never copied or assigned...
ast_node(const ast_node&) = delete;
ast_node(ast_node&&) = delete;
ast_node& operator=(const ast_node&) = delete;
ast_node& operator=(ast_node&&) = delete;

// Must be destructible
~ast_node() = default;

[[nodiscard]] GRAPHQLPEG_EXPORT bool is_root() const noexcept;
[[nodiscard]] GRAPHQLPEG_EXPORT position begin() const noexcept;
[[nodiscard]] GRAPHQLPEG_EXPORT std::string_view string_view() const noexcept;
[[nodiscard]] GRAPHQLPEG_EXPORT std::string string() const noexcept;
[[nodiscard]] GRAPHQLPEG_EXPORT bool has_content() const noexcept;
GRAPHQLPEG_EXPORT void remove_content() noexcept;

GRAPHQLPEG_EXPORT void unescaped_view(std::string_view unescaped) noexcept;
[[nodiscard]] GRAPHQLPEG_EXPORT std::string_view unescaped_view() const;
Expand All @@ -55,71 +38,31 @@ class [[nodiscard]] ast_node

// The pointer comparison doesn't work with shared libraries where the parse tree is
// constructed in one module and consumed in another. So to optimize this comparison, check
// the size first, then the hash (cached in a static local variable per specialization of
// type_hash<U>()), then the pointer comparison with a full string compare as fallback.
return _type.size() == u.size() && _type_hash == type_hash<U>()
&& (_type.data() == u.data() || _type == u);
// the size first, then the pointer (cached in a static local variable per specialization of
// type_name<U>()), then the hash (cached in a static local variable per specialization of
// type_hash<U>()) and a full string compare as fallback.
return _type_name.size() == u.size()
&& (_type_name.data() == u.data() || (_type_hash == type_hash<U>() && _type_name == u));
}

template <typename... States>
void remove_content(States&&...) noexcept
{
_content = {};
_unescaped.reset();
}
using basic_node_t = parse_tree::basic_node<ast_node>;

// All non-root nodes receive a call to start() when
// a match is attempted for Rule in a parsing run...
template <typename Rule, typename ParseInput, typename... States>
void start(const ParseInput& in, States&&...)
template <typename Rule, typename ParseInput>
void success(const ParseInput& in)
{
_begin = in.iterator();
}

// ...and later a call to success() when the match succeeded...
template <typename Rule, typename ParseInput, typename... States>
void success(const ParseInput& in, States&&...)
{
const char* end = in.iterator().data;

_type = type_name<Rule>();
basic_node_t::template success<Rule>(in);
_type_name = type_name<Rule>();
_type_hash = type_hash<Rule>();
_source = in.source();
_content = { _begin.data, static_cast<size_t>(end - _begin.data) };
_unescaped.reset();
}

// ...or to failure() when a (local) failure was encountered.
template <typename Rule, typename ParseInput, typename... States>
void failure(const ParseInput&, States&&...)
{
}

// if parsing of the rule failed with an exception, this method is called
template <typename Rule, typename ParseInput, typename... States>
void unwind(const ParseInput&, States&&...) noexcept
{
}

// After a call to success(), and the (optional) call to the selector's
// transform() did not discard a node, it is passed to its parent node
// with a call to the parent node's emplace_back() member function.
template <typename... States>
void emplace_back(std::unique_ptr<ast_node> child, States&&...)
{
children.emplace_back(std::move(child));
}

using children_t = std::vector<std::unique_ptr<ast_node>>;

children_t children;

private:
template <typename U>
[[nodiscard]] static std::string_view type_name() noexcept
{
// This is cached in a static local variable per-specialization, but each module may have
// its own instance of the specialization and the local variable.
// its own instance of the specialization and the local variable. Within a single module,
// the pointer returned from std::string_view::data() should always be equal, which speeds
// up the string comparison in is_type.
static const std::string_view name { tao::graphqlpeg::demangle<U>() };

return name;
Expand All @@ -130,20 +73,17 @@ class [[nodiscard]] ast_node
{
// This is cached in a static local variable per-specialization, but each module may have
// its own instance of the specialization and the local variable.
static const size_t hash = std::hash<std::string_view>()(type_name<U>());
static const size_t hash = std::hash<std::string_view> {}(type_name<U>());

return hash;
}

std::string_view _source;
peginternal::iterator _begin;
std::string_view _type;
std::string_view _type_name;
size_t _type_hash = 0;
std::string_view _content;

using unescaped_t = std::variant<std::string_view, std::string>;

std::unique_ptr<unescaped_t> _unescaped;
mutable std::unique_ptr<unescaped_t> _unescaped;
};

template <class ParseInput>
Expand Down
4 changes: 2 additions & 2 deletions include/graphqlservice/internal/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

namespace graphql::internal {

constexpr std::string_view FullVersion { "4.4.0" };
constexpr std::string_view FullVersion { "4.4.1" };

constexpr size_t MajorVersion = 4;
constexpr size_t MinorVersion = 4;
constexpr size_t PatchVersion = 0;
constexpr size_t PatchVersion = 1;

} // namespace graphql::internal

Expand Down
4 changes: 2 additions & 2 deletions res/ClientGen.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/SchemaGen.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlclient_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqljson_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlpeg_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlresponse_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlservice_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"
#define GRAPHQL_RC_VERSION 4,4,1,0
#define GRAPHQL_RC_VERSION_STR "4.4.1"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
Loading