这是定义一组递归规则的正确方法吗?

Is this the correct way of defining a set of recursive rules?

本文关键字:规则 方法 递归 一组 定义      更新时间:2023-10-16

前言:我问这个问题是因为由于某种原因我无法编译我的代码。我只想知道对精神::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 分钟
  • 遇到一些内部编译器错误,没有正确的错误消息
  • 中止并让我没有可执行文件

当我尝试编译我的代码时。我已经有同样的问题 2 天了,这也是为什么,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<std::string, int>将计为 2 个单独的宏参数,__VA_ARGS__修复了这一点。无论您在哪里看到它,它始终只是属性的基础类型。宏导致属性类型是名称本身,解析器是名称本身,但在其末尾附加了下划线以符合x3x3::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(非常有用,所以我试图通过这样做来熟悉它。

这是精神中的一个错误; 由 PR651 修复; 修复将在 1.76 版本中提供。