diff options
author | Spartan322 <Megacake1234@gmail.com> | 2023-08-20 09:58:07 +0200 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2023-08-20 09:58:07 +0200 |
commit | b1bc7d520f09430c8d2372c6541ce23ec8099e13 (patch) | |
tree | a28708ccff8332e0233e6f578d988c68e0d589c4 | |
parent | 8ebcba11d103ebe8ab259b311e874e1bac05dfd3 (diff) |
Add the rough draft grammar for events and decisions
-rw-r--r-- | include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp | 27 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/AiBehaviorGrammar.hpp | 22 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/DecisionGrammar.hpp | 76 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/EffectGrammar.hpp | 14 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/EventGrammar.hpp | 129 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/SimpleGrammar.hpp | 14 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/TriggerGrammar.hpp | 14 |
7 files changed, 296 insertions, 0 deletions
diff --git a/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp index 80485b7..5faeb80 100644 --- a/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp +++ b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp @@ -167,6 +167,33 @@ namespace ovdl::v2script::ast { } }) }; + + struct EventNode final : public Node { + enum class Type { + Country, + Province + } _type; + std::vector<NodeUPtr> _statements; + explicit EventNode(Type type, std::vector<NodePtr> statements) + : _type(type), + _statements(make_node_ptr_vector(statements)) { + } + + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + + OVDL_PRINT_FUNC_DEF({ + switch (_type) { + case Type::Country: stream << "country_event"; break; + case Type::Province: stream << "province_event"; break; + } + stream << " = {"; + for (auto& statement : _statements) { + statement->print(stream); + } + stream << "}"; + }) + }; } #undef OVDL_PRINT_FUNC_DECL diff --git a/src/openvic-dataloader/v2script/AiBehaviorGrammar.hpp b/src/openvic-dataloader/v2script/AiBehaviorGrammar.hpp new file mode 100644 index 0000000..f3e1994 --- /dev/null +++ b/src/openvic-dataloader/v2script/AiBehaviorGrammar.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SimpleGrammar.hpp" +#include "TriggerGrammar.hpp" +#include <lexy/dsl.hpp> + +namespace ovdl::v2script::grammar { + constexpr auto modifier_keyword = LEXY_KEYWORD("modifier", lexy::dsl::inline_<Identifier>); + constexpr auto factor_keyword = LEXY_KEYWORD("factor", lexy::dsl::inline_<Identifier>); + + struct AiModifierStatement { + static constexpr auto rule = + modifier_keyword >> + lexy::dsl::curly_bracketed.list( + (factor_keyword >> lexy::dsl::p<Identifier>) | + lexy::dsl::p<TriggerStatement>); + }; + + struct AiBehaviorList { + static constexpr auto rule = lexy::dsl::list((factor_keyword >> lexy::dsl::p<Identifier>) | lexy::dsl::p<AiModifierStatement>); + }; +}
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/DecisionGrammar.hpp b/src/openvic-dataloader/v2script/DecisionGrammar.hpp index ebc9ad2..70e009f 100644 --- a/src/openvic-dataloader/v2script/DecisionGrammar.hpp +++ b/src/openvic-dataloader/v2script/DecisionGrammar.hpp @@ -4,11 +4,87 @@ #include <string> #include <vector> +#include "AiBehaviorGrammar.hpp" +#include "EffectGrammar.hpp" +#include "SimpleGrammar.hpp" +#include "TriggerGrammar.hpp" #include <lexy/callback.hpp> #include <lexy/dsl.hpp> #include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> // Decision Grammar Definitions // namespace ovdl::v2script::grammar { + ////////////////// + // Macros + ////////////////// +// Produces <KW_NAME>_keyword +#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ + static constexpr auto KW_NAME##_keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>) +// Produces <KW_NAME>_keyword and <KW_NAME>_flag and <KW_NAME>_too_many_error +#define OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(KW_NAME) \ + static constexpr auto KW_NAME##_keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>); \ + static constexpr auto KW_NAME##_flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ + struct KW_NAME##_too_many_error { \ + static constexpr auto name = "expected left side " #KW_NAME " to be found once"; \ + } + +// Produces <KW_NAME>_statement +#define OVDL_GRAMMAR_KEYWORD_STATEMENT(KW_NAME, ...) \ + constexpr auto KW_NAME##_statement = KW_NAME##_keyword >> (lexy::dsl::equal_sign + (__VA_ARGS__)) + +// Produces <KW_NAME>_statement +#define OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(KW_NAME, ...) \ + constexpr auto KW_NAME##_statement = KW_NAME##_keyword >> ((lexy::dsl::must(KW_NAME##_flag.is_reset()).error<KW_NAME##_too_many_error> + KW_NAME##_flag.set()) + lexy::dsl::equal_sign + (__VA_ARGS__)) + ////////////////// + // Macros + ////////////////// + + struct DecisionStatement { + OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(potential); + OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(allow); + OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(effect); + OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(ai_will_do); + + static constexpr auto rule = [] { + constexpr auto create_flags = + potential_flag.create() + + allow_flag.create() + + effect_flag.create() + + ai_will_do_flag.create(); + constexpr auto check_flag = [](auto flag) { return flag.is_reset() + flag.set(); }; + + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(potential, lexy::dsl::curly_bracketed.opt(lexy::dsl::p<TriggerList>)); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(allow, lexy::dsl::curly_bracketed.opt(lexy::dsl::p<TriggerList>)); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(effect, lexy::dsl::curly_bracketed(lexy::dsl::p<EffectList>)); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(ai_will_do, lexy::dsl::curly_bracketed(lexy::dsl::p<AiBehaviorList>)); + + return lexy::dsl::p<Identifier> >> + (create_flags + lexy::dsl::equal_sign + + lexy::dsl::curly_bracketed.list( + potential_statement | + allow_statement | + effect_statement | + ai_will_do_statement | + lexy::dsl::p<SimpleAssignmentStatement>)); + }(); + + static constexpr auto value = lexy::callback<ast::NodePtr>([](auto name, lexy::nullopt = {}) { return LEXY_MOV(name); }, [](auto name, auto&& initalizer) { return make_node_ptr<ast::AssignNode>(LEXY_MOV(name), LEXY_MOV(initalizer)); }); + }; + + struct DecisionFile { + // 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_KEYWORD("political_decisions", lexy::dsl::inline_<Identifier>) >> (lexy::dsl::equal_sign + lexy::dsl::curly_bracketed.opt_list(lexy::dsl::p<DecisionStatement>))) | // + lexy::dsl::p<SimpleAssignmentStatement>); + + static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; + }; + +#undef OVDL_GRAMMAR_KEYWORD_DEFINE +#undef OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE +#undef OVDL_GRAMMAR_KEYWORD_STATEMENT +#undef OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT }
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/EffectGrammar.hpp b/src/openvic-dataloader/v2script/EffectGrammar.hpp new file mode 100644 index 0000000..4ee19dd --- /dev/null +++ b/src/openvic-dataloader/v2script/EffectGrammar.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SimpleGrammar.hpp" +#include <lexy/dsl.hpp> + +namespace ovdl::v2script::grammar { + struct EffectStatement { + static constexpr auto rule = lexy::dsl::p<SimpleAssignmentStatement>; + }; + + struct EffectList { + static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<EffectStatement>); + }; +}
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/EventGrammar.hpp b/src/openvic-dataloader/v2script/EventGrammar.hpp index 7ab40d4..21dd66b 100644 --- a/src/openvic-dataloader/v2script/EventGrammar.hpp +++ b/src/openvic-dataloader/v2script/EventGrammar.hpp @@ -4,11 +4,140 @@ #include <string> #include <vector> +#include "AiBehaviorGrammar.hpp" +#include "EffectGrammar.hpp" +#include "SimpleGrammar.hpp" +#include "TriggerGrammar.hpp" #include <lexy/callback.hpp> #include <lexy/dsl.hpp> #include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> // Event Grammar Definitions // namespace ovdl::v2script::grammar { + ////////////////// + // Macros + ////////////////// +// Produces <KW_NAME>_keyword +#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ + static constexpr auto KW_NAME##_keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>) +// Produces <KW_NAME>_keyword and <KW_NAME>_flag and <KW_NAME>_too_many_error +#define OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(KW_NAME) \ + static constexpr auto KW_NAME##_keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>); \ + static constexpr auto KW_NAME##_flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ + struct KW_NAME##_too_many_error { \ + static constexpr auto name = "expected left side " #KW_NAME " to be found once"; \ + } + +// Produces <KW_NAME>_statement +#define OVDL_GRAMMAR_KEYWORD_STATEMENT(KW_NAME, ...) \ + constexpr auto KW_NAME##_statement = KW_NAME##_keyword >> (lexy::dsl::equal_sign + (__VA_ARGS__)) + +// Produces <KW_NAME>_statement +#define OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(KW_NAME, ...) \ + constexpr auto KW_NAME##_statement = KW_NAME##_keyword >> ((lexy::dsl::must(KW_NAME##_flag.is_reset()).error<KW_NAME##_too_many_error> + KW_NAME##_flag.set()) + lexy::dsl::equal_sign + (__VA_ARGS__)) + ////////////////// + // Macros + ////////////////// + static constexpr auto event_symbols = lexy::symbol_table<ast::EventNode::Type> // + .map<LEXY_SYMBOL("country_event")>(ast::EventNode::Type::Country) + .map<LEXY_SYMBOL("province_event")>(ast::EventNode::Type::Province); + + struct EventMeanTimeToHappenModifierStatement { + static constexpr auto rule = + modifier_keyword >> + lexy::dsl::curly_bracketed.list( + (factor_keyword >> lexy::dsl::p<Identifier>) | + lexy::dsl::p<TriggerStatement>); + }; + + struct EventMeanTimeToHappenStatement { + static constexpr auto months_keyword = LEXY_KEYWORD("months", lexy::dsl::inline_<Identifier>); + + static constexpr auto rule = lexy::dsl::list( + (months_keyword >> lexy::dsl::p<Identifier>) | + lexy::dsl::p<EventMeanTimeToHappenModifierStatement>); + }; + + struct EventOptionList { + OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(name); + + static constexpr auto rule = [] { + constexpr auto create_flags = name_flag.create(); + + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(name, lexy::dsl::p<StringExpression> | lexy::dsl::p<Identifier>); + + return create_flags + lexy::dsl::list(name_statement | lexy::dsl::p<EffectStatement>); + }(); + }; + + 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 create_flags = + id_flag.create() + + title_flag.create() + + desc_flag.create() + + picture_flag.create() + + is_triggered_only_flag.create() + + fire_only_once_flag.create() + + immediate_flag.create() + + mean_time_to_happen_flag.create(); + + constexpr auto string_value = lexy::dsl::p<StringExpression> | lexy::dsl::p<Identifier>; + + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(id, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(title, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(desc, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(picture, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(is_triggered_only, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(fire_only_once, string_value); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(immediate, lexy::dsl::curly_bracketed.opt(lexy::dsl::p<EffectList>)); + OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT(mean_time_to_happen, lexy::dsl::curly_bracketed(lexy::dsl::p<EventMeanTimeToHappenStatement>)); + + OVDL_GRAMMAR_KEYWORD_STATEMENT(trigger, lexy::dsl::curly_bracketed.opt(lexy::dsl::p<TriggerList>)); + OVDL_GRAMMAR_KEYWORD_STATEMENT(option, lexy::dsl::curly_bracketed(lexy::dsl::p<EventOptionList>)); + + return lexy::dsl::symbol<event_symbols>(lexy::dsl::inline_<Identifier>) >> + (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<SimpleAssignmentStatement>)); + }(); + + static constexpr auto value = lexy::callback<ast::NodePtr>([](auto name, lexy::nullopt = {}) { return LEXY_MOV(name); }, [](auto name, auto&& initalizer) { return make_node_ptr<ast::AssignNode>(LEXY_MOV(name), LEXY_MOV(initalizer)); }); + }; + + 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<EventStatement> | lexy::dsl::p<SimpleAssignmentStatement>); + + static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; + }; + +#undef OVDL_GRAMMAR_KEYWORD_DEFINE +#undef OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE +#undef OVDL_GRAMMAR_KEYWORD_STATEMENT +#undef OVDL_GRAMMAR_KEYWORD_FLAG_STATEMENT }
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/SimpleGrammar.hpp b/src/openvic-dataloader/v2script/SimpleGrammar.hpp index 48a80ce..6849fe2 100644 --- a/src/openvic-dataloader/v2script/SimpleGrammar.hpp +++ b/src/openvic-dataloader/v2script/SimpleGrammar.hpp @@ -1,3 +1,5 @@ +#pragma once + #include <memory> #include <string> #include <vector> @@ -57,6 +59,18 @@ namespace ovdl::v2script::grammar { static constexpr auto value = lexy::as_string<std::string> >> lexy::new_<ast::StringNode, ast::NodePtr>; }; + struct SimpleAssignmentStatement { + static constexpr auto rule = + lexy::dsl::p<Identifier> >> + lexy::dsl::equal_sign + + (lexy::dsl::p<Identifier> | lexy::dsl::p<StringExpression> | lexy::dsl::recurse_branch<StatementListBlock>); + + static constexpr auto value = lexy::callback<ast::NodePtr>( + [](auto name, auto&& initalizer) { + return make_node_ptr<ast::AssignNode>(LEXY_MOV(name), LEXY_MOV(initalizer)); + }); + }; + struct AssignmentStatement { static constexpr auto rule = lexy::dsl::p<Identifier> >> diff --git a/src/openvic-dataloader/v2script/TriggerGrammar.hpp b/src/openvic-dataloader/v2script/TriggerGrammar.hpp new file mode 100644 index 0000000..6f3436b --- /dev/null +++ b/src/openvic-dataloader/v2script/TriggerGrammar.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SimpleGrammar.hpp" +#include <lexy/dsl.hpp> + +namespace ovdl::v2script::grammar { + struct TriggerStatement { + static constexpr auto rule = lexy::dsl::p<SimpleAssignmentStatement>; + }; + + struct TriggerList { + static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<TriggerStatement>); + }; +}
\ No newline at end of file |