启用此Spirit x3 c++项目的正确编译

exdqitrt  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(130)

我正在练习使用Spirit x3解析C language并将其存储在自定义数据结构中。
但我遇到了巨大的困难,5天后仍然无法编译。
提示的大多数错误都是不完整的结构,无法进行赋值。
但我仔细检查了没有不完整的数据结构。
例如,无法转换以下结构:

谁接受这个挑战,以帮助修改代码,使之编译。git仓库的代码可以随意克隆和修改:
git code
C language BNF

nbnkbykc

nbnkbykc1#

但我仔细检查了没有不完整的数据结构。
投诉的不是这个。它说的是“不兼容”,而不是“不完整”。有些东西是不会改变的。
使用此临时CMakeLists.txt

project(cc)
cmake_minimum_required(VERSION 3.22.0)
set(BOOST_ROOT /home/sehe/custom/superboost)
find_package(Boost 1.82.0 REQUIRED)

set(CMAKE_CXX_COMPILER g++-13)
set(CMAKE_CXX_STANDARD 23)
add_executable(cc main.cpp)
target_link_libraries(cc Boost::boost)

经过几次清理/审查提交后,我最终发现了第一个与传播相关的错误,

auto const init_declarator_def = ((declarator >> '=' >> initializer) | declarator);

您可以从错误消息here中的rule标记中看出:
rule_def.hpp|214 col 5| required from ‘bool parse::parse_rule(boost::spirit::x3::detail::rule_id<init_declarator_class>, Iterator&, const Iterator&, const Context&, boost::spirit::x3::rule<?>::attribute_type&) [with Iterator = const char*; Context = boost::spirit::x3::context<?>; boost::spirit::x3::rule<?>::attribute_type = ast::test::init_declarator]’
AST为:

struct init_declarator_1 {
    x3::forward_ast<declarator> pre;
    initializer                 last;
};
struct init_declarator : x3::variant<init_declarator_1, x3::forward_ast<declarator>> {
    using base_type::base_type;
    using base_type::operator=;
};

我能理解你的期望,但精神不能:
/home/sehe/custom/superboost/libs/spirit/include/boost/spirit/home/x3/support/ast/variant.hpp|184 col 17| error: no match for ‘operator=’ (operand types are ‘boost::spirit::x3::variant<ast::test::init_declarator_1, boost::spirit::x3::forward_ast<ast::test::declarator> >::variant_type’ and ‘boost::fusion::deque<ast::test::declarator,ast::test::initializer>’)
如何将fusion::deque<...>分配给init_declarator_1?我知道你改编了它,但X3没有上下文线索来合成什么。明确规则:

auto const init_declarator_def = ( //
    (x3::rule<struct _, ast::test::init_declarator_1>{"init_declarator_1"} =
         declarator >> '=' >> initializer) //
    | declarator                           //
);

现在它可以编译了,下一个问题出现在selection_statement_class中。从这里开始冲洗并重复。

摘要

检查您的属性兼容性。理想情况下,从SMALL子语法开始,只前进到更高级别的产生式IFF,低级别的产生式都能正确地编译和传播。
你可能会注意到这是测试驱动编程的基本原则。如果你不限制范围来寻找上下文,你就不能指望在错误小说中找到自己的路。

奖金

请注意,我倾向于使用a type-coercion facility来使上面的操作更容易:

namespace {
    template <typename T>
    struct as_type {
        template <typename Expr>
            auto operator[](Expr&& expr) const {
                return x3::rule<struct _, T>{"as"} = x3::as_parser(std::forward<Expr>(expr));
            }
    };

    template <typename T> static const as_type<T> as = {};
}

现在,您可以编写上面的匿名规则,如

auto const init_declarator_def                                           //
    = as<ast::test::init_declarator_1>[declarator >> '=' >> initializer] //
    | declarator;

当你去修复selection_statement时,请帮自己一个忙,不要再使用像selection_statement_1这样令人费解的名字。我们是人类,不是代码生成器。
你真正需要的是这样的规则:

auto selection_statement = if_statement | switch_statement;

auto if_statement = "id" >> '(' >> expression >> ')' >> statement >> -("else" >> statement);

要匹配的AST:

struct if_statement {
     expression          cond;
     statement           true_branch;
     optional<statement> false_branch;
};

PEG语法不是BNF。此外,Spirit是一个用于解析器规范的eDSL。你的目标不是机器翻译,而是一个可维护的、高效的解析器生成器。

相关问题