提振精神:: ::复制齐解析的输出 [英] boost::spirit::qi duplicate parsing on the output

查看:134
本文介绍了提振精神:: ::复制齐解析的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Boost有一个非常简单的解析器::精神:

I have this very simple parser using Boost::Spirit:

rule<std::string::iterator, std::string()> zeroTo255 = (string("25") >> char_('0', '5'))
    | (char_('2') >> char_('0', '4') >> digit)
    | (char_('1') >> repeat[2](digit))
    | (char_('1', '9') >> digit) | digit;

当我尝试解析

std::string o{"1"};
std::string s;
parse(o.begin(), o.end(), zeroTo255, s);
std::cout << o << ": " << s << std::endl;

我有作为输出

1: 111

我明明做错事,但什么?

I'm obviously doing something wrong, but what?

推荐答案

齐::持有大约是它的一种方式,如正确地@Andrzej提到

qi::hold is one way about it, as correctly mentioned by @Andrzej

我觉得我有一些看法,可能会帮助,以及一个更好的解决方案。

I think I have a few observations that might help, as well as a better solution.

的要点是,灵将不需要用于通过设计属性临时的存储。事实上,它不能真正承担该属性是摆在首位拷贝的。这就是原因就在这里(想象一切解析成一个单一的std ::矢量&lt;>并为每个分析器一步复制?)。

The point is that Spirit will not require 'temp' storage for attributes by design. In fact, it can't really assume the attribute be copyable in the first place. This is the reason here (imagine parsing everything into a single std::vector<> and copying for each parser step?).

在一个更重要的层面,在我看来,如果它是不处理是倒退这里的属性,但是解析器前pression本身:它未能陈述的意图,并招对付一些重新presentations 当...真是不应该。

On a more essential level, it looks to me as if it is not the attribute handling that is backwards here, but the parser expression itself: It fails to state the intent, and incurs all kinds of complexity dealing with number representations when... really it shouldn't.

我就带它会

rule<std::string::iterator, std::string()> zeroTo255, alternatively;

alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];

您看:你让精神分析的数字,并且确实只是验证的范围,这是你想在第一时间做什么

You see: you let Spirit parse a number, and indeed just verify the range, which is what you wanted to do in the first place.

这在我看来是一个非典型的第二件事,就是该规则暴露了一个的std ::字符串属性,而不是无符号的事实焦例如:这是为什么?

The second thing that strikes me as a-typical, is the fact that the rule exposes a std::string attribute, instead of unsigned char e.g. Why is that?

假设这是一个有意识的设计决策,就可以通过明智地使用

Assuming this was a conscious design decision, you can have it your way by judicious use of


  • 负向前查找(解析器!) - 这不影响属性

  • 正向前查找(&放大器;分析器) - 不影响属性

  • 开始使用熟悉齐:: as_string 补气生:: 齐: :语义齐:: no_skip

  • 语义动作(不依赖的自动规则的)

  • negative lookahead (!parser) - which doesn't affect attributes
  • positive lookahead (&parser) - which doesn't affect attributes
  • Get acquainted with qi::as_string, qi::raw, qi::lexeme and qi::no_skip
  • semantic actions (don't rely on automatic rules)

下面就是你原来的规则变化最小的不得不的工作:

Here's what minimal change to your original rule would have worked:

zeroTo255 = raw [ 
          ("25" >> char_("0-5"))
        | ('2' >> char_("0-4") >> digit)
        | ('1' >> digit >> digit)
        | (char_("1-9") >> digit) 
        | digit
    ];

这有大致为code。使用同样的效果齐::持有但不_hold_ing属性值的性能缺点。

This has roughly the same effect as the code using qi::hold but not the performance drawback of _hold_ing attribute values.

希望这有助于。

全样本:住在 http://liveworkspace.org/$c$ C / 4v4CQW $ 0个

Full sample: Live on http://liveworkspace.org/code/4v4CQW$0:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

int main()
{
    using namespace qi;
    rule<std::string::iterator, std::string()> zeroTo255, alternatively;

    zeroTo255 = raw [ 
              ("25" >> char_("0-5"))
            | ('2' >> char_("0-4") >> digit)
            | ('1' >> digit >> digit)
            | (char_("1-9") >> digit) 
            | digit
        ];

    alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];

    for (auto& input : std::vector<std::string> { "255", "249", "178", "30", "4" })
    {
        std::string output;
        std::cout << "zeroTo255:\t" << std::boolalpha 
                  << parse(std::begin(input), std::end(input), zeroTo255, output) 
                  << ": " << output << std::endl;

        output.clear();
        std::cout << "alternatively:\t" << std::boolalpha 
                  << parse(std::begin(input), std::end(input), alternatively, output) 
                  << ": " << output << std::endl;
    }

}

输出

zeroTo255:      true: 255
alternatively:  true: 255
zeroTo255:      true: 249
alternatively:  true: 249
zeroTo255:      true: 178
alternatively:  true: 178
zeroTo255:      true: 30
alternatively:  true: 30
zeroTo255:      true: 4
alternatively:  true: 4

这篇关于提振精神:: ::复制齐解析的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