2010-01-05 21 views
1

我有一個有趣的問題。我需要分析源代碼並在編譯之前確定變量的類型。所以,反射不能使用!正則表達式來分析源代碼

只有五種類型:

double  x = 1.23; 
long  x = 3; 
string  s='Hello World!' 
bool  b=true 
object[]  A = [1, 1+2, 'Hello', s] 

的五言代碼示例:

for (i=0; i < 5; i++) 
{ 
    a=2; 
    b=4; 
    c=6; 
    tesstClass.Str = 'sss'; 
} 

我決定使用正則表達式來解決這個問題。

首先,我發現與所期望可變(與它的表達式)的代碼的所有件如下:

string pattern = variable + @"[\w.]*\s*[-*+/]?=\s*[\w\s+'*/-]*\s*;"; 
MatchCollection mc = Regex.Matches(code, pattern); 

其次,我分析使用5個正則表達式(每個類型)各匹配度:

string stringPattern = @"'[^'\r\n]*'"; //String; 
string doublePattern = @"\b[0-9]+\.[0-9]+\b"; //Double 
string longPattern = @"[-+]?\b\d+\b"; // Integer with a sign 
string boolPattern = @"\b(false|true)\b"; // Boolean 
string arrayPattern = @"\[([\w']*\s*,?\s*)*\]"; // Array 

我在正則表達式中很糟糕。所以我定義了一組非常簡單的r。表達式。你能幫我改進它們嗎?

+1

你有沒有想過使用反射來獲取變量的類型? – 2010-01-05 11:45:42

+0

是的,但我需要在競爭之前分析代碼。所以它只是一個簡單的文字。 – user101375 2010-01-05 11:48:12

+2

我想說反射對於源代碼檢查沒有多大幫助。 – stakx 2010-01-05 11:49:35

回答

1

這樣做的正常方式是讓你的程序的AST,然後只需搜索變量聲明你需要。 Gramars建議是產生這樣的AST的一個好方法。

但是,如果您需要即時分析程序,您不能使用此選項,因爲您的代碼可能有分析錯誤。在這種情況下,我感到你的痛苦...

你唯一的選擇是解析你的源代碼和正則表達式可能會有所幫助。

首先,我會用一個正則表達式類似這樣開始:

(double|long|string|bool|object)\s*(\[\s*\])?\s+(YOUR_VARIABLE_TOKEN) 

OBS:YOUR_VARIABLE_TOKEN丟失,因爲變量有一個關於它如何被構建爲每種語言強大和定義的規則。

我沒有測試這個正則表達式,它肯定不是完美的。這只是給你一個想法。

第二個,你將不得不驗證這些匹配與某些例外情況。例如:

  1. 聲明可能是一個字符串文字中:"bool a;"
  2. 聲明可能是在註釋裏:/* bool a; */

而且,這不是一個很奇怪的要求。 Eclipse在某些情況下也會進行這種評估,例如縮進。

雖然這並不是一件容易的事,特別是尋找那些異常情況。祝你好運。

+0

嗨,我想首先使用AST,但正如你所說,代碼沒有完成,它可能有一些解析錯誤。可能的解決方案是查找所有字符串(「blabla」或「bool a;」),並用一些標準文本(如「text」)替換它們。同樣的評論,他們可以被刪除。 – user101375 2010-01-05 12:29:26

2

你試圖做的事情對於正則表達式來說是非常困難的,尤其是當你支持字符串結構時。如果我這樣做會發生什麼情況:

a = 'b = 3;'; 

I.e.在這種情況下,您需要將正則表達式的字符串轉義。

在開始能夠執行任何有意義的分析之前,您確實需要對代碼執行正確的解析。

+0

根據我的正則表達式,這個變量是一個字符串和一個整數。 =)這就是我尋求幫助的原因。 – user101375 2010-01-05 12:04:29

+5

這就是爲什麼使用正則表達式是一個壞主意 - 要準確地轉義字符串會非常困難。儘管在技術上可能做到這一點,但正則表達式最終會看起來像一團糟! – Justin 2010-01-05 12:11:09

