提升精神:类似于排列,但不完全是
Boost Spirit : something like permutation, but not exactly
我正在尝试掌握 Spirit,这意味着我对此一窍不通(因此预计下文中会缺少适当的术语)。
我必须解析这个:
value1 = 10
value2 = 20
value3 = 30
value4 = 40
顺序无关紧要,但每个 "value1" ... "value4" 行必须恰好出现一次。这样就可以了:
value1 = 10
value4 = 40
value2 = 20
value3 = 30
但这不行(重复"value1"):
value1 = 10
value2 = 20
value3 = 30
value4 = 40
value1 = 10000
也不是这个(缺少 "value4"):
value1 = 10
value2 = 20
value3 = 30
我如何通过 Spirit 实现这一点?
额外问题:如果行 "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";
}
}
版画
---------------------------------------------------------
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)
如您所见,最后一个解决了您的奖励问题。
也看看 Spirit Repository 中的关键字解析器指令:
- 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
它允许您设置 min/max 次出现
我正在尝试掌握 Spirit,这意味着我对此一窍不通(因此预计下文中会缺少适当的术语)。
我必须解析这个:
value1 = 10
value2 = 20
value3 = 30
value4 = 40
顺序无关紧要,但每个 "value1" ... "value4" 行必须恰好出现一次。这样就可以了:
value1 = 10
value4 = 40
value2 = 20
value3 = 30
但这不行(重复"value1"):
value1 = 10
value2 = 20
value3 = 30
value4 = 40
value1 = 10000
也不是这个(缺少 "value4"):
value1 = 10
value2 = 20
value3 = 30
我如何通过 Spirit 实现这一点?
额外问题:如果行 "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";
}
}
版画
---------------------------------------------------------
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)
如您所见,最后一个解决了您的奖励问题。
也看看 Spirit Repository 中的关键字解析器指令:
- 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
它允许您设置 min/max 次出现