2011-01-19 99 views
4

我正在爲一個項目編寫一個編譯器前端,我試圖理解什麼是標記源代碼的最佳方法。 我不能兩種方式之間進行選擇:Tokenizer效率問題

1)分詞器讀取的所有令牌:

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)解析階段開始,並在需要的時候,在創建和使用令牌(代碼似乎不是那麼清楚)

什麼是最好的方法?爲什麼??和效率? 在此先感謝您的答案

回答

3

傳統上,編譯器構造類將教會您在解析時逐個讀取令牌。原因是,在那些日子裏,內存資源非常稀少。你有你的處置千字節,而不是今天你做的千兆字節。儘管如此,我並不是故意建議您事先閱讀所有的令牌,然後從令牌列表中解析出來。輸入具有任意大小。如果你的內存太多,系統會變慢。由於它看起來只需要一個令牌,所以我一次只能從輸入流中讀取一個令牌。操作系統會爲你緩衝和緩存輸入流,所以它對於大多數目的來說足夠快。

2

最好使用類似Boost::Spirit這樣的標記。爲什麼重新發明輪子?

+2

因爲它適用於考試:P – Salv0 2011-01-19 13:30:27

1

第一種方法是更好的,你可以接着也明白3個月後...(1)一般矯枉過正

+0

實際解析器幾乎沒有差異,詞法分析器稍微複雜一些。輕微。對於任何程序員來說,使用緩衝流不應該是一個謎,因此peek()(或者任何你的流機制的首選名字)應該很容易記住,甚至幾年之後...... – 2011-01-19 18:04:06

2

你的方法的代碼 - 它不需要來標記整個文件之前解析它。

一個好的方法是實現一個緩衝的標記器,它將存儲在列表中的戳記或未存取的標記,以及在獲取或從文件中讀取標記時使用該列表的元素該列表變空(a FILE *)。