【发布时间】:2021-04-17 21:58:44
【问题描述】:
我最近正在使用 boost spirit x3 编写一个最简单的解析器。它包含 2 个规则:identifier 和单个字符 operator。自然地,我使用符号表实现了运算符,它产生了一个运算符类型enum class。 标识符被解析为std::strings。但是,当将标识符和运算符组合到一个解析器中时,代码会拒绝编译(请参阅问题末尾的代码段)。
请注意,如果您将运算符类型枚举更改为整数,则一切正常。运算符和标识符在分开时也能很好地解析。
模板错误消息很大,无法附加,而且我无法理解,但我怀疑它与std::variant<std::string, OperType> 的构造/移动语义有关。然而,enum class 不应该与普通的int 有很大不同。它与enum class 默认构造函数有什么关系吗?如何绕过?
这是密码
#include <variant>
#include <string>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
auto addCharacter = [](auto &context) {
x3::_val(context).push_back(x3::_attr(context));
};
x3::rule<class IdentifierTag, std::string> identifier{"identifier"};
const auto identifier_def = x3::lexeme[x3::char_("a-zA-Z")[addCharacter] >> *(x3::char_("a-zA-Z0-9")[addCharacter])];
BOOST_SPIRIT_DEFINE(identifier);
enum class OperType
{
plus,
minus
};
struct Opers_ : x3::symbols<OperType>
{
Opers_()
{
add("+", OperType::plus)("-", OperType::minus);
}
} opers_;
x3::rule<class OperTypeTag, OperType> oper{"operator"};
const auto oper_def = x3::lexeme[opers_];
BOOST_SPIRIT_DEFINE(oper);
int main()
{
std::string input{"iden1 + - iden2"};
std::vector<std::variant<std::string, OperType>> tokens;
auto start = input.cbegin();
auto result = x3::phrase_parse(start, input.cend(), (+(identifier | oper)), x3::space, tokens);
return 0;
}
编写复合解析器时有什么陷阱吗?我错过了什么?感谢您的宝贵时间。
【问题讨论】:
标签: c++ boost boost-spirit boost-spirit-x3