关于 Spirit.Qi 序列运算符和语义动作的问题

2024-03-06

我对灵气中的序列运算符和语义动作有一些疑问。

我正在尝试为接受公制前缀(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;

问题一:为什么我必须向规则添加语义操作sign多于?不是char可转换为std::string?

问题2:当我尝试合并最后两条规则时,为什么编译会失败:

  rule<Iterator, std::string()> floating = -sign >> (mantissa >> -(exp | suffix) | +digit >> (exp | suffix));

问题3:假设我想让属性floating be double并编写一个语义操作来执行从字符串到双精度的转换。如何从语义操作内部引用与规则匹配的整个字符串?

问题4:在规则中floating问题2中,占位符的作用是什么_2指的是它的类型是什么?

Edit:

我想最后一个问题需要澄清一下:

占位符 _2 在以下规则的语义动作中指代什么?它的类型是什么?

  rule<Iterator, std::string()> floating = (-sign >> (mantissa >> -(exp | suffix) | +digit >> (exp | suffix))) [ _2 ];

Thanks!


首先,逐一击破。请参阅下面的开箱即用答案。

问题1:为什么我要在上面的规则标志上添加语义动作? char 不能转换为 std::string 吗?

呃,没有字符不能转换为字符串。请参阅下文了解其他选项。

问题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> > >

或类似的(参见解析器的文档 http://www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/operator.html,我凭记忆在浏览器中输入了此内容)。显然,这不能分配给字符串。使用qi::as<>强制原子分配。为了方便***有qi::as_string:

floating = qi::as_string [ -sign >> (mantissa >> -(exp | suffix) | 
                                     +digit >> (exp | suffix)) ] 

问题3: 假设我想让浮动属性为 double 并且 编写一个语义操作来执行从字符串到双精度的转换。我怎么能够 从语义内部引用规则匹配的整个字符串 行动?

你可以使用qi::as_string再次,但最合适的似乎是使用qi::raw:

floating = qi::raw [ -sign >> (mantissa >> -(exp | suffix) | 
                               +digit >> (exp | suffix)) ] 
       [ _val = parse_float(_1, _2) ];

这个解析器指示公开一对源迭代器,因此您可以使用它来引用精确匹配的输入序列。

问题4:问题2的规则浮动中,占位符_2是做什么用的 指的是它的类型是什么?

一般来说,要检测属性类型 - 也就是说,当文档让您感到困惑或您想仔细检查您对它的理解时 - 请参阅此处的答案:

  • 检测 Spirit 语义动作中的参数类型 https://stackoverflow.com/questions/9404189/detecting-the-parameter-types-in-a-spirit-semantic-action/9405265#9405265

盒子外面

你有没有看过使用Qi的builtin real_parser<>模板 http://www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html#spirit.qi.reference.numeric.real._code__phrase_role__identifier__realpolicies__phrase___code_,可全面定制。看起来您确实想要使用它,而不是在语义操作中进行自定义解析。

真实的_parser模板与policies既快速又非常灵活和强大。另请参阅最近的答案是否可以使用输入流读取无穷大或 NaN 值? https://stackoverflow.com/questions/11420263/is-it-possible-to-read-infinity-or-nan-values-using-input-streams/11420901#11420901.

对于 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

See 这个例子 http://www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html#spirit.qi.reference.numeric.real.example了解如何使用它的令人信服的想法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 Spirit.Qi 序列运算符和语义动作的问题 的相关文章

随机推荐