【问题标题】:Questions about Spirit.Qi sequence operator and semantic actions关于 Spirit.Qi 序列算子和语义动作的问题
【发布时间】:2012-07-19 20:28:30
【问题描述】:

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

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

谢谢!

【问题讨论】:

    标签: boost-spirit boost-spirit-qi


    【解决方案1】:

    首先,逐个介绍。请参阅下面的开箱即用答案。

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

    或类似的(参见the documentation for the parsers,我是从内存中在浏览器中输入的)。显然,这不能分配给字符串。使用qi::as&lt;&gt; 强制进行原子分配。为方便起见***有qi::as_string:

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

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

    您可以再次使用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&lt;&gt; template,可以全面定制。看起来您确实想使用它而不是在语义操作中进行自定义解析。

    带有策略的real_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,了解如何使用它的令人信服的想法。

    【讨论】:

    • 谢谢赛斯。说的很全面!我仍然有一个问题。您说这种类型显然不能分配给字符串:vector2&lt;optional&lt;string&gt;, variant&lt; vector2&lt;string, optional&lt;string&gt; &gt;, vector2&lt;std::vector&lt;char&gt;, optional&lt;string&gt; &gt; &gt; 那么是什么让类型:variant&lt; vector2&lt;string, optional&lt;string&gt; &gt;, vector2&lt;std::vector&lt;char&gt;, optional&lt;string&gt; &gt; 可以分配给字符串?换句话说,是什么让两种类型兼容或不兼容?
    • Spirit 具有 自定义点 用于属性处理(提取、转换、分配),这些都记录在 in the advanced section of the documentation
    猜你喜欢
    • 2011-10-16
    • 1970-01-01
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    相关资源
    最近更新 更多