我正在编写一个简单的通用解析器组合库。这意味着该库包含许多小函数对象,称为解析器,(在调用时)将字符串作为输入并返回ParseResults列表作为输出,其中ParseResult是
template <typename A>
using ParseResult = std::pair<A, std::string>
如果解析器不匹配,则列表为空,如果匹配,则包含单个结果,并且可能以多种(模糊)方式匹配的某些解析器可能返回更多结果。
但是,这意味着现在正在进行大量的字符串复制。此外,在开始时,需要使用字符串调用最终构造的解析器,因此所有std::cin
(或文件的合并内容)都将复制到字符串中。
看起来更好的主意(因为解析器只查看字符串当前前面的第一个(少数)字符),就是在标准输入流中跟踪你现在的位置。我相信这正是std::istream
的意思。但是,istreams不可复制。我的问题怎么解决?
有没有办法返回一个istream的副本,指向原始点所在的几个字符?或者是否有另一种更清洁的方法来解决这个问题?
答案 0 :(得分:1)
这个问题可以这样重写:你如何以避免过度复制并允许输入流的方式表示未解析部分的输入?
最灵活的方法是用迭代器表示它。如果解析器进行回溯,则需要ForwardIterator
,如果不是,InputIterator
就足够了。这意味着您可以直接使用std::istream_iterator
而不是std::cin
或std::ifstream
,或者从内存中的std::strings
或char
数组进行解析。使用回溯的流更复杂,需要您编写缓冲迭代器适配器,将InputIterator
转换为std::istream_iterator
或ForwardIterator
,或者编写直接包装std::ifstream
的迭代器,在你需要回溯时做.seekg()
。
另一种选择是使用C ++ 17的std::string_view
,它不会复制,并且具有一个很好的,解析友好的界面。虽然这不能解决流式传输问题,但您仍需要先读取整个文件。