#pragma once #include #include #include #include #include #include #include "detail/LexyLitRange.hpp" // Grammar Definitions // namespace ovdl::v2script::grammar { struct StatementListBlock; static constexpr auto whitespace_specifier = lexy::dsl::ascii::blank / lexy::dsl::ascii::newline; static constexpr auto comment_specifier = LEXY_LIT("#") >> lexy::dsl::until(lexy::dsl::newline).or_eof(); static constexpr auto data_specifier = lexy::dsl::ascii::alpha_digit_underscore / LEXY_ASCII_ONE_OF("%&'") / lexy::dsl::lit_c<0x2B> / LEXY_ASCII_ONE_OF("-.") / lexy::dsl::ascii::digit / lexy::dsl::lit_c<0x3A> / lexy::dsl::lit_c<0x40> / lexy::dsl::ascii::upper / lexy::dsl::lit_c<0x5F> / lexy::dsl::ascii::lower / lexy::dsl::lit_b<0x8A> / lexy::dsl::lit_b<0x8C> / lexy::dsl::lit_b<0x8E> / lexy::dsl::lit_b<0x92> / lexy::dsl::lit_b<0x97> / lexy::dsl::lit_b<0x9A> / lexy::dsl::lit_b<0x9C> / lexy::dsl::lit_b<0x9E> / lexy::dsl::lit_b<0x9F> / lexy::dsl::lit_b<0xC0> / ovdl::detail::lexydsl::make_range<0xC0, 0xD6>() / ovdl::detail::lexydsl::make_range<0xD8, 0xF6>() / ovdl::detail::lexydsl::make_range<0xF8, 0xFF>(); static constexpr auto data_char_class = LEXY_CHAR_CLASS("DataSpecifier", data_specifier); struct Identifier { static constexpr auto rule = lexy::dsl::identifier(data_char_class); static constexpr auto value = lexy::as_string | lexy::new_; }; struct StringExpression { static constexpr auto escaped_symbols = lexy::symbol_table // .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(); return lexy::dsl::quoted(c, escape); }(); static constexpr auto value = lexy::as_string >> lexy::new_; }; struct SimpleAssignmentStatement { static constexpr auto rule = lexy::dsl::p >> lexy::dsl::equal_sign + (lexy::dsl::p | lexy::dsl::p | lexy::dsl::recurse_branch); static constexpr auto value = lexy::callback( [](auto name, auto&& initalizer) { return make_node_ptr(LEXY_MOV(name), LEXY_MOV(initalizer)); }); }; struct AssignmentStatement { static constexpr auto rule = lexy::dsl::p >> (lexy::dsl::equal_sign >> (lexy::dsl::p | lexy::dsl::p | lexy::dsl::recurse_branch) | lexy::dsl::else_ >> lexy::dsl::return_) | lexy::dsl::p; static constexpr auto value = lexy::callback( [](auto name, lexy::nullopt = {}) { return LEXY_MOV(name); }, [](auto name, auto&& initalizer) { return make_node_ptr(LEXY_MOV(name), LEXY_MOV(initalizer)); }); }; struct StatementListBlock { static constexpr auto rule = lexy::dsl::curly_bracketed( lexy::dsl::opt(lexy::dsl::list(lexy::dsl::p)) + lexy::dsl::opt(lexy::dsl::semicolon)); static constexpr auto value = lexy::as_list> >> lexy::callback( [](lexy::nullopt = {}, lexy::nullopt = {}) { return ast::make_node_ptr(); }, [](auto&& list, lexy::nullopt = {}) { return make_node_ptr(LEXY_MOV(list)); }, [](auto& list) { return make_node_ptr(list); }); }; struct File { // 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); static constexpr auto value = lexy::as_list> >> lexy::new_; }; }