1

我正在编写一个简单的通用解析器组合库。这意味着该库包含许多称为解析器的小函数对象,它们(在调用时)将字符串作为输入并返回 ParseResults 列表作为输出,其中 ParseResult 是

template <typename A> using ParseResult = std::pair<A, std::string> 如果解析器不匹配,则列表为空,如果匹配则包含单个结果,并且某些可能以多种(不明确)方式匹配的解析器可能会返回更多结果。

但是,这意味着现在正在进行大量的字符串复制。此外,在开始时,最终构造的解析器需要用一个字符串调用,因此所有std::cin(或文件的竞争内容)都被复制到一个字符串中。

似乎更好的主意(因为解析器只查看字符串当前前面的第一个(几个)字符),是跟踪您现在在标准输入流中的位置。我相信这正是 astd::istream的样子。但是,istream 是不可复制的。如何解决我的问题?有没有办法返回一个 istream 的副本,该副本指向原来指向的几个字符?还是有另一种更清洁的方法来解决这个问题?

4

1 回答 1

1

这个问题可以改写为:如何以一种避免过度复制并允许输入流的方式表示输入的未解析部分?

最灵活的方式是用迭代器来表示它。如果您的解析器进行回溯,则它需要是 a ForwardIterator,如果不是,InputIterator就足够了。这意味着您可以直接使用std::istream_iteratoroverstd::cinstd::ifstreams,或者从内存std::stringschar数组中解析。带有回溯的流式处理涉及更多,并且需要您编写一个缓冲迭代器适配器,将InputIteratorlikestd::istream_iterator转换为 aForwardIterator或编写一个迭代器直接包装std::ifstream并在.seekg()需要回溯时执行。

另一种选择是使用 C++17 std::string_view,它不会复制并且有一个很好的、易于解析的界面。但是,这并不能解决流式传输,您仍然必须先读取整个文件。

于 2017-02-24T21:39:21.127 回答