使用boost :: spirit解析字符串列表
问题描述:
我有一种情况,我将输入解析为向量boost :: Spirit的地图。使用boost :: spirit解析字符串列表
它运行良好,但我遇到了一种情况,我需要在某种情况下为用户输入提供一个固定的字符串,以便内部字符串被解析以代替用户输入。
这里是语法的一个示例:
input_pair =
key(std::string("__input")) >> valid_input % ','
;
其中:
key =
qi::attr(_r1)
;
和 “valid_input” 是一个简单的规则,对特定的字符串/字符模式测试等
该语法将输入与预定义的内部键配对,并将其作为向量存储在映射中。如果输入包含指定的分隔符,则输入将被适当地解析为接收向量的单独元素。
但是,我遇到的问题是为“valid_input”提供预定义的字符串。
我的第一个倾向是做什么我做与地图键:
input_pair =
key(std::string("__input")) >> key (std::string("A, B, C")) % ','
;
但是,当然,整个字符串被插入作为载体的第一要素。也就是说,“A,B,C”中的逗号分隔符不被认为是我所希望的。
因此我的问题:
给出一个boost ::精神解析器,其语法解析输入地图的载体,是有解析器本身中定义为载体任何方式来解析固定字符串?
答
给定的输入 “1 1 2 3 4”,下面的规则:
将(显然)解析的std::vector<string> { "1", "2", "3", "4" }
的属性值。
现在改变规则
rule %= qi::attr(attr_t { "aap", "noot", "mies" }) >> *qi::lexeme[+qi::char_];
,您会收到std::vector<string> { "aap", "noot", "mies", "1", "2", "3", "4" }
。如果要硬编码向量只有,请使用qi::omit
。
这是在工作中C++ 11统一初始化语法,因此,如果您不能使用,你必须提供一个载体一些其他的方式:
static const std::string hardcoded[] = { "aap", "noot", "mies" };
static const attr_t const_data(hardcoded, hardcoded+3);
rule = qi::attr(const_data) >> *qi::lexeme[+qi::char_];
这也是稍微更有效(代价是更详细的代码)。
在这里被完全工作实施例与本一些变型中(假定C++ 11编译器为测试主):
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
typedef std::vector<std::string> attr_t;
int main()
{
const std::string input = "1 2 3 4";
auto f(std::begin(input)), l(std::end(input));
qi::rule<decltype(f), attr_t(), qi::space_type> rule;
// #1: no hardcoded values
rule = *qi::lexeme[+qi::char_];
// #2: hardcoded inline temp vector
rule = qi::attr(attr_t { "aap", "noot", "mies" }) >> *qi::lexeme[+qi::char_];
// #3: hardcoded static vector, C++03 style
static const std::string hardcoded[] = { "aap", "noot", "mies" };
static const attr_t const_data(hardcoded, hardcoded+3);
rule = qi::attr(const_data) >> *qi::lexeme[+qi::char_];
try
{
attr_t data;
bool ok = qi::phrase_parse(f, l, rule, qi::space, data);
if (ok)
{
std::cout << "parse success\n";
std::cout << "data: " << karma::format_delimited(karma::auto_, ' ', data) << "\n";
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok? 0 : 255;
} catch(const qi::expectation_failure<decltype(f)>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
return 255;
}
}
它打印
parse success
data: 1 2 3 4
这是一个很好的方法。由于向量是硬编码的,我可以将它指定为多个字符串的列表,而不是一个字符串中包含的整个列表(当然,这是我*接受用户输入的方式)。感谢您的教训! – 2012-03-21 22:28:40