【问题标题】:Is this the correct way of defining a set of recursive rules?这是定义一组递归规则的正确方法吗?
【发布时间】:2020-08-31 03:27:39
【问题描述】:

前言:我问这个问题是因为由于某种原因我无法编译我的代码。我只想知道对spirit::x3的错误理解是否是原因

您好,我想验证一下;以下是为大量重递归解析器定义规则的正确方法(至少在技术上)吗?所以对于每一个解析器,我都会做如下操作:

// This is for reference only, it greatly simplifies the process of defining attributes.

template <class Tag, class... Bases> // the tag is for uniqueness
struct Access_base_s : Bases... {
    using base = Access_base_s;
    using Bases::Bases..., Bases::operator=...;
};

这是我对每个解析器的实际操作:

struct attribute : Access_base_s<class attribute_tag, underlying_type /*eg. std::string*/> {
    using base::base, base::operator=; // Access_base_s helps here
};

x3::rule<class rule_tag, attribute, true> rule_name = "rule_name";

auto rule_name_def = some_definition;

BOOST_SPIRIT_DEFINE(rule_name);

我用宏自动完成了这一切,所以它实际上看起来更像这样:

DECLARE_RULE(rulename1, "rulename1", rule1_attribute_type);
DECLARE_RULE(rulename2, "rulename2", rule2_attribute_type);
DECLARE_RULE(rulename3, "rulename3", rule3_attribute_type);

DEFINE_RULE(rulename1, rule1_definition);
DEFINE_RULE(rulename2, rule2_definition);
DEFINE_RULE(rulename3, rule3_definition);

我已经组织了不同解析器的声明和定义,以便它们分为两个部分;它们都是先声明的,然后在它们都已经声明时再定义。声明的意思是定义了它们的属性结构并声明了规则,定义的意思是实现了 rule_name_def 并在规则上调用了 BOOST_SPIRIT_DEFINE。

我已经尝试过最新版本的 MSVC、G++ 和 clang++,以及所有这些:

  • 至少需要 3 分钟
  • 遇到一些没有正确错误消息的内部编译器错误
  • 中止并让我没有可执行文件

当我尝试编译我的代码时。我已经有同样的问题两天了,这也是为什么,sehe,如果你正在阅读这篇文章,你可能是,我没有将你对我最后一个精神问题的回答标记为答案;由于忙于与编译器搏斗,我一直没有机会对其进行测试。

编辑:这是仍然导致相同错误的解析器的简化代码:

DECLARE_RULE(string_literal, "", std::string);
DECLARE_RULE(identifier    , "", std::string);

struct list;
struct dictionary;
struct expression;

DECLARE_RULE(literal       , "", x3::variant<double, int, string_literal, x3::forward_ast<list>, x3::forward_ast<dictionary>>);
DECLARE_RULE(parameter_pack, "", std::vector<expression>);
DECLARE_RULE(invocation    , "", parameter_pack);
DECLARE_RULE(expression    , "", x3::variant<literal, identifier, invocation>);
DECLARE_RULE(list          , "", std::vector<expression>);
DECLARE_RULE(dictionary    , "", std::vector<fusion::vector<expression, expression>>);


struct statement;
struct declaration;

DECLARE_RULE(compound_statement    , "", std::vector<statement>);
DECLARE_RULE(control_block_body    , "", x3::variant<x3::forward_ast<statement>, compound_statement>);
DECLARE_RULE(identifier_sequence   , "", std::vector<identifier>);
DECLARE_RULE(function_definition   , "", fusion::vector<identifier, std::vector<identifier>, control_block_body>);
DECLARE_RULE(structure_definition  , "", fusion::vector<identifier, std::vector<declaration>>);
DECLARE_RULE(enumeration_definition, "", fusion::vector<identifier, std::vector<fusion::vector<identifier, int>>>);
DECLARE_RULE(namespace_scope       , "", std::vector<declaration>);
DECLARE_RULE(namespace_extension   , "", fusion::vector<identifier, namespace_scope>);
DECLARE_RULE(declaration           , "", x3::variant<function_definition, structure_definition, enumeration_definition, namespace_extension>);
DECLARE_RULE(for_loop              , "", fusion::vector<identifier, expression, control_block_body>);
DECLARE_RULE(while_loop            , "", fusion::vector<expression, control_block_body>);
DECLARE_RULE(if_else_statement     , "", fusion::vector<expression, control_block_body, control_block_body>);
DECLARE_RULE(switch_statement      , "", fusion::vector<expression, std::vector<fusion::vector<expression, control_block_body>>>);
DECLARE_RULE(control_statement     , "", x3::variant<for_loop, while_loop, if_else_statement, switch_statement>);
DECLARE_RULE(statement_terminator  , "", std::string);
DECLARE_RULE(statement             , "", fusion::vector<x3::variant<expression, declaration, control_statement>, statement_terminator>);



