2011-12-02 72 views
1

由於性能原因,我將C#庫移植到C++。在正常操作期間,這個庫需要解析大約150,000個數學表達式(認爲excel公式),平均長度小於150個字符。解析C++中許多小文本的最佳解析器生成器?

在C#版本中,我使用了GOLD解析器來生成解析代碼。它可以在一秒鐘內解析所有150'000個表情。

因爲我們在考慮擴展我們的語言,所以我認爲向C++的轉變可能是改變ANTLR的好機會。我已經將(簡單)語法移植到ANTLR上,並生成了C代碼。解析150'000個表達式需要12秒鐘,因爲對於每個表達式,我需要創建一個新的ANTL3_INPUT_STREAM,令牌流,詞法分析器和解析器 - 至少在3.4版中,沒有辦法重用它們。

我很感激有人可以給我一個推薦什麼使用,而不是 - 黃金當然是一個選項,雖然生成C++或C代碼似乎比C#品種複雜得多。我的語法是LALR和LL(1)兼容。最重要的問題是解析小輸入的性能。

+0

低至400毫秒(從12秒)與提升精神 - 感謝一堆! – user816098

+0

如果您使用VC++ 2010編譯器,也可以嘗試AX。 –

回答

9

我會嘗試boost :: spirit。它往往成績不理想快(甚至用於解析簡單的事情,像一個整數,它可以比C函數atoi http://alexott.blogspot.com/2010/01/boostspirit2-vs-atoi.html更快)

http://boost-spirit.com/home/

它有美好的東西:唯一的頭,所以依賴地獄,自由的許可證。

但是要警告學習曲線是困難的。它是現代C++(沒有指針,但有很多模板和編譯錯誤令人沮喪),所以來自C或C#,你可能不會很舒服。

+1

謝謝你和Matthieu M.提出了提升精神 - 儘管有複雜性警告(我沒有遇到任何挑戰,但我已經習慣了一些C++),但我仍會試一試。我希望避免編寫自己的解析器,因爲我們的語言中的更改或擴展將更容易與ANTLR或助力精神整合。 – user816098

1

而不是expr讓你語法識別sequence-of-expr

編輯:

有(野牛語法)而不是:

start: expr { process_expr ($1); } 
    ; 

有:

start: expr_seq ; 

expr_seq: expr   { process_expr ($1); } 
      | expr_seq expr { process_expr ($2); } 
      ; 
+1

不幸的是,這不是一個選項,因爲我需要解析的表達式主要依賴於以前的解析結果(它們來自一個更大的池並表示依賴關係鏈)。 – user816098

+1

@ user816098,表達式之間的依賴關係應該鼓勵'sequence-of-expr'方式。如果您有時間後期樣本輸入和期望的輸出,請。 – Kirill

+1

基里爾,想象一個擁有250億個單元格的excel電子表格。一個細胞可能依賴於5個其他細胞,而這些細胞又依賴於其他細胞等。通常,這個細胞鏈長150,000個細胞。由於這組單元格引用僅在解析過程中出現,因此如果不提供全部250億個表達式,就無法使用expr序列,這將無法生效。 – user816098

3

我已經看到了解析從升壓來的最佳表現。 Spirit.Qi使用元模板編程在C++中表達語法。儘管如此,這並不是因爲內心的微弱。

這將需要很好的隔離,包含解析器的文件的編譯時間將增加到幾秒(所以最好確保儘可能少的文件)。

4

如果要解析的語法很簡單,那麼您可以直接手動編寫解析器。

大多數解析器生成器被設計爲可以很容易地掀起一個工作解析器,因此執行時間經常受到影響。

2

如果您的表達式的語法很簡單,請考慮製作一個手寫遞歸下降解析器。它可以運行得非常快,給你的能力(足夠的關注)來報告很好,特別是語法錯誤。

你也可以使用bison,但我相信一個手寫的遞歸解析器可能會更快。

而且你可以用flex生成的詞法分析器來進行分析,並以遞歸下降的方式手動進行分析。

對於您的信息,GCC編譯器至少有C++ & C自己的遞歸下降解析器。它不再使用解析器生成器(如bisonANTLR)。

1

我寫過很多解析器,而手寫的遞歸下降就是我這樣做的。它們很容易編寫,非常適合。這就是說,如果速度是你所追求的,無論你寫什麼,都會有足夠的空間來加速它。 這些會讓你感到驚訝,因爲你可能想到的任何東西,你都已經完成了。

這裏是一個slide set顯示如何做到這一點。