令牌效率问题

时间:2011-01-19 13:03:14

标签: c++ parsing compiler-construction tokenize

我正在为项目编写一个编译器前端,我正在尝试理解什么是标记源代码的最佳方法。 我无法在两种方式中做出选择:

1)tokenizer读取所有令牌:

bool Parser::ReadAllTokens()
{
  Token token;
  while( m_Lexer->ReadToken( &token ) )
  {
    m_Tokens->push_back( token );
    token.Reset(); // reset the token values..
  }

  return !m_Tokens->empty();
}

然后解析阶段开始,在m _ Tokens列表上运行。通过这种方式,方法getNextToken(),peekNextToken()和ungetToken()通过迭代器相对容易实现,并且解析代码编写得很清楚(不会被getNextToken()破坏,即:

 getNextToken();
 useToken();
 getNextToken();
 peekNextToken();
 if( peeked is something )
  ungetToken();
 ..
 ..

2)解析阶段开始,并在需要时创建并使用令牌(代码似乎不那么清楚)

什么是最好的方法??为什么??和效率? 提前感谢您的答案

4 个答案:

答案 0 :(得分:3)

传统上,编译器构造类教您在解析时逐个读取令牌。原因在于,在那些日子里,记忆资源稀缺。您可以使用千字节,而不是今天的千兆字节。

话虽如此,我并不是建议您提前阅读所有令牌,然后从您的令牌列表中解析。输入是任意大小的。如果你占用太多内存,系统会变慢。由于看起来你在前瞻中只需要一个令牌,我一次从输入流中读取一个令牌。操作系统将为您缓冲和缓存输入流,因此对于大多数用途来说它足够快。

答案 1 :(得分:2)

最好使用Boost::Spirit之类的东西进行标记。为什么重新发明轮子?

答案 2 :(得分:2)

您的方法(1)通常是过度的 - 在解析之前不需要对整个文件进行标记。

一个好的方法是实现一个缓冲的标记化器,它将在列表中存储poke或unget的标记,并在“get”时使用该列表的元素,或者从文件中读取标记。 list变为空(la FILE *)。

答案 3 :(得分:1)

第一种方法更好,因为您可以在3个月后理解代码......