提振精神:: ::复制齐解析的输出(boost::spirit::qi duplicate pars

2019-07-05 06:15发布

我使用boost ::精神这个非常简单的解析器:

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

我明明做错事,但什么?

Answer 1:

qi::hold大约是它的一种方式,如正确地@Andrzej提到

我想我有几点看法,可能会帮助,以及更好的解决方案。


问题的关键是,灵将不需要通过设计属性“临时”存储。 事实上,它不能真正承担属性是摆在首位可复制。 这是原因这里(想象解析一切成一个单一的std ::矢量<>和复制为每个解析器步骤?)。

在一个更重要的水平,在我看来,如果它不是属性的处理是倒退这里,但解析器表达式本身: 它没有说明意图,并造成处理多次交涉时, 各种复杂的 ...真不应该。

我就带它会

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

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

你看:你让精神分析的数字,而事实上只是验证的范围,这是你想在第一时间做什么。

这在我看来是一个非典型的第二件事,是一个事实,即规则暴露出std::string ,而不是属性, unsigned char如这是为什么?

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

  • 负前瞻( !parser ) -这不影响属性
  • 正向前查找( &parser ) -这不影响属性
  • 想结识qi::as_stringqi::rawqi::lexemeqi::no_skip
  • 语义动作(不依赖于自动规则

这里就是你原来的规则变化最小工作:

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

这有大致为使用的代码相同的效果qi::hold但不_hold_ing属性值的性能缺陷。

希望这可以帮助。

全样本:住在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


Answer 2:

我遇到了类似的问题一次。 这是特别的方式在精神的替代操作符。 如果你使用其他指令“HOLD”你的榜样应该工作。

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

有关此行为的详细信息请参阅此线程 。



文章来源: boost::spirit::qi duplicate parsing on the output