Boost spirit 鼓舞士气:有点像排列,但不完全是

Boost spirit 鼓舞士气:有点像排列,但不完全是,boost-spirit,boost-spirit-qi,Boost Spirit,Boost Spirit Qi,我试图掌握精神,这意味着我是一个在这方面的傻瓜(因此,在下文中可能缺少合适的术语) 我必须分析这个: value1 = 10 value2 = 20 value3 = 30 value4 = 40 顺序不重要,但每个“值1”。。。“value4”行必须正好出现一次。这样就可以了: value1 = 10 value4 = 40 value2 = 20 value3 = 30 但这并不合适(重复的“值1”): 也不包括以下内容(缺少“值4”): 我怎样才能用精神做到这一点 额外问题:如果行“v

我试图掌握精神,这意味着我是一个在这方面的傻瓜(因此,在下文中可能缺少合适的术语)

我必须分析这个:

value1 = 10
value2 = 20
value3 = 30
value4 = 40
顺序不重要,但每个“值1”。。。“value4”行必须正好出现一次。这样就可以了:

value1 = 10
value4 = 40
value2 = 20
value3 = 30
但这并不合适(重复的“值1”):

也不包括以下内容(缺少“值4”):

我怎样才能用精神做到这一点

额外问题:如果行“value3”是可选的,该怎么办


MaX.

我会使用置换解析器+附加的有效性检查

这样你就不必写所有的东西,而且仍然可以实现你想要的约束

#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";
    }
}
如您所见,最后一个问题解决了您的奖金问题

还可以查看Spirit存储库中的关键字解析器指令:


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

谢谢,关键字指令似乎符合要求。然而,在您的解决方案中,任何项目都可以是可选的,而我更感兴趣的是只选择其中一项。我说的对吗?@HometMaX你试过了吗?我想我已经说了为什么我会这样做:)无论如何,你可以自由使用关键字解析器(我没有太多的经验,我只知道它存在。它不是支持的Qi接口的一部分)嗨,sehe,不,我还没有试过。我希望在写下来之前100%地确定我理解了它(因为我必须解析的真实文件比上面的例子更复杂)。我对Fusion和Phoenix的使用也有点害怕(我一点也不知道):我仍在思考是否值得学习它们,或者我是否可以不用它们就完成这项工作。但我不确定“不属于支持的Qi接口”意味着什么。谢谢你的帮助!干杯没关系。我想说的是,如果你要使用精神,那么学习融合和凤凰是值得的(反之亦然)。当然,您可以使用更重的枪(自定义指令和自定义点),但这要复杂得多。我会尽可能多地帮助你,所以我可以向你保证,没有他们,我可以在精神上完成大部分任务。
value1 = 10
value2 = 20
value3 = 30
#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)