DEFINE_RULE(string_literal, x3::lexeme['"' > *x3::char_ > '"']); // just a placeholder
DEFINE_RULE(identifier    , x3::lexeme[(x3::alpha | x3::char_('_')) >> *(x3::alnum | x3::char_('_'))]);
DEFINE_RULE(literal       , x3::double_ | x3::int_ | string_literal_ | list_ | dictionary_)
DEFINE_RULE(parameter_pack, +expression_);
DEFINE_RULE(invocation    , '(' > parameter_pack_ > ')');
DEFINE_RULE(expression    , literal_ | identifier_ | invocation_);
DEFINE_RULE(list          , '[' > *expression_ > ']');
DEFINE_RULE(dictionary    , '{' > *(expression_ > ':' > expression_) > '}');


DEFINE_RULE(compound_statement, '{' > *statement_ > '}');
DEFINE_RULE(control_block_body, (':' > statement_) | compound_statement_);
DEFINE_RULE(identifier_sequence, +identifier_);
DEFINE_RULE(function_definition, x3::lit("") > '(' > identifier_ > *identifier_ > ')' > control_block_body_);
DEFINE_RULE(structure_definition, "" > identifier_ > namespace_scope_);
DEFINE_RULE(enumeration_definition, "" > identifier_ > '{' > *(identifier_ > '=' > x3::int_) > '}');
DEFINE_RULE(namespace_scope, '{' > *declaration_ > '}');
DEFINE_RULE(namespace_extension, "" > identifier_ > namespace_scope_);
DEFINE_RULE(declaration, function_definition_ | structure_definition_ | enumeration_definition_ | namespace_extension_);
DEFINE_RULE(for_loop, "" > identifier_ > "" > expression_ > control_block_body_);
DEFINE_RULE(while_loop, "" > expression_ > control_block_body_);
DEFINE_RULE(if_else_statement, "" > expression_ > control_block_body_ > "" > control_block_body_);
DEFINE_RULE(switch_statement, "" > expression_ > '{' > *("" > expression_ > control_block_body_) > '}');
DEFINE_RULE(control_statement, for_loop_ | while_loop_ | if_else_statement_ | switch_statement_);
DEFINE_RULE(statement_terminator, x3::string("") | x3::string("") | x3::string(""));
DEFINE_RULE(statement, (expression_ | declaration_ | control_statement_) > statement_terminator_);

其中DECLARE_RULEDEFINE_RULE定义如下:

class empty_t {};

#define DEFINE_ATTRIBUTE(name, ...)                                                                                                                                                \
struct name : Access_base_s<class name ## _base_access_tag, std::conditional_t<!std::is_base_of_v<x3::position_tagged, __VA_ARGS__>, x3::position_tagged, empty_t>, __VA_ARGS__> { \
    using base::base, base::operator=;                                                                                                                                             \
} // the conditional is there to make sure each attribute inherits from position_tagged no more than once.

#define DECLARE_RULE(name, text, ...) \
DEFINE_ATTRIBUTE(name, __VA_ARGS__);  \
x3::rule<class name ## _tag, name, true> name ## _ = text

#define DEFINE_RULE(name, definition) \
auto name ## __def = definition;      \
BOOST_SPIRIT_DEFINE(name ## _)

我将宏设置为可变参数以稍微作弊;它允许我传入模板类型,而不必担心预处理器的白痴。例如,x3::variant&lt;std::string, int&gt; 将被视为 2 个单独的宏参数,__VA_ARGS__ 解决了这个问题。无论您在哪里看到它,它始终只是属性的基础类型。宏导致属性类型是名称本身,解析器是名称,但在其末尾附加下划线以符合 x3 之类的 x3::int_

这里是驱动代码:

int main() {
    std::string str = read_file("filename");
    auto begin = std::begin(str), end = std::end(str);
    std::cout << std::boolalpha << x3::phrase_parse(begin, end, statement_, x3::ascii::space);
}

另外,如果您无法通过名称来判断,我正在尝试为简单的 DSL 编写解析器。我可以使用 YACC 之类的东西,但我认为熟悉诸如 spirit::x3 之类的通用解析库非常有用,因此我试图通过这样做来熟悉它。

【问题讨论】:

  • 是的。那很有意思。但是没有你的代码就没什么好说的了。因为我们看不到。我可能可以使用您的片段编写自己的代码,但是 99$ 它没有您描述的问题。唯一“特别”的东西是你的 attribute 强类型设计模式,但这并不可怕(我在某些属性上使用它)
  • @sehe 我会尝试从我的代码中分离出导致问题的解析器,并将其添加到明天的帖子中。此外,如果您之前在 x3 的上下文中遇到过它,我忘了特别提到 MSVC 而不是仅仅崩溃实际上说“编译器堆空间不足”。这可能意味着特定的东西吗?
  • 是的。有什么东西在爆炸。我的 sipdey 感觉表明与更换船长有关(我以前见过)但我们会看到
  • @sehe 更换船长是指更换船长还是自行改变船长的行为?
  • 通过使用例如改变x3::skip()[]

标签: c++ parsing boost boost-spirit boost-spirit-x3


【解决方案1】:

这是 Spirit 中的一个错误;由PR651 修复;修复将在 1.76 版本中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多