c++ - boost spirit X3 解析器生成原始字符串的偏移量

标签 c++ boost boost-spirit

我正在尝试编写一个 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

显然,当我们在每一行上匹配特定的子字符串时,它会变得更加复杂,而不是只匹配整个内容。

这可能吗?

最佳答案

这是一个快速草稿。

我用 POD 结构替换了 tuple<p, len>,因为 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 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) }; }
} } } }

完整演示

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)

关于c++ - boost spirit X3 解析器生成原始字符串的偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36994539/

相关文章:

c++ - (boost::)outcome 的错误处理:在具有组合和继承的构造函数中使用

c++ - 在 Mac 上使用 CodeBlocks 安装 Boost

c++ - 简单的 C 风格结构化输入的 Spirit Qi 解析问题

c++ - 如何将类中的函数放入线程中? (使用 Boost 的 C++)

c++ - 在文件中包含所有模板库

c++ - Libcurl得到响应 “415 Unsupported Media Type”但使用Curl.exe可以很好地工作

c++ - 以高效的方式创建、访问、存储和加载 boost::bimap

c++ - 如果函数调用返回 true,则跳过 boost::spirit::qi 中的部分输入

c++ - 执行字符集中字符的值是多少?

c++ - 编译器 : How is class instantiation code compiled?