作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 boost spirit x3 编写一个表达式解析器。
我的新代码基于我多年前用 Spirit 2.x (qi) 编写(并且运行良好)的旧代码。
我的代码的核心是:
//Make new rule(s) for expression
auto term = factor >> *(('*' >> factor) | ('/' >> factor));
auto expression = term >> *(('+' >> term) | ('-' >> term));
auto group = '(' >> expression >> ')';
auto factor = lexeme["double_"] | group;
string s="12.4 + 3.2";
auto first = s.begin();
auto last = s.end();
bool r = x3::phrase_parse(
first,
last,
// Begin grammar
expression,
// End grammar
x3::space);
我收到两个错误(Visual Studio 2019):
最佳答案
BOOST_SPIRIT_DEFINE 用于将静态规则标签与定义(即该规则的解析函数模板的实例化)相关联。
好消息是这通常是不必要的,并且可以在没有任何宏的情况下内嵌定义规则。
一般来说,使用x3::rule
存在以下原因:
rule<>
对象)来引用(很像前向声明)。#define BOOST_SPIRIT_X3_DEBUG
)。这是我知道使用 BOOST_SPIRIT_DEFINE
的唯一原因宏家族This frequently gives rise to hard-to diagnose linker errors so I recommend against this in most cases: X3 parsers compile fast enough in practice that I can afford to keep them in a single translation unit
expression
递归使用。对于其余的,只需重新排序它们就足够了:
namespace parser {
x3::rule<struct expression_> expression{"expression"};
auto group = '(' >> expression >> ')';
auto factor = x3::lexeme["double_"] | group;
auto term = factor >> *(('*' >> factor) | ('/' >> factor));
auto expression_def = term >> *(('+' >> term) | ('-' >> term));
BOOST_SPIRIT_DEFINE(expression)
}
看看
Live On Compiler Explorer 打印:
<expression>
<try>12.4 + 3.2</try>
<fail/>
</expression>
------ 12.4 + 3.2
r: false
remaining input: '12.4 + 3.2'
很明显,您的
factor
规则应该恢复正常:
auto factor = x3::double_ | group;
看看
Live On Compiler Explorer 打印:
<expression>
<try>12.4 + 3.2</try>
<success></success>
</expression>
------ 12.4 + 3.2
r: true
remaining input: ''
奖励:属性
namespace Ast {
struct binop;
using expression = boost::make_recursive_variant<
double,
boost::recursive_wrapper<binop>,
boost::recursive_variant_
>::type;
struct binop {
char op;
expression lhs, rhs;
};
}
这是可以工作的最简单的事情。您的规则对于从语义操作构建 ast 非常有效¹:
namespace parser {
x3::rule<struct expression_, Ast::expression> expression{"expression"};
auto assign = [](auto& ctx) { _val(ctx) = _attr(ctx); };
auto make_binop = [](auto& ctx) {
using boost::fusion::at_c;
auto& op = at_c<0>(_attr(ctx));
auto& rhs = at_c<1>(_attr(ctx));
_val(ctx) = Ast::binop { op, _val(ctx), rhs };
};
auto group
= x3::rule<struct group_, Ast::expression> {"group"}
= '(' >> expression >> ')';
auto factor
= x3::rule<struct factor_, Ast::expression> {"factor"}
= x3::double_ | group;
auto term
= x3::rule<struct term_, Ast::expression> {"term"}
= factor [assign] >> *(x3::char_("*/") >> factor) [make_binop];
auto expression_def
= term [assign] >> *(x3::char_("-+") >> term) [make_binop];
BOOST_SPIRIT_DEFINE(expression)
}
看看
Live On Compiler Explorer :
int main() {
for (std::string const s : {
"12.4 + 3.2",
})
{
auto f = s.begin(), l = s.end();
Ast::expression e;
bool r = x3::phrase_parse(f, l, parser::expression, x3::space, e);
std::cout
<< "------ " << s << "\n"
<< "r: " << std::boolalpha << r << "\n";
if (r)
std::cout << "e: " << e << "\n";
if (f!=l)
std::cout << "remaining input: '" << std::string(f,l) << "'\n";
}
}
打印
------ 12.4 + 3.2
r: true
e: (12.4 + 3.2)
和调试输出:
<expression>
<try>12.4 + 3.2</try>
<term>
<try>12.4 + 3.2</try>
<factor>
<try>12.4 + 3.2</try>
<success> + 3.2</success>
<attributes>12.4</attributes>
</factor>
<success> + 3.2</success>
<attributes>12.4</attributes>
</term>
<term>
<try> 3.2</try>
<factor>
<try> 3.2</try>
<success></success>
<attributes>3.2</attributes>
</factor>
<success></success>
<attributes>3.2</attributes>
</term>
<success></success>
<attributes>(12.4 + 3.2)</attributes>
</expression>
关于c++ - BOOST_SPIRIT_DEFINE 不明白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65566480/
我正在尝试用 boost spirit x3 编写一个表达式解析器。 我的新代码基于我多年前用 Spirit 2.x (qi) 编写(并且运行良好)的旧代码。 我的代码的核心是: //Make
我是一名优秀的程序员,十分优秀!