我正在尝试编写一个boost :: spirit :: x3解析器,而不是生成子字符串(例如),而是在源中生成匹配字符串的偏移量和长度。
我尝试了on_success
处理程序的各种组合,语义操作,并没有真正有效。
下式给出:
ABC\n
DEFG\n
HI\n
我想要一个产生std::vector<boost::tuple<size_t, size_t>>
的解析器,其中包含:
0,3
4,4
9,2
显然,当我们匹配每一行的特定子串时,它变得更加复杂,而不仅仅是完整的事情。
这可能吗?
答案 0 :(得分:2)
这是一个快速草案。
我已将tuple<p, len>
替换为POD结构,因为x3::raw[]
和fusion/adapted/std_tuple.hpp
之间的互动无论如何都需要专门化traits::move_to
。
在这种情况下,我非常喜欢用户定义的自定义类型来专注于,而不是特殊包装一些可能与其他地方的其他用途发生冲突的通用标准库类型。
所以,让结构为
using It = char const*;
struct Range {
It data;
size_t size;
};
然后,解析以下示例输入:
char const input[] = "{ 123, 234, 345 }\n{ 456, 567, 678 }\n{ 789, 900, 1011 }";
我们只需要一个简单的语法:
x3::raw ['{' >> (x3::int_ % ',') >> '}'] % x3::eol
和dito特质专长:
namespace boost { namespace spirit { namespace x3 { namespace traits {
template <> void move_to<It, Range>(It b, It e, Range& r) { r = { b, size_t(e-b) }; }
} } } }
<强> Live On Coliru 强>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
using It = char const*;
struct Range {
It data;
size_t size;
};
namespace boost { namespace spirit { namespace x3 { namespace traits {
template <> void move_to<It, Range>(It b, It e, Range& r) { r = { b, size_t(e-b) }; }
} } } }
int main() {
char const input[] = "{ 123, 234, 345 }\n{ 456, 567, 678 }\n{ 789, 900, 1011 }";
std::vector<Range> ranges;
namespace x3 = boost::spirit::x3;
if (x3::phrase_parse(
std::begin(input), std::end(input),
x3::raw ['{' >> (x3::int_ % ',') >> '}'] % x3::eol,
x3::blank,
ranges)
)
{
std::cout << "Parse results:\n";
for (auto const& r : ranges) {
std::cout << "(" << (r.data-input) << "," << r.size << ")\n";
}
} else {
std::cout << "Parse failed\n";
}
}
打印:
Parse results:
(0,17)
(18,17)
(36,18)