使用boost :: spirit :: qi我尝试解析由标签后跟可变数量的分隔标记组成的行。我使用 phrase_parse 调用语法,并使用提供的空白解析器作为跳过解析器来保留换行符,因为我需要确保标签是每个标签上的第一个项目线。
简单的基本情况:
label token, token, token
可以用语法解析:
line = label >> (token % ',') >> eol;
我面临的问题是语法应该接受零个或多个令牌,并且令牌可能是空的。语法应该接受以下几行:
label
label ,
label , token
label token, , token,
我还没有设法创建一个接受上述所有示例的语法。 关于如何解决这个问题的任何建议?
修改
感谢关于上述问题的所有输入。 现在,我忘了包括有趣的部分...... 语法也应该接受空行和分割线。 (没有标签的代币) 当我尝试使标签可选时,我得到一个与空字符串匹配的无限循环。
label
label token
token
答案 0 :(得分:3)
你应该能够接受带有
的空列表line = label >> -(token % ',') >> eol;
请注意,eol
如果你的队长也跳过了eol也不会工作(所以不要使用qi::space
但是qi::blank
用于此目的)
此外,根据token
的定义,你应该改变它以接受"空"令牌以及
回应评论:完整的工作示例 Live On Coliru
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi;
using It = std::string::const_iterator;
using Token = std::string;
using Tokens = std::vector<Token>;
rule<It, blank_type> label
= lexeme[+~char_(":")] >> ':'
;
rule<It, Token(), blank_type> token
= lexeme[*~char_(",\n")];
;
rule<It, Tokens(), blank_type> line
= label >> -(token % ',') >> eol
;
for (std::string const input : {
"my first label: 123, 234, 345 with spaces\n",
"1:\n",
"2: \n",
"3: ,,,\n",
"4: , \t ,,\n",
"5: , \t , something something,\n",
})
{
std::cout << std::string(40, '=') << "\nparsing: '" << input << "'\n";
Tokens parsed;
auto f = input.begin(), l = input.end();
bool ok = phrase_parse(f, l, line, blank, parsed);
if (ok)
{
std::cout << "Tokens parsed successfully, number parsed: " << parsed.size() << "\n";
for (auto token : parsed)
std::cout << "token value '" << token << "'\n";
}
else
std::cout << "Parse failed\n";
if (f != l)
std::cout << "Remaining input: '" << std::string(f, l) << "'\n";
}
}
输出:
========================================
parsing: 'my first label: 123, 234, 345 with spaces
'
Tokens parsed successfully, number parsed: 3
token value '123'
token value '234'
token value '345 with spaces'
========================================
parsing: '1:
'
Tokens parsed successfully, number parsed: 1
token value ''
========================================
parsing: '2:
'
Tokens parsed successfully, number parsed: 1
token value ''
========================================
parsing: '3: ,,,
'
Tokens parsed successfully, number parsed: 4
token value ''
token value ''
token value ''
token value ''
========================================
parsing: '4: , ,,
'
Tokens parsed successfully, number parsed: 4
token value ''
token value ''
token value ''
token value ''
========================================
parsing: '5: , , something something,
'
Tokens parsed successfully, number parsed: 4
token value ''
token value ''
token value 'something something'
token value ''