#pragma once #include #include #include #include #include #include #include #include #include "detail/StringLiteral.hpp" namespace ovdl::dsl { template constexpr auto callback(Callback... cb) { return lexy::bind(lexy::callback(cb...), lexy::parse_state, lexy::values); } template constexpr auto sink(Sink sink) { return lexy::bind_sink(sink, lexy::parse_state); } template constexpr auto collect(Callback callback) { return sink(lexy::collect(callback)); } template constexpr auto collect(Callback callback) { return sink(lexy::collect(callback)); } template constexpr auto construct = callback( [](StateType& state, ovdl::NodeLocation loc, auto&& arg) { if constexpr (std::is_same_v, lexy::nullopt>) return state.ast().template create(loc); else return state.ast().template create(loc, DRYAD_FWD(arg)); }, [](StateType& state, ovdl::NodeLocation loc, auto&&... args) { return state.ast().template create(loc, DRYAD_FWD(args)...); }); template constexpr auto construct_list = callback( [](StateType& state, const char* begin, ListType&& arg, const char* end) { return state.ast().template create(NodeLocation::make_from(begin, end), DRYAD_FWD(arg)); }, [](StateType& state, const char* begin, lexy::nullopt, const char* end) { return state.ast().template create(NodeLocation::make_from(begin, end)); }, [](StateType& state, const char* begin, const char* end) { return state.ast().template create(NodeLocation::make_from(begin, end)); }); template constexpr auto construct_list = callback( [](StateType& state, const char* begin, ListType&& arg, const char* end) { return state.ast().template create(NodeLocation::make_from(begin, end), DRYAD_FWD(arg)); }, [](StateType& state, const char* begin, lexy::nullopt, const char* end) { return state.ast().template create(NodeLocation::make_from(begin, end)); }); template consteval auto make_range() { if constexpr (LOW == HIGH) { return ::lexy::dsl::lit_c; } else if constexpr (LOW == (HIGH - 1)) { return ::lexy::dsl::lit_c / ::lexy::dsl::lit_c; } else { return ::lexy::dsl::lit_c / make_range(); } } template constexpr auto position_brackets = lexy::dsl::brackets(lexy::dsl::position(lexy::dsl::lit_c), lexy::dsl::position(lexy::dsl::lit_c)); constexpr auto round_bracketed = position_brackets<'(', ')'>; constexpr auto square_bracketed = position_brackets<'[', ']'>; constexpr auto curly_bracketed = position_brackets<'{', '}'>; constexpr auto angle_bracketed = position_brackets<'<', '>'>; template constexpr auto p = lexy::dsl::position(lexy::dsl::p); template static constexpr auto default_kw_value = dsl::callback( [](ParseType& state, NodeLocation loc) { return state.ast().template create(loc, state.ast().intern(Keyword.data(), Keyword.size())); }); template< IsParseState ParseType, typename Identifier, typename RuleValue, ovdl::detail::string_literal Keyword, auto Production, auto Value> struct keyword_rule { struct rule_t { static constexpr auto keyword = ovdl::dsl::keyword(lexy::dsl::inline_); static constexpr auto rule = lexy::dsl::position(keyword) >> lexy::dsl::equal_sign; static constexpr auto value = Value; }; static constexpr auto rule = dsl::p >> Production; static constexpr auto value = construct; }; template< IsParseState ParseType, typename Identifier, typename RuleValue, ovdl::detail::string_literal Keyword, auto Production, auto Value> struct fkeyword_rule : keyword_rule { using base_type = keyword_rule; struct context_t; struct rule_t : base_type::rule_t { static constexpr auto flag = lexy::dsl::context_flag; struct too_many_error { static constexpr auto name = "expected event " + Keyword + " to only be found once"; }; static constexpr auto must = lexy::dsl::must(rule_t::flag.is_reset()) . // See https://stackoverflow.com/questions/77144003/use-of-template-keyword-before-dependent-template-name // THANKS FOR NOTHING MICROSOFT, CAN'T EVEN GET THE STANDARD RIGHT #if !defined(_MSC_VER) || defined(__clang__) template #endif error; }; static constexpr auto make_flag = rule_t::flag.create(); static constexpr auto rule = dsl::p >> (rule_t::must >> rule_t::flag.set()) >> Production; static constexpr auto value = construct; }; template struct rule_helper { static constexpr auto flags = (Args::make_flag + ...); static constexpr auto p = (lexy::dsl::p | ...); }; }