#pragma once #include #include #include #include #include #include #include "AiBehaviorGrammar.hpp" #include "EffectGrammar.hpp" #include "ModifierGrammar.hpp" #include "SimpleGrammar.hpp" #include "TriggerGrammar.hpp" // Event Grammar Definitions // namespace ovdl::v2script::grammar { ////////////////// // Macros ////////////////// // Produces _rule and _p #define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ struct KW_NAME##_rule { \ static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_); \ static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ static constexpr auto value = lexy::noop; \ }; \ static constexpr auto KW_NAME##_p = lexy::dsl::p // Produces _rule and _p and _rule::flag and _rule::too_many_error #define OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(KW_NAME) \ struct KW_NAME##_rule { \ static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_); \ static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ static constexpr auto value = lexy::noop; \ static constexpr auto flag = lexy::dsl::context_flag; \ struct too_many_error { \ static constexpr auto name = "expected left side " #KW_NAME " to be found once"; \ }; \ }; \ static constexpr auto KW_NAME##_p = lexy::dsl::p >> (lexy::dsl::must(KW_NAME##_rule::flag.is_reset()).error + KW_NAME##_rule::flag.set()) ////////////////// // Macros ////////////////// static constexpr auto event_symbols = lexy::symbol_table // .map(ast::EventNode::Type::Country) .map(ast::EventNode::Type::Province); struct EventMtthStatement { OVDL_GRAMMAR_KEYWORD_DEFINE(months); struct MonthValue { static constexpr auto rule = lexy::dsl::inline_; static constexpr auto value = lexy::as_string | lexy::new_; }; static constexpr auto rule = lexy::dsl::list( (months_p >> lexy::dsl::p) | lexy::dsl::p); static constexpr auto value = lexy::as_list> >> lexy::callback( [](auto&& list) { return ast::make_node_ptr(LEXY_MOV(list)); }); }; template struct _StringStatement { static constexpr auto rule = Production >> (lexy::dsl::p | lexy::dsl::p); static constexpr auto value = lexy::callback( [](auto&& value) { auto result = ast::make_node_ptr(std::move(static_cast(value)->_name)); delete value; return result; }); }; template static constexpr auto StringStatement = lexy::dsl::p<_StringStatement>; struct EventOptionList { OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(name); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(ai_chance); static constexpr auto rule = [] { constexpr auto create_flags = name_rule::flag.create() + ai_chance_rule::flag.create(); constexpr auto name_statement = StringStatement; constexpr auto ai_chance_statement = ai_chance_p >> lexy::dsl::curly_bracketed(lexy::dsl::p); return create_flags + lexy::dsl::list(name_statement | ai_chance_statement | lexy::dsl::p); }(); static constexpr auto value = lexy::as_list> >> lexy::callback( [](auto&& list) { return ast::make_node_ptr(LEXY_MOV(list)); }); }; struct EventStatement { OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(id); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(title); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(desc); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(picture); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(is_triggered_only); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(fire_only_once); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(immediate); OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(mean_time_to_happen); OVDL_GRAMMAR_KEYWORD_DEFINE(trigger); OVDL_GRAMMAR_KEYWORD_DEFINE(option); static constexpr auto rule = [] { constexpr auto symbol_value = lexy::dsl::symbol(lexy::dsl::inline_); constexpr auto create_flags = id_rule::flag.create() + title_rule::flag.create() + desc_rule::flag.create() + picture_rule::flag.create() + is_triggered_only_rule::flag.create() + fire_only_once_rule::flag.create() + immediate_rule::flag.create() + mean_time_to_happen_rule::flag.create(); constexpr auto id_statement = StringStatement; constexpr auto title_statement = StringStatement; constexpr auto desc_statement = StringStatement; constexpr auto picture_statement = StringStatement; constexpr auto is_triggered_only_statement = StringStatement; constexpr auto fire_only_once_statement = StringStatement; constexpr auto immediate_statement = immediate_p >> lexy::dsl::p; constexpr auto mean_time_to_happen_statement = mean_time_to_happen_p >> lexy::dsl::curly_bracketed(lexy::dsl::p); constexpr auto trigger_statement = trigger_p >> lexy::dsl::curly_bracketed.opt(lexy::dsl::p); constexpr auto option_statement = option_p >> lexy::dsl::curly_bracketed(lexy::dsl::p); return symbol_value >> (create_flags + lexy::dsl::equal_sign + lexy::dsl::curly_bracketed.opt_list( id_statement | title_statement | desc_statement | picture_statement | is_triggered_only_statement | fire_only_once_statement | immediate_statement | mean_time_to_happen_statement | trigger_statement | option_statement | lexy::dsl::p)); }(); static constexpr auto value = lexy::as_list> >> lexy::callback( [](auto& type, auto&& list) { return ast::make_node_ptr(type, LEXY_MOV(list)); }, [](auto& type, lexy::nullopt = {}) { return ast::make_node_ptr(type); }); }; struct EventFile { // Allow arbitrary spaces between individual tokens. static constexpr auto whitespace = whitespace_specifier | comment_specifier; static constexpr auto rule = lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p | lexy::dsl::p); static constexpr auto value = lexy::as_list> >> lexy::new_; }; #undef OVDL_GRAMMAR_KEYWORD_DEFINE #undef OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE #undef OVDL_GRAMMAR_KEYWORD_STATEMENT #undef OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT }