我已經爲我的編程語言(教育)創建了一個解釋器,現在我想進一步爲它創建一個編譯器。我知道這是非常艱苦的工作。爲Win32編寫編譯器的知識
我已經知道的是:
- 我需要翻譯我的輸入語言彙編
了很多,是不是?現在我不知道的是:
- 什麼彙編我需要創建Win32 PE可執行文件,例如,Visual Studio呢?
- 文件頭怎麼樣?
我不想使用MASM,但它似乎我必須。
- 如何將彙編器與我的編譯器結合?
我已經爲我的編程語言(教育)創建了一個解釋器,現在我想進一步爲它創建一個編譯器。我知道這是非常艱苦的工作。爲Win32編寫編譯器的知識
我已經知道的是:
了很多,是不是?現在我不知道的是:
我不想使用MASM,但它似乎我必須。
您並不嚴格需要將您的代碼轉換爲程序集;你可以將它翻譯成任何語言,該語言可以編譯爲本機可執行文件。
讓我們來看一個非常簡單的例子。假設我有一些毫無價值的虛構語言(以下稱爲Adder),其中輸入文件包含任意數量的行,每行包含空格分隔的整數列表。輸出是每行的總和。
所以對於輸入文件
1
1 2 3
200 50 6
輸出將
1
6
256
您可以在Ruby中的一行寫解釋的加法:
puts($_.split.map(&:to_i).inject(0, :+)) while gets
如果我想將輸入程序翻譯爲獨立的Ruby腳本,該怎麼辦? T'很簡單:
while line = gets
num = line.split.map(&:to_i).inject(0, :+)
puts "puts(#{num})"
end
輸出:
$ ruby adder2rb.rb nums.txt
puts(1)
puts(6)
puts(256)
$ ruby adder2rb.rb nums.txt | ruby -
1
6
256
好了,現在如果我們想這個翻譯的東西,實際上編譯爲本地可執行程序 - 比如,C?我們幾乎沒有任何改變:
puts '#include <stdio.h>'
puts 'int main() {'
while line = gets
num = line.split.map(&:to_i).inject(0, :+)
puts " printf(\"%ld\\n\", #{num}L);"
end
puts ' return 0;'
puts '}'
屆輸出:
$ ruby adder2c.rb nums.txt
#include <stdio.h>
int main() {
printf("%ld\n", 1L);
printf("%ld\n", 6L);
printf("%ld\n", 256L);
return 0;
}
$ ruby adder2c.rb nums.txt | tcc -
$ ./a.out
1
6
256
(這裏注意,tcc
是Tiny C Compiler,這可能是,如果你希望最終用戶能夠生成你的項目非常有用可執行文件)。
想翻譯爲另一種高級語言嗎?哈斯克爾呢?
$ cat adder2hs.rb
puts 'main = do'
while line = gets
num = line.split.map(&:to_i).inject(0, :+)
puts " print #{num}"
end
$ ruby adder2hs.rb nums.txt
main = do
print 1
print 6
print 256
$ ruby adder2hs.rb nums.txt | runghc
1
6
256
當然,具有多個構造的任何語言的代碼翻譯將比上述例子顯着更完整;但是,基本思想保持不變,您將擁有針對輸出語言的一般模板。
現在,如果您決定仍然真的想要生成程序集而不是高級代碼,那麼您並不侷限於那裏的單個實現。比直接裝配更容易轉化爲虛擬機的字節碼。 MSIL會爲您提供.NET可執行文件,或者您可以使用LLVM的代碼生成工具。如果Java更多,你可以發出JVM字節碼。一個稍微不太常見的選擇是Parrot。
在這些虛擬機中,只有AFAIK的LLVM纔會生成實際的本機可執行文件,但這可能不是您現在最關心的問題。
+1給答案! – jimsweb 2012-03-04 16:45:07
查看http://stackoverflow.com/questions/1669/learning-to-write-a-compiler – 2010-04-12 16:53:33