这是定义一组递归规则的正确方法吗?
Is this the correct way of defining a set of recursive rules?
前言:我问这个问题是因为由于某种原因我无法编译我的代码。我只想知道对精神::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_RULE
和DEFINE_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__
修复了这一点。无论您在哪里看到它,它始终只是属性的基础类型。宏导致属性类型是名称本身,解析器是名称本身,但在其末尾附加了下划线以符合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(非常有用,所以我试图通过这样做来熟悉它。
这是精神中的一个错误; 由 PR651 修复; 修复将在 1.76 版本中提供。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 此代码是否违反一个定义规则
- 这是定义一组递归规则的正确方法吗?
- 有什么方法可以在 GNU Make 中使用变量作为规则和先决条件?
- Boost::精神与织物方法在一条规则中
- 了解方法重载规则
- 该"Named Constructor Idiom"似乎与静态方法无法访问非静态成员函数的规则相矛盾。有什么解释吗?
- g++和Visual Studio中方法指针强制转换规则之间的差异