使用迭代器进行内存有效的词法分析

时间:2014-03-21 02:50:39

标签: c++ iterator

我一直试图设计一个不会在中间列表中累积令牌的词法分析器(用于编程语言)。这应该很简单,在C ++中,我认为这是迭代器的一个很好的用法(顺便说一句,我不是C ++的专家)。话虽这么说,我似乎无法找到一个令人满意的问题解决方案。这是我在迭代器上下文中提出的最合乎逻辑的事情:

enum class symbol {
  IDENTIFIER,
  ...
};
struct token {
  symbol symbol;
  std::string::const_iterator lexeme_begin;
  std::string::const_iterator lexeme_end;
};
class lexer {
private:
  std::string::const_iterator begin_, end_;
public:
  lexer(
      std::string::const_iterator begin,
      std::string::const_iterator end) :
      begin_ {begin}, end_ {end} {};
  class iterator;
  iterator begin() {
    return {begin_, end_};
  }
  iterator end() {
    // Can't figure out what to do here.
  }
};
class lexer::iterator {
private:
  std::string::const_iterator begin_, end_, next_;
public:
  iterator(
      std::string::const_iterator begin,
      std::string::const_iterator end) :
      begin_ {begin}, end_ {end} {};
  iterator operator++() {
    if (_next == _end) {
      // Same problem as in lexer::end.
    }
    _begin = _next;
    return *this;
  }
  token operator*() {
    // Perform actual lexical analysis here.
  }
};

我希望能够做到这样的事情:

for (auto token : lexer {"abc 123"}) {
  std::cout << token;
}

我的问题是:这是否适当地使用了迭代器,如果是这样,我将如何处理lexer::end()迭代器。我能想到实现lexer::end()的唯一方法是返回lexer::iterator的特殊实例,但这对我来说似乎不是一个好的解决方案。困扰我的另一件事是每个迭代器必须包含与字符串末尾相同的迭代器,尽管这似乎不是一个问题。

2 个答案:

答案 0 :(得分:0)

是的,它看起来像是使用迭代器的合理位置。我没有看到像这样构建的词法分析器,但它看起来似乎有道理。

对我来说,没有人反对将lexer的一个杰出实例作为end()的值。词法分析器通常很方便返回源代码中不存在的EOF标记,并且实际上是end()的值。很可能是一个静止的。

我真的不明白为什么你需要一个类和一个嵌套类来表达基本的标记化逻辑。你在这里向我们展示的内容是缺少关于实际交付令牌的所有有趣内容,并且对于简单的tokeniser和迭代器支持来说似乎有些过分。

我猜测你的开始/结束/下一个迭代器是为了指向一个字符串的目的,所以我不理解each iterator has to contain the same iterator to the end of the string

答案 1 :(得分:0)

我最终没有使用自定义界面而不是迭代器来实现我的词法分析器。我的困惑是我使用的是C ++迭代器,好像它是一个生成器http://en.wikipedia.org/wiki/Generator_(computer_programming)。对于简单的输入解析,标准库提供输入流(http://en.cppreference.com/w/cpp/io),但是为了更强大的解析,我建议使用解析库,例如boost的精神,或者只是编写自己的自定义接口。