boost spirit X3解析器,可将偏移量转换为原始字符串 [英] boost spirit X3 parser which produces offsets into the original string

查看:90
本文介绍了boost spirit X3解析器,可将偏移量转换为原始字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写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) }; }
} } } }

完整演示

在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)

这篇关于boost spirit X3解析器,可将偏移量转换为原始字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