我的編譯器 開篇

2021-03-31 21:06:12 字數 2254 閱讀 8233

引言

我在乙個資料庫專案的開發過程中,需要乙個窗體編輯器,待到有了乙個拙劣的實現之後,我突然發現我需要乙個直譯器!按照我自己的想法,我寫了一些**,但很快發現這不是乙個解決之道。我需要的是乙個真正的直譯器。於是我便開始進行文字分析方面的研究,在基礎的理論中,當我接觸到ebnf這個東西的時候,我驚喜的發現,我要找的東西就是這個了——只要實現了乙個ebnf的編譯器,就可以通過書寫ebnf**描述目標語言,從而生成目標語言的直譯器。進行了一段時間的使用後,發現yacc(乙個已有的生成分析器c的**的工具)的語法非常晦澀,讓我這個編譯器的新手感到非常不適。於是,我開始了建立自己的ebnf方言的路途。不斷地在黑暗中探索,並最終有了這篇文章所描述的一點成果。

簡要說明

自動分析工具用於編寫語言的分析器,用ebnf語言編寫2型語言的語法,然後通過自動分析工具生成相應的c**檔案(傳統的自動分析器工具大部分生成c**,這主要是因為大部分編譯器使用c/c++編寫),然後鏈入編譯器其它部分的源**,一同編譯,之後生成完整的編譯器。常見的自動分析工具有使用lr分析法的yacc和使用ll的lex,由於它們都生成c**,需要再次編譯,並且使用的ebnf的語法偏向於c的風格,對於專家級的編譯器製作人員,這也許並不成什麼問題,但是對於其他非編譯器製作者,要使用乙個直譯器或者乙個微型的編譯器,學習c風格的ebnf語法顯然比較費事,而vb的接近自然語言的語法則對於初學者有著非常大的吸引力。於是我就有了製作了這麼乙個接近vb語法的ebnf的編譯器/直譯器。使用更接近於自然語言的語法來降低對於編譯器/直譯器的製作難度。

首先讓我們來了解一下上面提到的ebnf的一些細節。ebnf是在老的bnf的基礎上進行一些擴充套件而成的,它相對於bnf則更接近於程式的邏輯,如迴圈、條件。bnf即backs-naur正規化,是由此二人提出的用於描述2型語言的一種形式語言。使用這種語言來編寫語法統一的語法說明檔案不僅有助於交流而且使構造乙個描述語言的語言成為了可能。而我們所要做的工作就是構造乙個這樣的編譯器,同時開發乙個使用它的編譯器,以證明其可用性。

由於yacc的語法非常晦澀,所以我並不打算使用它的語法,所以接下來我們就要定義乙個ebnf的方言來達到我們的目的。首先要考慮的問題就是語法。使用乙個什麼樣的語法?當然現在開始就定義乙個比較複雜的語言對於我們沒有任何好處,原因也是一樣的顯而易見:由於初期我們只能使用手工編碼的方式,乙個複雜的語法必然大大增加實現的複雜性,而語法檔案與ebnf編譯器到底是誰出的錯也將很難查詢,從而不如一開始就只定義乙個使用到大概所有ebnf編譯器的功能的語言,越簡單越好。由於主要是語法規則的問題,所以在簡單性上,加入開始符號和結束符號無疑是乙個很好的方法。當然語法接近vb將對學習此語言是很有幫助的。於是初期的想法當然就是:

section ***xx

rule ***=>....

end section

這種語法非常接近於vb,同時符號也非常明顯(例如推導符=>)。而且它的語法是遞迴的,對於構造這樣乙個編譯器也非常簡單。

這樣在掃瞄器(本章所指掃瞄器、分析器等均為ebnf編譯器的)遇到section的時候就可以開始取區段名,然後開始語法規則的分析工作。而對於語法規則,在使用回車還是分號作為邏輯行結束符的問題上,最初採用與vb一樣的回車作為結束符,但是在後來的使用中逐漸發現有些語法規則非常長,這樣如果使用回車作為邏輯行結束符會使乙個行變得非常長,而加入另外的換行符無疑將增加難度,於是在後繼版本(1.1~1.5)中,使用了分號作為邏輯行結束符,同樣帶來的問題就是空格不再是有效的元字元,而成為不折不扣的分隔符。

掃瞄器使用的是3型語言,分析器使用的是2型語言。既然2型語言可以描述3型語言能描述的所有的語言(具體為什麼可以參見編譯器的教科書),所以就不如直接使用2型語言來描述掃瞄器,只不過對使用作一些限制。這樣就能夠大大簡化實現方面的工作(閱讀**時就能夠體會到這些限制使得掃瞄器的構造充分利用了.***的類庫使**大幅簡化)——因此只需實現乙個2型語言的編譯器。

另外乙個不能忽視的設計問題就是,如何使用這個編譯器?將語法直接編譯成為原**?.***的程式集?還是編譯成為一種內部結構,然後通過序列化儲存成檔案?客觀上講,直接編譯成為.***的程式集是最好的,管理上方便,使用上速度也可能比較快。但是起決定作用的卻不是這一點,因為如果要編譯成為程式集的話需要將依此為驅動的掃瞄器和分析器都整合在其中。想一想,我們現在根本什麼也沒有!無法整合任何東西,我們還要它幹什麼?編譯為源**也有同樣的問題。於是最後的方案就是使用序列化的內部表示。使用時再反序列化為內部的表示,然後構造乙個通用的掃瞄器和分析器或者再加上乙個介面卡來使掃瞄器和分析器工作起來。而且語法規則和分析器/掃瞄器可以分別除錯,對於現在這種處於研究階段的專案來所也是非常合適的。

下面就是c3的定義及自描述,這是經過數次修改之後的1.4版(最初能用的那個版本稱為 1.0版)。

VC編譯器與GCC編譯器的區別

今天無意寫了一段 發現了vc編譯器與gun的gcc編譯器還是存在區別的。畢竟gcc支援的是標準c。include struct node int main 上述 在gcc下是編譯失敗的,提示的錯誤 uknown typename node 但是放到vc編譯器下則順利編譯通過。於是按照標準c寫了另外乙...

編譯方舟編譯器

環境 mac os parallels desktop 安裝ubuntu 16.04 安裝基礎包 sudo apt get y install openjdk 8 jdk git core gnupg flex bison gperf build essential zip curl zlib1g ...

方舟編譯器編譯

目錄環境變數 安裝 ninja 和 gn 編譯成功 總結2019.9.1 編譯華為方舟編譯器原始碼 這篇文章僅僅是關於如何搭建環境並進行編譯。本機環境 ubuntu 16 server.一定要好好看參考文件!建議使用root賬戶操作 先 clone 原始碼華為開源平台 對應的參考文件openarkc...