使用文字的默认值增强Spirit Qi整数 [英] Boost spirit qi integer with default value on literal
问题描述
我想用特定文字的默认值解析数字. 例如,如果程序接收到"nan"或"n/a",则整数默认值为-1.
I want to parse numbers with default values on specific literals. For example if the program receives "nan" or "n/a" the integer default value will be -1.
// Example program
#include <iostream>
#include <string>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
struct Person
{
std::string name;
int age;
std::string gender;
};
BOOST_FUSION_ADAPT_STRUCT(
Person,
(std::string, name)(int, age)(std::string, gender)
)
template <typename Iterator>
struct PersonGrammar : boost::spirit::qi::grammar<Iterator, Person(), boost::spirit::ascii::space_type>
{
using Skipper = boost::spirit::ascii::space_type;
PersonGrammar(std::ostream& error_stream = std::cerr)
: PersonGrammar::base_type(start, "Person")
{
string = +boost::spirit::qi::char_("a-zA-Z0-9_ .()/-") | boost::spirit::qi::attr("(unspecified)");
integer = boost::spirit::qi::lit("n/a") [boost::spirit::qi::_val = int(-1)] | boost::spirit::qi::int_;
//integer = boost::spirit::qi::lexeme[boost::spirit::qi::no_case[boost::spirit::qi::eps > ( boost::spirit::qi::lit("n/a")[boost::spirit::qi::_val = -1] | boost::spirit::qi::int_ ) ] ];
const char sep = ',';
start %= string >> boost::spirit::qi::lit(sep) >> integer >> boost::spirit::qi::lit(sep) >> string;
string.name("string");
integer.name("integer");
}
private:
boost::spirit::qi::rule<Iterator, std::string(), Skipper> string;
boost::spirit::qi::rule<Iterator, int(), Skipper> integer;
boost::spirit::qi::rule<Iterator, Person(), Skipper> start;
};
int main()
{
std::string input_row = "Jon Snow, n/a, male";
std::string::const_iterator iterator = input_row.begin();
std::string::const_iterator end = input_row.end();
PersonGrammar<std::string::const_iterator> grammar;
Person person;
bool success = boost::spirit::qi::phrase_parse(
iterator, end, grammar, boost::spirit::ascii::space, person);
std::cout << "Parse status: " << std::boolalpha << success << std::endl;
std::cout << "Person: " << person.name << std::endl << "Age: " << person.age << std::endl << "Gender: " << person.gender << std::endl;
return 0;
}
输出将是:
Parse status: true
Person: JonSnow
Age: -1
Gender: male
没关系.但我想用数字来填充它:
So it's okay. But I want to feed it with a number:
std::string input_row = "Jon Snow, 22, male";
输出将是:
Parse status: true
Person: JonSnow
Age: -2075995368
Gender: male
这是什么问题?我希望这不是一个错误.也许我使用的是错误的东西. 代码中有一个注释的词素.我也尝试过这种表达方式.不幸的是,它没有用.
What is the problem here? I hope this is not a bug. Maybe I'm using something wrong. There is a commented lexeme in the code. I tried that expression as well. Sadly it didn't work.
感谢您的帮助!
推荐答案
就是这样:
> (qi::int_ | (no_case["n/a"] >> qi::attr(-1)))
注意:
integer_ = lexeme[no_case[eps > ( lit("n/a")[_val = -1] | int_ ) ] ];
缺少对int_
的语义操作.或者,您需要使用%=
强制进行自动传播.但是,我的第一个建议是更优雅一些,IMO.
lacks the semantic action on int_
. OR you need to force automatic propagation with %=
. But my first suggestion is way more elegant, IMO.
在魔盒上直播 >
#include <iostream>
#include <string>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
struct Person
{
std::string name;
int age;
std::string gender;
};
BOOST_FUSION_ADAPT_STRUCT(
Person,
(std::string, name)(int, age)(std::string, gender)
)
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct PersonGrammar : qi::grammar<Iterator, Person(), qi::ascii::space_type>
{
PersonGrammar(std::ostream& /*error_stream*/ = std::cerr)
: PersonGrammar::base_type(start, "Person")
{
using namespace qi;
string_ = +char_("a-zA-Z0-9_ .()/-") | attr("(unspecified)");
integer_ = int_ | no_case["n/a"] >> attr(-1);
const char sep = ',';
start = string_ >> sep >> integer_ >> sep >> string_;
BOOST_SPIRIT_DEBUG_NODES((string_)(integer_))
}
private:
using Skipper = boost::spirit::ascii::space_type;
qi::rule<Iterator, std::string(), Skipper> string_;
qi::rule<Iterator, int(), Skipper> integer_;
qi::rule<Iterator, Person(), Skipper> start;
};
int main() {
std::string input_row = "Jon Snow, n/a, male";
std::string::const_iterator iterator = input_row.begin();
std::string::const_iterator end = input_row.end();
PersonGrammar<std::string::const_iterator> grammar;
Person person;
bool success = qi::phrase_parse(
iterator, end, grammar, qi::ascii::space, person);
std::cout << "Parse status: " << std::boolalpha << success << std::endl;
std::cout << "Person: " << person.name << std::endl << "Age: " << person.age << std::endl << "Gender: " << person.gender << std::endl;
}
打印
Parse status: true
Person: JonSnow
Age: -1
Gender: male
这篇关于使用文字的默认值增强Spirit Qi整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!