// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #ifndef HAVE_IRCD_SPIRIT_H #define HAVE_IRCD_SPIRIT_H /// This file is not part of the IRCd standard include list (stdinc.h) because /// it involves extremely expensive boost headers for creating formal spirit /// grammars. Include this in a definition file which defines such grammars. /// /// Note that directly sharing elements of a grammar between two compilation /// units can be achieved with forward declarations in `ircd/grammar.h`. // ircd.h is included here so that it can be compiled into this header. Then // this becomes the single leading precompiled header. #include // Disables asserts in spirit headers even when we're NDEBUG due to // some false asserts around boolean character tests in spirit. #define BOOST_DISABLE_ASSERTS #pragma GCC visibility push(default) #include #include #pragma GCC visibility pop #pragma GCC visibility push(hidden) #include #include #include #include #include #include #include #include #include #include #include #pragma GCC visibility pop namespace ircd { namespace spirit __attribute__((visibility("default"))) { struct substring_view; template struct expectation_failure; extern thread_local char rulebuf[64]; // parse.cc }} namespace ircd __attribute__((visibility("default"))) { template bool parse(args&&...); } namespace ircd { namespace spirit __attribute__((visibility("hidden"))) { namespace spirit = boost::spirit; namespace ascii = spirit::ascii; namespace karma = spirit::karma; namespace qi = spirit::qi; namespace phx = boost::phoenix; using _val_type = phx::actor>; using _r0_type = phx::actor>; using _r1_type = phx::actor>; using _r2_type = phx::actor>; using _r3_type = phx::actor>; using spirit::unused_type; using spirit::auto_; using spirit::_pass; using spirit::_val; using qi::locals; using qi::_a; using qi::_a_type; using qi::_r1_type; using qi::raw; using qi::omit; using qi::matches; using qi::hold; using qi::eoi; using qi::eps; using qi::expect; using qi::attr; using qi::attr_cast; using qi::repeat; using qi::lit; using qi::char_; using qi::byte_; using qi::string; using qi::short_; using qi::ushort_; using qi::word; using qi::big_word; using qi::little_word; using qi::int_; using qi::uint_; using qi::dword; using qi::big_dword; using qi::little_dword; using qi::long_; using qi::ulong_; using qi::qword; using qi::big_qword; using qi::little_qword; using qi::float_; using qi::bin_float; using qi::big_bin_float; using qi::little_bin_float; using qi::double_; using qi::bin_double; using qi::big_bin_double; using qi::little_bin_double; using spirit::repository::qi::seek; using karma::lit; using karma::char_; using karma::long_; using karma::double_; using karma::bool_; using karma::eps; using karma::attr_cast; using karma::maxwidth; using karma::buffer; using karma::skip; template auto & attr_at(semantic_context&&); template auto & local_at(semantic_context&&); }} namespace ircd::spirit::local { using qi::_0; using qi::_1; using qi::_2; using qi::_3; } namespace ircd { namespace spirit __attribute__((visibility("default"))) { }} struct ircd::spirit::substring_view :ircd::string_view { using _iterator = boost::spirit::karma::detail::indirect_iterator; using _iterator_range = boost::iterator_range<_iterator>; using ircd::string_view::string_view; explicit substring_view(const _iterator_range &range) :ircd::string_view { std::addressof(*range.begin()), std::addressof(*range.end()) } {} }; template struct __attribute__((visibility("default"))) ircd::spirit::expectation_failure :parent_error { template expectation_failure(const qi::expectation_failure &e, const ssize_t &show_max = 64); template expectation_failure(const qi::expectation_failure &e, const it &start, const ssize_t &show_max = 64); }; template template ircd::spirit::expectation_failure::expectation_failure(const qi::expectation_failure &e, const ssize_t &show_max) :parent { "Expected %s. You input %zd invalid characters :%s", ircd::string(rulebuf, e.what_), std::distance(e.first, e.last), string_view{e.first, e.first + std::min(std::distance(e.first, e.last), show_max)} } {} template template ircd::spirit::expectation_failure::expectation_failure(const qi::expectation_failure &e, const it &start, const ssize_t &show_max) :parent { "Expected %s. You input %zd invalid characters somewhere between position %zd and %zd: %s", ircd::string(rulebuf, e.what_), std::distance(e.first, e.last), std::distance(start, e.first), std::distance(start, e.last), string_view{e.first, e.first + std::min(std::distance(e.first, e.last), show_max)} } {} template inline bool ircd::parse(args&&... a) try { return spirit::qi::parse(std::forward(a)...); } catch(const spirit::qi::expectation_failure &e) { throw spirit::expectation_failure(e); } template auto & ircd::spirit::local_at(semantic_context&& c) { return boost::fusion::at_c(c.locals); } template auto & ircd::spirit::attr_at(semantic_context&& c) { return boost::fusion::at_c(c.attributes); } #endif // HAVE_IRCD_SPIRIT_H