使用boost spirit从括号中提取字符串
extracting string from bracket using boost spirit
我有以下字符串:
%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)
我想解析它和 store/extract 括号中的 90pv-RKSJ-UCS2C
字符串。
我的规则如下:
std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
std::string strStartTokenRecur;
std::string token_intRecur;
bool bParsedLine1 = qi::phrase_parse(strLinesRecur.begin(), strLinesRecur.end(), +char_>>+char_,':', token_intRecur, strStartTokenRecur);
您似乎认为船长是分隔符。恰恰相反(Boost spirit skipper issues).
在这种罕见的情况下,我想我更喜欢正则表达式。但是,既然你问了这里的精神:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
std::string const line = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
auto first = line.begin(), last = line.end();
std::string label, token;
bool ok = qi::phrase_parse(
first, last,
qi::lexeme [ "%%" >> +~qi::char_(":") ] >> ':' >> qi::lexeme["CMap"] >> '(' >> qi::lexeme[+~qi::char_(')')] >> ')',
qi::space,
label, token);
if (ok)
std::cout << "Parse success: label='" << label << "', token='" << token << "'\n";
else
std::cout << "Parse failed\n";
if (first!=last)
std::cout << "Remaining unparsed input: '" << std::string(first, last) << "'\n";
}
版画
Parse success: label='DocumentNeededResources', token='90pv-RKSJ-UCS2C'
好的,假设我们得到以下 using
和别名命名空间指令:
using namespace boost::spirit::qi;
namespace phx = boost::phoenix;
并给定字符串:
std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
我们想把括号内的"code"提取成res
:
std::string res;
一种方法是使用 boost::phoenix::ref
作为语义动作。
所以给定一个代码语法为:
using boost::spirit::ascii::alnum;
auto code = copy(+(alnum | char_('-')));
(这与正则表达式中的内容一致 [a-zA-Z\-]
)
我们可以为整个字符串创建自己的语法:
using boost::spirit::ascii::alpha;
auto grammar = copy(
(char_('%') >> char_('%') >> +alpha >> char_(':'))
>> +alpha >> char_('(') >> as_string[lexeme[code]][phx::ref(res) = _1] >> char_(')'));
它解析以两个 %
开头的任何内容,然后是一些字母字符和一个 :
,然后是括号内的一些 "code"。
整点是 as_string[lexeme[code]][phx::ref(res) = _1]
。如果我们将其分解:lexeme[code]
只是说将解析的 code
视为一个原子单元,as_string
"returns" 将结果视为 std::string
(与 std::vector<char>
) 和 [phx::ref(res) = _1]
使用语义操作将解析后的字符串存储到 res
中(_1
是该语法中第一个匹配项的占位符)。
在这种情况下,以下调用会跳过空格:
using boost::spirit::ascii::blank;
phrase_parse(begin(strLinesRecur), end(strLinesRecur), grammar, blank);
这当然只是适合该字符串的语法示例。
注意:copy
指的是 qi::copy
,这是一种能够像在对象 code
和 [=34= 中存储语法片段的方法].否则 auto
的使用将失败(可能出现分段错误)。
我有以下字符串:
%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)
我想解析它和 store/extract 括号中的 90pv-RKSJ-UCS2C
字符串。
我的规则如下:
std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
std::string strStartTokenRecur;
std::string token_intRecur;
bool bParsedLine1 = qi::phrase_parse(strLinesRecur.begin(), strLinesRecur.end(), +char_>>+char_,':', token_intRecur, strStartTokenRecur);
您似乎认为船长是分隔符。恰恰相反(Boost spirit skipper issues).
在这种罕见的情况下,我想我更喜欢正则表达式。但是,既然你问了这里的精神:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
std::string const line = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
auto first = line.begin(), last = line.end();
std::string label, token;
bool ok = qi::phrase_parse(
first, last,
qi::lexeme [ "%%" >> +~qi::char_(":") ] >> ':' >> qi::lexeme["CMap"] >> '(' >> qi::lexeme[+~qi::char_(')')] >> ')',
qi::space,
label, token);
if (ok)
std::cout << "Parse success: label='" << label << "', token='" << token << "'\n";
else
std::cout << "Parse failed\n";
if (first!=last)
std::cout << "Remaining unparsed input: '" << std::string(first, last) << "'\n";
}
版画
Parse success: label='DocumentNeededResources', token='90pv-RKSJ-UCS2C'
好的,假设我们得到以下 using
和别名命名空间指令:
using namespace boost::spirit::qi;
namespace phx = boost::phoenix;
并给定字符串:
std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
我们想把括号内的"code"提取成res
:
std::string res;
一种方法是使用 boost::phoenix::ref
作为语义动作。
所以给定一个代码语法为:
using boost::spirit::ascii::alnum;
auto code = copy(+(alnum | char_('-')));
(这与正则表达式中的内容一致 [a-zA-Z\-]
)
我们可以为整个字符串创建自己的语法:
using boost::spirit::ascii::alpha;
auto grammar = copy(
(char_('%') >> char_('%') >> +alpha >> char_(':'))
>> +alpha >> char_('(') >> as_string[lexeme[code]][phx::ref(res) = _1] >> char_(')'));
它解析以两个 %
开头的任何内容,然后是一些字母字符和一个 :
,然后是括号内的一些 "code"。
整点是 as_string[lexeme[code]][phx::ref(res) = _1]
。如果我们将其分解:lexeme[code]
只是说将解析的 code
视为一个原子单元,as_string
"returns" 将结果视为 std::string
(与 std::vector<char>
) 和 [phx::ref(res) = _1]
使用语义操作将解析后的字符串存储到 res
中(_1
是该语法中第一个匹配项的占位符)。
在这种情况下,以下调用会跳过空格:
using boost::spirit::ascii::blank;
phrase_parse(begin(strLinesRecur), end(strLinesRecur), grammar, blank);
这当然只是适合该字符串的语法示例。
注意:copy
指的是 qi::copy
,这是一种能够像在对象 code
和 [=34= 中存储语法片段的方法].否则 auto
的使用将失败(可能出现分段错误)。