diff options
author | Hop311 <Hop3114@gmail.com> | 2023-09-15 21:46:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-15 21:46:26 +0200 |
commit | 8f71abc25ec993ce7e85f5342a52fb456bdba26f (patch) | |
tree | e9a6f4e6a7b3d8df0744747adf525462924425f4 /src/openvic-dataloader/v2script | |
parent | 2564d91f23a0b2a332d0d72023caa4091a56d1f1 (diff) | |
parent | 338bb84a5f5f883fb50fbe4f64398ab40dad74fe (diff) |
Merge pull request #15 from OpenVicProject/fix/escaping
Add ParseOptions
Diffstat (limited to 'src/openvic-dataloader/v2script')
-rw-r--r-- | src/openvic-dataloader/v2script/DecisionGrammar.hpp | 42 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/EffectGrammar.hpp | 4 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/EventGrammar.hpp | 42 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/ModifierGrammar.hpp | 6 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/Parser.cpp | 2 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/SimpleGrammar.hpp | 75 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/TriggerGrammar.hpp | 4 |
7 files changed, 99 insertions, 76 deletions
diff --git a/src/openvic-dataloader/v2script/DecisionGrammar.hpp b/src/openvic-dataloader/v2script/DecisionGrammar.hpp index 93ba0f5..a1c1e3e 100644 --- a/src/openvic-dataloader/v2script/DecisionGrammar.hpp +++ b/src/openvic-dataloader/v2script/DecisionGrammar.hpp @@ -23,25 +23,25 @@ namespace ovdl::v2script::grammar { // Macros ////////////////// // Produces <KW_NAME>_rule and <KW_NAME>_p -#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ - struct KW_NAME##_rule { \ - static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>); \ - static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ - static constexpr auto value = lexy::noop; \ - }; \ +#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ + struct KW_NAME##_rule { \ + static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier<StringEscapeOption>>); \ + static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ + static constexpr auto value = lexy::noop; \ + }; \ static constexpr auto KW_NAME##_p = lexy::dsl::p<KW_NAME##_rule> // Produces <KW_NAME>_rule and <KW_NAME>_p and <KW_NAME>_rule::flag and <KW_NAME>_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_<Identifier>); \ - static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ - static constexpr auto value = lexy::noop; \ - static constexpr auto flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ - struct too_many_error { \ - static constexpr auto name = "expected left side " #KW_NAME " to be found once"; \ - }; \ - }; \ +#define OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(KW_NAME) \ + struct KW_NAME##_rule { \ + static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier<StringEscapeOption>>); \ + static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ + static constexpr auto value = lexy::noop; \ + static constexpr auto flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ + 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<KW_NAME##_rule> >> (lexy::dsl::must(KW_NAME##_rule::flag.is_reset()).error<KW_NAME##_rule::too_many_error> + KW_NAME##_rule::flag.set()) ////////////////// // Macros @@ -49,7 +49,7 @@ namespace ovdl::v2script::grammar { struct DecisionStatement { template<auto Production, typename AstNode> struct _StringStatement { - static constexpr auto rule = Production >> (lexy::dsl::p<StringExpression> | lexy::dsl::p<Identifier>); + static constexpr auto rule = Production >> (lexy::dsl::p<StringExpression<StringEscapeOption>> | lexy::dsl::p<Identifier<StringEscapeOption>>); static constexpr auto value = lexy::forward<ast::NodePtr>; }; template<auto Production, typename AstNode> @@ -72,14 +72,14 @@ namespace ovdl::v2script::grammar { constexpr auto effect_statement = effect_p >> lexy::dsl::p<TriggerBlock>; constexpr auto ai_will_do_statement = ai_will_do_p >> lexy::dsl::p<AiBehaviorBlock>; - return lexy::dsl::p<Identifier> >> + return lexy::dsl::p<Identifier<StringEscapeOption>> >> (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>)); + lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>)); }(); static constexpr auto value = @@ -95,7 +95,7 @@ namespace ovdl::v2script::grammar { struct DecisionList { static constexpr auto rule = - LEXY_KEYWORD("political_decisions", lexy::dsl::inline_<Identifier>) >> + LEXY_KEYWORD("political_decisions", lexy::dsl::inline_<Identifier<StringEscapeOption>>) >> (lexy::dsl::equal_sign + lexy::dsl::curly_bracketed.opt_list(lexy::dsl::p<DecisionStatement>)); static constexpr auto value = @@ -116,7 +116,7 @@ namespace ovdl::v2script::grammar { static constexpr auto rule = lexy::dsl::terminator(lexy::dsl::eof).list( // lexy::dsl::p<DecisionList> | // - lexy::dsl::p<SimpleAssignmentStatement>); + lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; }; diff --git a/src/openvic-dataloader/v2script/EffectGrammar.hpp b/src/openvic-dataloader/v2script/EffectGrammar.hpp index 9f164b2..1b85382 100644 --- a/src/openvic-dataloader/v2script/EffectGrammar.hpp +++ b/src/openvic-dataloader/v2script/EffectGrammar.hpp @@ -9,7 +9,7 @@ namespace ovdl::v2script::grammar { struct EffectStatement { - static constexpr auto rule = lexy::dsl::inline_<SimpleAssignmentStatement>; + static constexpr auto rule = lexy::dsl::inline_<SimpleAssignmentStatement<StringEscapeOption>>; static constexpr auto value = lexy::callback<ast::NodePtr>( [](auto name, auto&& initalizer) { @@ -18,7 +18,7 @@ namespace ovdl::v2script::grammar { }; struct EffectList { - static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<SimpleAssignmentStatement>); + static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> diff --git a/src/openvic-dataloader/v2script/EventGrammar.hpp b/src/openvic-dataloader/v2script/EventGrammar.hpp index 93a52bf..e6e4c02 100644 --- a/src/openvic-dataloader/v2script/EventGrammar.hpp +++ b/src/openvic-dataloader/v2script/EventGrammar.hpp @@ -21,25 +21,25 @@ namespace ovdl::v2script::grammar { // Macros ////////////////// // Produces <KW_NAME>_rule and <KW_NAME>_p -#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ - struct KW_NAME##_rule { \ - static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier>); \ - static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ - static constexpr auto value = lexy::noop; \ - }; \ +#define OVDL_GRAMMAR_KEYWORD_DEFINE(KW_NAME) \ + struct KW_NAME##_rule { \ + static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier<StringEscapeOption>>); \ + static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ + static constexpr auto value = lexy::noop; \ + }; \ static constexpr auto KW_NAME##_p = lexy::dsl::p<KW_NAME##_rule> // Produces <KW_NAME>_rule and <KW_NAME>_p and <KW_NAME>_rule::flag and <KW_NAME>_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_<Identifier>); \ - static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ - static constexpr auto value = lexy::noop; \ - static constexpr auto flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ - struct too_many_error { \ - static constexpr auto name = "expected left side " #KW_NAME " to be found once"; \ - }; \ - }; \ +#define OVDL_GRAMMAR_KEYWORD_FLAG_DEFINE(KW_NAME) \ + struct KW_NAME##_rule { \ + static constexpr auto keyword = LEXY_KEYWORD(#KW_NAME, lexy::dsl::inline_<Identifier<StringEscapeOption>>); \ + static constexpr auto rule = keyword >> lexy::dsl::equal_sign; \ + static constexpr auto value = lexy::noop; \ + static constexpr auto flag = lexy::dsl::context_flag<struct KW_NAME##_context>; \ + 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<KW_NAME##_rule> >> (lexy::dsl::must(KW_NAME##_rule::flag.is_reset()).error<KW_NAME##_rule::too_many_error> + KW_NAME##_rule::flag.set()) ////////////////// // Macros @@ -52,7 +52,7 @@ namespace ovdl::v2script::grammar { OVDL_GRAMMAR_KEYWORD_DEFINE(months); struct MonthValue { - static constexpr auto rule = lexy::dsl::inline_<Identifier>; + static constexpr auto rule = lexy::dsl::inline_<Identifier<StringEscapeOption>>; static constexpr auto value = lexy::as_string<std::string> | lexy::new_<ast::MonthNode, ast::NodePtr>; }; @@ -70,7 +70,7 @@ namespace ovdl::v2script::grammar { template<auto Production, typename AstNode> struct _StringStatement { - static constexpr auto rule = Production >> (lexy::dsl::p<StringExpression> | lexy::dsl::p<Identifier>); + static constexpr auto rule = Production >> (lexy::dsl::p<StringExpression<StringEscapeOption>> | lexy::dsl::p<Identifier<StringEscapeOption>>); static constexpr auto value = lexy::callback<ast::NodePtr>( [](auto&& value) { @@ -116,7 +116,7 @@ namespace ovdl::v2script::grammar { OVDL_GRAMMAR_KEYWORD_DEFINE(option); static constexpr auto rule = [] { - constexpr auto symbol_value = lexy::dsl::symbol<event_symbols>(lexy::dsl::inline_<Identifier>); + constexpr auto symbol_value = lexy::dsl::symbol<event_symbols>(lexy::dsl::inline_<Identifier<StringEscapeOption>>); constexpr auto create_flags = id_rule::flag.create() + @@ -153,7 +153,7 @@ namespace ovdl::v2script::grammar { mean_time_to_happen_statement | trigger_statement | option_statement | - lexy::dsl::p<SimpleAssignmentStatement>)); + lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>)); }(); static constexpr auto value = @@ -171,7 +171,7 @@ namespace ovdl::v2script::grammar { // 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 rule = lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p<EventStatement> | lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; }; diff --git a/src/openvic-dataloader/v2script/ModifierGrammar.hpp b/src/openvic-dataloader/v2script/ModifierGrammar.hpp index 632cfd5..96e928c 100644 --- a/src/openvic-dataloader/v2script/ModifierGrammar.hpp +++ b/src/openvic-dataloader/v2script/ModifierGrammar.hpp @@ -8,11 +8,11 @@ #include "TriggerGrammar.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>); + constexpr auto modifier_keyword = LEXY_KEYWORD("modifier", lexy::dsl::inline_<Identifier<StringEscapeOption>>); + constexpr auto factor_keyword = LEXY_KEYWORD("factor", lexy::dsl::inline_<Identifier<StringEscapeOption>>); struct FactorStatement { - static constexpr auto rule = factor_keyword >> lexy::dsl::equal_sign + lexy::dsl::inline_<Identifier>; + static constexpr auto rule = factor_keyword >> lexy::dsl::equal_sign + lexy::dsl::inline_<Identifier<StringEscapeOption>>; static constexpr auto value = lexy::as_string<std::string> | lexy::new_<ast::FactorNode, ast::NodePtr>; }; diff --git a/src/openvic-dataloader/v2script/Parser.cpp b/src/openvic-dataloader/v2script/Parser.cpp index 0ff7612..9e74e32 100644 --- a/src/openvic-dataloader/v2script/Parser.cpp +++ b/src/openvic-dataloader/v2script/Parser.cpp @@ -175,7 +175,7 @@ bool Parser::simple_parse() { _warnings.push_back(warnings::make_utf8_warning(_file_path)); } - auto errors = _buffer_handler->parse<grammar::File>(ovdl::detail::ReporError.path(_file_path).to(detail::OStreamOutputIterator { _error_stream })); + auto errors = _buffer_handler->parse<grammar::File<grammar::NoStringEscapeOption>>(ovdl::detail::ReporError.path(_file_path).to(detail::OStreamOutputIterator { _error_stream })); if (errors) { _errors.reserve(errors->size()); for (auto& err : errors.value()) { diff --git a/src/openvic-dataloader/v2script/SimpleGrammar.hpp b/src/openvic-dataloader/v2script/SimpleGrammar.hpp index d478bdf..2679598 100644 --- a/src/openvic-dataloader/v2script/SimpleGrammar.hpp +++ b/src/openvic-dataloader/v2script/SimpleGrammar.hpp @@ -22,7 +22,18 @@ * DAT-643 */ namespace ovdl::v2script::grammar { + struct ParseOptions { + /// @brief Makes string parsing avoid string escapes + bool NoStringEscape; + }; + + static constexpr ParseOptions NoStringEscapeOption = ParseOptions { true }; + static constexpr ParseOptions StringEscapeOption = ParseOptions { false }; + + template<ParseOptions Options> struct StatementListBlock; + template<ParseOptions Options> + struct AssignmentStatement; /* REQUIREMENTS: DAT-630 */ static constexpr auto whitespace_specifier = lexy::dsl::ascii::blank / lexy::dsl::ascii::newline; @@ -45,6 +56,18 @@ namespace ovdl::v2script::grammar { static constexpr auto data_char_class = LEXY_CHAR_CLASS("DataSpecifier", data_specifier); + static constexpr auto escaped_symbols = lexy::symbol_table<char> // + .map<'"'>('"') + .map<'\''>('\'') + .map<'\\'>('\\') + .map<'/'>('/') + .map<'b'>('\b') + .map<'f'>('\f') + .map<'n'>('\n') + .map<'r'>('\r') + .map<'t'>('\t'); + + template<ParseOptions Options> struct Identifier { static constexpr auto rule = lexy::dsl::identifier(data_char_class); static constexpr auto value = lexy::callback<ast::NodePtr>( @@ -58,27 +81,22 @@ namespace ovdl::v2script::grammar { * DAT-633 * DAT-634 */ + template<ParseOptions Options> struct StringExpression { - static constexpr auto escaped_symbols = lexy::symbol_table<char> // - .map<'"'>('"') - .map<'\''>('\'') - .map<'\\'>('\\') - .map<'/'>('/') - .map<'b'>('\b') - .map<'f'>('\f') - .map<'n'>('\n') - .map<'r'>('\r') - .map<'t'>('\t'); static constexpr auto rule = [] { // Arbitrary code points that aren't control characters. auto c = ovdl::detail::lexydsl::make_range<0x20, 0xFF>() - lexy::dsl::ascii::control; - // Escape sequences start with a backlash. - // They either map one of the symbols, - // or a Unicode code point of the form uXXXX. - auto escape = lexy::dsl::backslash_escape // - .symbol<escaped_symbols>(); - return lexy::dsl::delimited(lexy::dsl::position(lexy::dsl::lit_b<'"'>))(c, escape); + if constexpr (Options.NoStringEscape) { + return lexy::dsl::delimited(lexy::dsl::position(lexy::dsl::lit_b<'"'>))(c); + } else { + // Escape sequences start with a backlash. + // They either map one of the symbols, + // or a Unicode code point of the form uXXXX. + auto escape = lexy::dsl::backslash_escape // + .symbol<escaped_symbols>(); + return lexy::dsl::delimited(lexy::dsl::position(lexy::dsl::lit_b<'"'>))(c, escape); + } }(); static constexpr auto value = @@ -90,16 +108,18 @@ namespace ovdl::v2script::grammar { }; /* REQUIREMENTS: DAT-638 */ + template<ParseOptions Options> struct ValueExpression { - static constexpr auto rule = lexy::dsl::p<Identifier> | lexy::dsl::p<StringExpression>; + static constexpr auto rule = lexy::dsl::p<Identifier<Options>> | lexy::dsl::p<StringExpression<Options>>; static constexpr auto value = lexy::forward<ast::NodePtr>; }; + template<ParseOptions Options> struct SimpleAssignmentStatement { static constexpr auto rule = - lexy::dsl::position(lexy::dsl::p<Identifier>) >> - lexy::dsl::equal_sign + - (lexy::dsl::p<ValueExpression> | lexy::dsl::recurse_branch<StatementListBlock>); + lexy::dsl::position(lexy::dsl::p<Identifier<Options>>) >> + (lexy::dsl::equal_sign + + (lexy::dsl::p<ValueExpression<Options>> | lexy::dsl::recurse_branch<StatementListBlock<Options>>)); static constexpr auto value = lexy::callback<ast::NodePtr>( [](const char* pos, auto name, auto&& initalizer) { @@ -108,13 +128,14 @@ namespace ovdl::v2script::grammar { }; /* REQUIREMENTS: DAT-639 */ + template<ParseOptions Options> struct AssignmentStatement { static constexpr auto rule = - lexy::dsl::position(lexy::dsl::p<Identifier>) >> + lexy::dsl::position(lexy::dsl::p<Identifier<Options>>) >> (lexy::dsl::equal_sign >> - (lexy::dsl::p<ValueExpression> | lexy::dsl::recurse_branch<StatementListBlock>) | + (lexy::dsl::p<ValueExpression<Options>> | lexy::dsl::recurse_branch<StatementListBlock<Options>>) | lexy::dsl::else_ >> lexy::dsl::return_) | - lexy::dsl::p<StringExpression>; + lexy::dsl::p<StringExpression<Options>>; static constexpr auto value = lexy::callback<ast::NodePtr>( [](const char* pos, auto name, lexy::nullopt = {}) { @@ -129,11 +150,12 @@ namespace ovdl::v2script::grammar { }; /* REQUIREMENTS: DAT-640 */ + template<ParseOptions Options> struct StatementListBlock { static constexpr auto rule = lexy::dsl::position(lexy::dsl::curly_bracketed.open()) >> - lexy::dsl::opt(lexy::dsl::list(lexy::dsl::p<AssignmentStatement>)) + - lexy::dsl::opt(lexy::dsl::semicolon) >> + (lexy::dsl::opt(lexy::dsl::list(lexy::dsl::recurse_branch<AssignmentStatement<Options>>)) + + lexy::dsl::opt(lexy::dsl::semicolon)) >> lexy::dsl::position(lexy::dsl::curly_bracketed.close()); static constexpr auto value = @@ -156,11 +178,12 @@ namespace ovdl::v2script::grammar { }); }; + template<ParseOptions Options> struct File { // Allow arbitrary spaces between individual tokens. static constexpr auto whitespace = whitespace_specifier | comment_specifier; - static constexpr auto rule = lexy::dsl::position + lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p<AssignmentStatement>); + static constexpr auto rule = lexy::dsl::position + lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p<AssignmentStatement<Options>>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; }; diff --git a/src/openvic-dataloader/v2script/TriggerGrammar.hpp b/src/openvic-dataloader/v2script/TriggerGrammar.hpp index 6d964db..3849b12 100644 --- a/src/openvic-dataloader/v2script/TriggerGrammar.hpp +++ b/src/openvic-dataloader/v2script/TriggerGrammar.hpp @@ -9,7 +9,7 @@ namespace ovdl::v2script::grammar { struct TriggerStatement { - static constexpr auto rule = lexy::dsl::inline_<SimpleAssignmentStatement>; + static constexpr auto rule = lexy::dsl::inline_<SimpleAssignmentStatement<StringEscapeOption>>; static constexpr auto value = lexy::callback<ast::NodePtr>( [](auto name, auto&& initalizer) { @@ -18,7 +18,7 @@ namespace ovdl::v2script::grammar { }; struct TriggerList { - static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<SimpleAssignmentStatement>); + static constexpr auto rule = lexy::dsl::list(lexy::dsl::p<SimpleAssignmentStatement<StringEscapeOption>>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> |