我对Spirit Qi中的序列操作符和语义操作有一些疑问。
我正在尝试为接受度量标准前缀(u,m,k,M等)以及正常指数形式的浮点数定义语法规则。
rule<Iterator, std::string()> sign = char_("+-") [ _val = _1 ];
rule<Iterator, std::string()> exp = char_("eE") >> -sign >> +digit;
rule<Iterator, std::string()> suffix = char_("yzafpnumkKMGTPEZY") [ _val = _1 ];
rule<Iterator, std::string()> mantissa = ((*digit >> char_('.') >> +digit) | (+digit >> char_('.') >> *digit));
rule<Iterator, std::string()> unsigned_floating = (mantissa >> -(exp | suffix) | +digit >> (exp | suffix));
rule<Iterator, std::string()> floating = -sign >> unsigned_floating;
问题1:为什么我必须在上面的规则sign
中添加语义操作? char
不能转换为std::string
吗?
问题2:当我尝试合并最后两个规则时,为什么编译失败:
rule<Iterator, std::string()> floating = -sign >> (mantissa >> -(exp | suffix) | +digit >> (exp | suffix));
问题3:假设我想让floating
的属性为double
并编写语义操作来执行从字符串到双精度的转换。如何从语义操作中引用规则匹配的整个字符串?
问题4:在问题2的规则floating
中,占位符_2
引用了什么以及它的类型是什么?
修改
我想最后一个问题需要澄清一下:
占位符_2在以下规则的语义操作中引用了什么,它的类型是什么?
rule<Iterator, std::string()> floating = (-sign >> (mantissa >> -(exp | suffix) | +digit >> (exp | suffix))) [ _2 ];
谢谢!
答案 0 :(得分:2)
首先,逐个打击。请参阅下面的开箱即用答案。
问题1 :为什么我必须在上面的规则标志中添加语义操作? char不能转换为std :: string吗?
嗯,没有char不能转换成字符串。请参阅下面的其他选项。
问题2 :当我尝试合并最后两条规则时,为什么编译失败 像这样:
rule<Iterator, std::string()> floating = -sign >> (mantissa >> -(exp | suffix) | +digit >> (exp | suffix));
这是由于原子属性赋值的规则。解析器暴露了像
这样的东西vector2<optional<string>, variant<
vector2<string, optional<string> >,
vector2<std::vector<char>, optional<string> > >
或类似的(见the documentation for the parsers,我在浏览器中从内存中输入了这个)。显然,这不能分配给字符串。使用qi::as<>
来强制原子分配。为方便起见,有qi::as_string
:
floating = qi::as_string [ -sign >> (mantissa >> -(exp | suffix) |
+digit >> (exp | suffix)) ]
问题3 :假设我想让浮动属性加倍 写一个语义动作来进行从字符串到双精度的转换。我怎么能够 从语义内部引用规则匹配的整个字符串 动作?
您可以再次使用qi::as_string
,但最合适的似乎是使用qi::raw
:
floating = qi::raw [ -sign >> (mantissa >> -(exp | suffix) |
+digit >> (exp | suffix)) ]
[ _val = parse_float(_1, _2) ];
此解析器指令公开了一对源迭代器,因此您可以使用它来引用匹配的确切输入序列。
问题4 :在问题2的规则浮动中,占位符_2是什么 参考什么是它的类型?
一般来说,要检测属性类型 - 也就是说,当文档让您感到困惑或想要仔细检查对它的理解时 - 请参阅此处的答案:
你看过使用Qi builtin real_parser<>
template,它可以全面定制。看起来你肯定想要使用它而不是在你的语义动作中进行自定义解析。
带有政策的真实_ parser
模板既快又灵活又强大。另请参阅最近的答案Is it possible to read infinity or NaN values using input streams?。
对于RealPolicies的模型,以下表达式必须有效:
Expression | Semantics
===========================+=============================================================================
RP::allow_leading_dot | Allow leading dot.
RP::allow_trailing_dot | Allow trailing dot.
RP::expect_dot | Require a dot.
RP::parse_sign(f, l) | Parse the prefix sign (e.g. '-'). Return true if successful, otherwise false.
RP::parse_n(f, l, n) | Parse the integer at the left of the decimal point. Return true if successful, otherwise false. If successful, place the result into n.
RP::parse_dot(f, l) | Parse the decimal point. Return true if successful, otherwise false.
RP::parse_frac_n(f, l, n) | Parse the fraction after the decimal point. Return true if successful, otherwise false. If successful, place the result into n.
RP::parse_exp(f, l) | Parse the exponent prefix (e.g. 'e'). Return true if successful, otherwise false.
RP::parse_exp_n(f, l, n) | Parse the actual exponent. Return true if successful, otherwise false. If successful, place the result into n.
RP::parse_nan(f, l, n) | Parse a NaN. Return true if successful, otherwise false. If successful, place the result into n.
RP::parse_inf(f, l, n) | Parse an Inf. Return true if successful, otherwise false. If successful, place the result into n
请参阅 the example ,了解您如何使用它。