从Employee - Parsing into structs开始示例:
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::int_;
using qi::lit;
using qi::double_;
using qi::lexeme;
using ascii::char_;
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %=
lit("employee")
>> '{'
>> int_ >> ','
>> quoted_string >> ','
>> quoted_string >> ','
>> double_
>> '}'
;
}
qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
qi::rule<Iterator, employee(), ascii::space_type> start;
};
假设我想将 quoted_string
替换为匹配给定容器中存储的任何字符串的规则。
例如,如果我有一个容器,例如:
std::array<std::string, 4> match_list =
{ "string0", "string1", "string2", "string3" };
并且我希望解析器仅将输入与数组中的值之一进行匹配(容器不必是数组)。
我敢肯定这很简单,但是 Spirit 帮助页面似乎没有解决这个问题。
最佳答案
很简单:https://www.boost.org/doc/libs/1_67_0/libs/spirit/doc/html/spirit/qi/reference/string/symbols.html
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
struct employee {
int id;
std::string sym;
std::string name;
double value;
};
BOOST_FUSION_ADAPT_STRUCT(employee, id, sym, name, value)
template <typename Iterator, typename Skipper = qi::space_type>
struct employee_parser : qi::grammar<Iterator, employee(), Skipper>
{
employee_parser() : employee_parser::base_type(start)
{
using namespace qi;
quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];
symbol_.add
("string0")
("string1")
("string2")
("string3")
;
start =
lit("employee")
>> '{'
>> int_ >> ','
>> symbol_ >> ','
>> quoted_string >> ','
>> double_
>> '}'
;
}
qi::rule<Iterator, std::string(), Skipper> quoted_string;
qi::rule<Iterator, employee(), Skipper> start;
qi::symbols<char, std::string> symbol_;
};
int main() {
std::string const input = "employee { 42, string3, \"more names or stuff\", 6.7 }";
using It = std::string::const_iterator;
It f = input.begin(), l = input.end();
employee_parser<It> p;
employee e;
if (phrase_parse(f, l, p, qi::space, e)) {
using boost::fusion::operator<<;
std::cout << boost::fusion::tuple_delimiter(';');
std::cout << "Parsed: " << e << "\n";
} else {
std::cout << "Parse failed\n";
}
if (f!=l)
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
打印
Parsed: (42;;more names or stuff;6.7)
实际包含值:
symbol_.add
("string0", "STRING0")
("string1", "STRING1")
("string2", "STRING2")
("string3", "STRING3")
;
Parsed: (42;STRING3;more names or stuff;6.7)
或者您可以完全使用另一种类型:
symbol_.add
("string0", 0)
("string1", 1)
("string2", 2)
("string3", 3)
;
与
symbol_.add
("string0", 0)
("string1", 1)
("string2", 2)
("string3", 3)
;
Parsed: (42;3;more names or stuff;6.7)
最后,您可以使用 raw[]
来“转换”输入序列,例如结合 qi::no_space[]
: Live On Coliru
>> raw[no_case[symbol_]] >> ','
打印
Parsed: (42;sTrInG3;more names or stuff;6.7)
关于c++ - 从 Boost.Spirit 中的固定列表中解析选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51315726/