本文介绍了增强精神:类似于排列,但不完全相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试掌握Spirit,这意味着我对此很陌生(因此,请期待下面缺少适当的术语).

I'm trying to get a grasp of Spirit, meaning I'm a noob at it (hence expect lack of proper terminology in the below).

我必须解析这个:

value1 = 10
value2 = 20
value3 = 30
value4 = 40

顺序无关紧要,但是每个"value1" ..."value4"行必须恰好出现一次.这样就可以了:

Order doesn't matter but each "value1" ... "value4" line must be present exactly once. This would be OK:

value1 = 10
value4 = 40
value2 = 20
value3 = 30

但这不行(重复的"value1"):

but this would not be OK (duplicated "value1"):

value1 = 10
value2 = 20
value3 = 30
value4 = 40
value1 = 10000

也不存在(缺少"value4"):

Nor this (missing "value4"):

value1 = 10
value2 = 20
value3 = 30

我怎么能用Spirit实现呢?

How could I achieve that with Spirit ?

奖金问题:如果"value3"行是可选行怎么办?

Bonus question: what if the line "value3" is optional ?

MaX.

推荐答案

我将使用排列分析器+附加的有效性检查.

I'd use the permutation parser + an added validity check.

这样,您不必编写所有内容,仍然可以实现所需的约束.

This way you don't have to write all the stuff, and can still achieve the constraints you want.

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/optional/optional_io.hpp>

struct X {
    boost::optional<int> value1;
    boost::optional<int> value2;
    boost::optional<int> value3;
    boost::optional<int> value4;
};

static bool is_valid(X const& x) { return x.value1 && x.value2 && x.value4; } // value3 is optional

BOOST_FUSION_ADAPT_STRUCT(X,
        (boost::optional<int>, value1)
        (boost::optional<int>, value2)
        (boost::optional<int>, value3)
        (boost::optional<int>, value4)
    )

int main() {
    namespace qi = boost::spirit::qi;
    namespace phx = boost::phoenix;
    using It = std::string::const_iterator;

    qi::rule<It, X(), qi::space_type> grammar;
    grammar =
        (("value1" > qi::lit('=') > qi::int_) ^
         ("value2" > qi::lit('=') > qi::int_) ^
         ("value3" > qi::lit('=') > qi::int_) ^
         ("value4" > qi::lit('=') > qi::int_))
        >> qi::eoi
        >> qi::eps(phx::bind(is_valid, qi::_val))
        ;

    for (std::string const& input : {
            "value1 = 10\nvalue2 = 20\nvalue3 = 30\nvalue4 = 40\n",
            // Order doesn't matter but each value1 ... value4 line must be present exactly once. This would be OK:
            "value1 = 10\nvalue4 = 40\nvalue2 = 20\nvalue3 = 30\n",
            // But this would not be OK (duplicated value1):
            "value1 = 10\nvalue2 = 20\nvalue3 = 30\nvalue4 = 40\nvalue1 = 10000\n",
            // Nor this (missing value4):
            "value1 = 10\nvalue2 = 20\nvalue3 = 30\n",
            // value3 _is_ optional though:
            "value1 = 10\nvalue2 = 20\nvalue4 = 40\n",
        })
    {
        std::cout << "---------------------------------------------------------\n";
        std::cout << "Parsing '" << input << "'\n";
        auto f(input.begin()), l(input.end());
        X parsed;
        bool ok = phrase_parse(f, l, grammar, qi::space, parsed);

        if (ok) {
            std::cout << "Parsing succeeded: " << boost::fusion::as_vector(parsed) << "\n";
        } else {
            std::cout << "Parsing failed\n";
        }

        if (f!=l)
            std::cout << "Remaing input '" << std::string(f,l) << "'\n";
    }
}

打印

---------------------------------------------------------
Parsing 'value1 = 10
value2 = 20
value3 = 30
value4 = 40
'
Parsing succeeded: ( 10  20  30  40)
---------------------------------------------------------
Parsing 'value1 = 10
value4 = 40
value2 = 20
value3 = 30
'
Parsing succeeded: ( 10  20  30  40)
---------------------------------------------------------
Parsing 'value1 = 10
value2 = 20
value3 = 30
value4 = 40
value1 = 10000
'
Parsing failed
Remaing input 'value1 = 10
value2 = 20
value3 = 30
value4 = 40
value1 = 10000
'
---------------------------------------------------------
Parsing 'value1 = 10
value2 = 20
value3 = 30
'
Parsing failed
Remaing input 'value1 = 10
value2 = 20
value3 = 30
'
---------------------------------------------------------
Parsing 'value1 = 10
value2 = 20
value4 = 40
'
Parsing succeeded: ( 10  20 --  40)

如您所见,最后一个解决了您的奖金问题.

As you can see, the last one addresses your bonus question.

也可以从Spirit Repository中查看关键字解析器指令:

Have a look at the keyword parser directive from the Spirit Repository too:

  • http://www.boost.org/doc/libs/1_57_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/kwd.html
  • http://www.boost.org/doc/libs/1_57_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/operators/keyword_list.html

它允许您设置最小/最大出现次数

It allows you to set min/max occurrences

这篇关于增强精神:类似于排列,但不完全相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 16:12