#pragma once #include #include #include #include #include #include #include "SimpleGrammar.hpp" #include "detail/InternalConcepts.hpp" #include "detail/dsl.hpp" namespace ovdl::v2script::lua::grammar { template constexpr auto callback(Callback... cb) { return dsl::callback(cb...); } template constexpr auto construct = v2script::grammar::construct; template constexpr auto construct_list = v2script::grammar::construct_list; struct StatementListBlock; static constexpr auto comment_specifier = LEXY_LIT("--") >> lexy::dsl::until(lexy::dsl::newline).or_eof(); struct Identifier { static constexpr auto rule = lexy::dsl::identifier(lexy::dsl::ascii::alpha_underscore, lexy::dsl::ascii::alpha_digit_underscore); static constexpr auto value = callback( [](detail::IsParseState auto& state, auto lexeme) { auto value = state.ast().intern(lexeme.data(), lexeme.size()); return state.ast().template create(lexeme.begin(), lexeme.end(), value); }); }; struct Value { static constexpr auto rule = lexy::dsl::identifier(lexy::dsl::ascii::digit / lexy::dsl::lit_c<'.'> / lexy::dsl::lit_c<'-'>); static constexpr auto value = callback( [](detail::IsParseState auto& state, auto lexeme) { auto value = state.ast().intern(lexeme.data(), lexeme.size()); return state.ast().template create(lexeme.begin(), lexeme.end(), value); }); }; struct String : lexy::scan_production, lexy::token_production { template static constexpr scan_result scan(lexy::rule_scanner& scanner, detail::IsParseState auto& state) { using encoding = typename Reader::encoding; constexpr auto c = [] { if constexpr (std::same_as || std::same_as) { // Arbitrary code points that aren't control characters. return dsl::lit_b_range<0x20, 0xFF> - lexy::dsl::ascii::control; } else { return -lexy::dsl::unicode::control; } }(); auto rule = lexy::dsl::quoted(c) | lexy::dsl::single_quoted(c); auto begin = scanner.position(); lexy::scan_result str_result; scanner.parse(str_result, rule); if (!scanner || !str_result) return lexy::scan_failed; auto end = scanner.position(); auto str = str_result.value(); auto value = state.ast().intern(str.data(), str.size()); return state.ast().template create(begin, end, value); } static constexpr auto rule = lexy::dsl::peek(lexy::dsl::quoted.open() | lexy::dsl::single_quoted.open()) >> lexy::dsl::scan; static constexpr auto value = ovdl::v2script::grammar::convert_as_string >> lexy::forward; }; struct Expression { static constexpr auto rule = lexy::dsl::p | lexy::dsl::p; static constexpr auto value = lexy::forward; }; struct AssignmentStatement { static constexpr auto rule = [] { auto right_brace = lexy::dsl::lit_c<'}'>; auto expression = lexy::dsl::p; auto statement_list = lexy::dsl::recurse_branch; auto rhs_recover = lexy::dsl::recover(expression, statement_list).limit(right_brace); auto rhs_try = lexy::dsl::try_(expression | statement_list, rhs_recover); auto identifier = dsl::p >> lexy::dsl::equal_sign + rhs_try; auto recover = lexy::dsl::recover(identifier).limit(right_brace); return lexy::dsl::try_(identifier, recover); }(); static constexpr auto value = callback( [](detail::IsParseState auto& state, const char* pos, ast::IdentifierValue* name, ast::Value* initializer) -> ast::AssignStatement* { if (initializer == nullptr) return nullptr; return state.ast().template create(pos, name, initializer); }, [](detail::IsParseState auto& state, ast::Value*) { return nullptr; }, [](detail::IsParseState auto& state) { return nullptr; }); }; struct StatementListBlock { static constexpr auto rule = [] { auto right_brace = lexy::dsl::lit_c<'}'>; auto comma = lexy::dsl::lit_c<','>; auto assign_statement = lexy::dsl::recurse_branch; auto assign_try = lexy::dsl::try_(assign_statement); auto curly_bracket = dsl::curly_bracketed.opt_list( assign_try, lexy::dsl::trailing_sep(comma)); return lexy::dsl::try_(curly_bracket, lexy::dsl::find(right_brace)); }(); static constexpr auto value = lexy::as_list >> construct_list; }; struct File { // Allow arbitrary spaces between individual tokens. static constexpr auto whitespace = ovdl::v2script::grammar::whitespace_specifier | comment_specifier; static constexpr auto rule = lexy::dsl::position + lexy::dsl::terminator(lexy::dsl::eof).opt_list(lexy::dsl::p); static constexpr auto value = lexy::as_list >> construct; }; }