+0

可能的解決方案是查找所有字符串(「blabla」或「bool a;」),並用一些標準文本(如「text」)替換它們。 – user101375 2010-01-05 12:32:40

0

請勿使用正則表達式。你在做什麼是類型扣除,我猜你正在爲學校做。他們會希望你學習另一種方式,如邏輯統一。

你所依賴的種類總是明顯不同。如果將0或1分配給布爾值會怎麼樣?正則表達式不善於減少輸入。最好的情況是,您的程序將生成每種類型的標識符列表。有更好的方法。

如果您處於商業環境中,您的解決方案將完全不可擴展,無法維護,不可靠,並且實施起來很慢,就像您自己承認的那樣,這不是您的強項。

如果您不只是做家庭作業,您應該有權訪問這種語言的解析器。如果你不這樣做,你應該開始一個解析器生成器,比如Bison(或者任何風格)。

如果你正在做家庭作業,我強烈建議打這本書。


編輯:我忘了說什麼與野牛做:的vP。你有每個變量的數據結構。它應該包含一組可能的類型。說一個unsigned int,其中一位代表每種類型,enum type_bits { double_bit = 1, long_bit = 2, string_bit = 4, … };。首先將所有位設置爲1;即type_map = (type_bits) -1;。當您遇到每個操作時,請屏蔽與其不兼容的位。完成後,您將設置一些位數。如果有多個規則,則應用優先規則,如果沒有則生成錯誤。

1

準確找到什麼?

您是否只需要找到文字(常量)或整個聲明?這是確定使用表達式來查找文字,但它是一個稍微複雜解析整個代碼

給個機會文法

如果你要解析所有的代碼......鬥,你知道語法分析器?當我學習'語言理論'時,我們使用語法來解析代碼。您可以使用正則表達式爲標記(常量,保留字,符號等)定義基本分析器,並在所有結構中使用語法分析器。

Java選項是JavaCC。必須有.Net選項。

基本上,語法分析器可以解析複雜的結構(並具有「內存」)。 如果一個有限狀態自動機等價於一個正則表達式,一個帶有堆棧(它是內存)的FSA相當於一個語法。它具有更強大的處理能力。

2

我也懷疑正則表達式適合這個。

正如Kragen所示,有些情況下正則表達式會匹配某些源代碼片段,但它們會忽略源代碼位出現的上下文。這可能導致錯誤。雖然可能可能爲Kragen顯示的這種情況編寫更智能的正則表達式,但它們很快會變得非常複雜且難以閱讀/維護/理解,因爲它們必須考慮許多不同的可能情境。

我寧願使用解析器生成器(如Yacc或Bison)編寫解析器。但取決於源代碼的語言,這也可能非常棘手。

+0

...但沒有那麼棘手。我認爲解析器是理解輸入代碼結構並將其轉換爲對象樹表示的正確工具。接下來,你可以做任何你想要的。當然,必須仔細編輯語法以避免歧義。但沒關係。 – helios 2010-01-05 12:11:04

+0

是的,避免歧義是我的意思是「棘手」。 (曾閱讀過有關試圖爲C++實現解析器的人?:)但除此之外,在這種情況下,解析器生成器肯定會是一個合適的工具。 – stakx 2010-01-05 16:37:27

0

您是否嘗試過查看單聲道項目C#編譯器的源代碼,可能有一些您認爲有用的想法。

的svn合作的svn://anonsvn.mono-project.com/source/trunk/mcs

1

鑑於這是.NET,你可以考慮使用CodeDOM來正確解析它。

使用已有的C# CodeDOM provider通過使用Parse method來獲得源代碼的結構化表示,然後遍歷它。這使您可以創建一個幾乎適用於任何.NET語言的解決方案。

即使您說在編譯之前必須完成編譯,您也許可以使用臨時內存中編譯,然後您可以使用反射進行處理。 CodeDOM提供者也可以幫助你。