而我們通常編寫的程序因此成爲一組文本。
「文本」這個詞在編譯器構造中並不是真正的常用術語(或者至少不是我以前聽說過的)。通常程序首先被翻譯成標記(它們基本上是該語言的「詞」¹),然後該序列被翻譯成語法樹。那棵樹可能會被進一步轉換,並最終被轉換成機器指令序列,這些指令組成編譯好的程序。
語言使用正則表達式來定義語法,即文本程序中的所有文本是否良好。
一種語言的語法描述了方案在結構上是有效還是無效(不考慮類型的錯誤和運行時錯誤,其被單獨處理)。你不能用正則表達式來做到這一點,因爲絕大多數語言都是不規則的,也就是說它們比正則表達式可以描述的要複雜得多。例如,你不能說使用正則表達式來表示「每個左括號都必須有一個右括號」。
正則表達式通常用於描述語言的標記。這就是說你可以說「語言中的標識符與正則表達式[a-zA-Z_][a-zA-Z0-9_]*
匹配,並且數字匹配正則表達式[0-9]+
」。
然後用語法描述這些令牌如何組合在一起形成一個完整的程序。
編譯器的前兩個步驟是詞法分析和解析。
通常,是的。
詞法分析將正則表達式轉換爲NFA/DFA,並處理程序文本,並驗證它們並將它們轉換爲令牌。
如果您使用詞法分析器生成器,那麼生成器會接收一大堆您給它的正則表達式並將它們轉換爲自動機,然後根據這些生成器生成代碼。生成的代碼是詞法分析器,它將獲取程序源並生成一系列令牌。
請注意,正則表達式和自動機之間的轉換髮生在生成器運行時,而不是作爲編譯器的一部分。如果你手動編寫詞法分析器,正則表達式和自動機之間不會發生任何轉換(除非可能在你的頭上)。
解析處理這些標記並檢查它們的語義。
號解析階段需要的令牌,並確保它們符合語言的語法。如果他們這樣做,它會根據語言的句法結構執行操作。通常這意味着構建一個語法樹。對於簡單的語言,也可以在解析器中直接進行語義分析(如類型檢查)和代碼生成。
如果你確實構建了一個語法樹,那麼隨後的階段就會遍歷那棵樹,這就是語言的語義發揮作用的地方。
另一個問題是,一個語言的定義是正則表達式,我們使用解析部分來驗證程序的語法?
語言的語法的的定義一般是給出一個語法,而不是一個正則表達式。正如我所說,正則表達式對此沒有足夠的表現力。我們使用解析來驗證給定的程序是否符合語言的語法(以及確定程序的語法結構)。
語言的定義由語言的語法定義和語義的定義組成。後者通常以文本形式提供。
¹在這裏我使用單詞「單詞」的口語意義,而不是它的語言理論意義。
真的有幫助的答案。謝謝。通過'正則表達式經常被用來描述一種語言的標記,你的意思是每個標記可以是一個正則表達式?這也是爲什麼在像ocamllex這樣的'lex'工具中,我們使用正則表達式來定義標記類型和每個構造函數? –
@JacksonTale我的意思是每個標記都有一個正則表達式,是的。我不會說令牌*是正則表達式。令牌是由詞法分析器生成的。如果你有'[0-9] + {IntegerLiteral(int_of_string(lexeme lexbuf)}'並且在輸入'42'上運行它,那麼令牌就是'IntegerLiteral 42'。 – sepp2k
現在明白了,謝謝。 –