boost spirit X3解析器,可将偏移量转换为原始字符串 [英] boost spirit X3 parser which produces offsets into the original string
问题描述
我正在尝试编写boost :: spirit :: x3解析器,该解析器而不是生成子字符串(例如),而是在源文件中生成匹配字符串的偏移量和长度.
I am trying to write a boost::spirit::x3 parser which, rather than producing the sub-strings (for instance), instead produces offsets and lengths of the matches strings in the source.
我尝试了on_success
处理程序,语义操作的各种组合,但没有真正起作用.
I have tried various combinations of on_success
handlers, semantic actions, and nothing has really worked.
给定:
ABC\n
DEFG\n
HI\n
我想要一个生成包含以下内容的std::vector<boost::tuple<size_t, size_t>>
的解析器:
I'd like a parser which produced a std::vector<boost::tuple<size_t, size_t>>
containing:
0,3
4,4
9,2
显然,随着我们在每一行上匹配特定的子字符串,而不仅仅是简单地处理整个事情,事情变得更加复杂.
where clearly it gets more complicated as we match specific substrings on each line, rather than just taking the whole thing.
这可能吗?
推荐答案
以下是快速草稿.
我已经用POD结构替换了tuple<p, len>
,因为x3::raw[]
和fusion/adapted/std_tuple.hpp
之间的相互作用使得您仍然需要专门研究traits::move_to
.
I've replaced tuple<p, len>
with a POD struct because the interaction between x3::raw[]
and fusion/adapted/std_tuple.hpp
is such that you need to specialize traits::move_to
anyways.
在这种情况下,我非常希望使用用户定义的自定义类型来专门研究,而不是将某些可能与其他地方的其他用途相冲突的通用标准库类型进行特殊包装.
In such cases I hugely prefer a user-defined custom type to specialize on, rather than special casing some generic standard library types that could collide with other uses elsewhere.
所以,让结构成为
using It = char const*;
struct Range {
It data;
size_t size;
};
然后,解析以下示例输入:
Then, to parse the following sample input:
char const input[] = "{ 123, 234, 345 }\n{ 456, 567, 678 }\n{ 789, 900, 1011 }";
我们只需要一个简单的语法:
We need nothing more than a simple grammar:
x3::raw ['{' >> (x3::int_ % ',') >> '}'] % x3::eol
以及dito特性特化:
And a dito trait specialization:
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) }; }
} } } }
完整演示
#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)
这篇关于boost spirit X3解析器,可将偏移量转换为原始字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!