C語言解釋器實現基礎知識_第1頁
C語言解釋器實現基礎知識_第2頁
C語言解釋器實現基礎知識_第3頁
C語言解釋器實現基礎知識_第4頁
C語言解釋器實現基礎知識_第5頁
已閱讀5頁,還剩4頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、(一) 在寫CuteC文本編輯器的同時,為了使之有腳本執行能力。特意實現了一個簡易的C語言解釋器,所謂的解釋器,就是它是解析執行腳本文件的,并不產生可執行的目標代碼。它具備了C語言的幾乎全部的語法。隨著時間的推移,我打算把它作為一個獨立的項目來開發了。在這個過程中,自己也學到了不少的知識,所以也打算跟大家分享。寫這些東西,雖然是重復發明輪子的事,但也不至于是在浪費生命。程序員嘛,我總覺得應該是要理解我們每天所編譯出來的程序是怎么被執行,應該明白我們敲打的每行代碼的實際意義。 我打算寫一個系列的文章來說明這個解釋器的實現過程,其中對于編譯原理的理論知識不做太多的講解,一是不容易提高大家的積極性,

2、二是自己水平有限。所以我覺得大部分從例子出發,講解一個個目標的實現過程,大家慢慢體會,估計收獲會比較大。 通過這一系列的文章,大家應該可以學到以下的知識。 1.更深入的理解C的內部細節,對以后的開發總是有好處的。例如,你能很清楚C語言的類型定義,通過基本的類型為何能夠定義出無窮的各種類型。 2.了解表達式的解析,中間代碼的產生。這點非常有意思,了解了這點,可以用同樣的方法做很多事情,包括設計個計算器,解析復雜的配置文件,在軟件中解析命令等等。 3.對編譯器有一個感性的認識,雖然離寫出編譯器還比較遙遠,但對于語法解析,預編譯,理解的就比較深入了。現在很多軟件都有預編譯的模塊在里面,比如Pro*C

3、, GSoap等等。 4.我們產生的中間代碼其實已經非常接近匯編代碼,這對理解C的執行過程總是有好處的。 總之,曬曬自己的成果,怎么說也是我親親苦苦寫出來的,希望大家能找到點可以借鑒的東西吧代碼我還在努力的編寫,過一段時間再放出來一個初級的版本。如果工作忙,那估計就要再等一段時間了。 以前我發過上一個版本的解釋器,可以在 HYPERLINK /linxr/archive/2011/03/23/1992644.html 這篇文章中下載,不過我現在已經重寫了解釋器,所以要看結果可以先下載下來看看:)。(二)1.內存池 在一些小的程序里,沒什么必要添加內存管理模塊在里面。但是對于比較復雜的代碼,如果

4、需要很多的內存操作,那么加入自己的內存管理是有必要的。至少有一些好處:能夠加快內存的申請和釋放;能夠輕松的查找內存泄露問題;能夠對整個軟件的內存消耗做一個比較精確的統計;對以后的優化有很大的好處等等。所以,在我的解釋器里,我加入了一個簡單的內存管理模塊,仿造了內存池的做法。 主要思想是這樣的: a.記錄所有的申請的內存 b.當釋放內存時,記錄下來以供下次申請使用 c.申請內存時,可以直接使用前面釋放過的內存 為了達到以上的功能。我為申請內存的大小劃分粒度,例如:我得粒度這么安排16,32,64,128,.那么申請17個字節的大小時候,我會申請32個字節的大小。這樣子方便管理。并且為每個粒度創建

5、一個可用內存的雙向鏈表。申請內存時,就可直接從這些鏈表頭中申請(即將一個節點從鏈表頭移除,作為被申請的空間,并插入到在使用的鏈表中),內存的釋放則是一個想法的過程。這些的存儲結構如下所示: (圖1.1 內存池的存儲結構)typedef struct _pool_block int size; void * data; struct _pool_block * next; struct _pool_block * pre;pool_block_t;typedef struct _pool int num_all; int num_free; pool_block_t * list_all; po

6、ol_block_t * list_freePOOL_ATOM_NUM;pool_t;int pool_atom_tabPOOL_ATOM_NUM = 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, -1; 說明: a.內存的申請會按照pool_atom_tab數組中的大小對齊,比如申請10byte,那么,我會申請32byte. b.為每個粒度保存一個雙向鏈表,用于保存被釋放的內存。如果要申請的內存超過8192,那么我直接調用系統的malloc,釋放時,直接調用free. c.內存申請過程:到相應的粒度鏈表(list_free)中查看是否有可用內存

7、,如果有,直接將它從該list_free鏈表中移動到list_all鏈表。 d.內存釋放過程:要釋放的內存必定保存在list_all中,根據它的大小,把它移動到相應的list_free鏈表。 e.pool_block_t結構被放置在申請內存的前面,則在釋放時,直接根據Buffer指針就可得到pool_block_t的位置,從而得到next和pre,快速的在鏈表中移動。2.棧 棧在解釋器中用到的地方很多,不管是表達式的解析,還是代碼塊的解析,類型的解析,等等都用到了棧。所以不實現它是不可能的事,不過在數據結構中他是最簡單的了,無非就是申請一個空間,按一個一個的節點保存進去,按一個一個的節點取出來

8、。沒什么技巧在里面,只是這個我讓棧的大小空間是自動增長和減小的,這么做的目的是:棧的空間僅僅限制于內存的大小。但是,這么做得缺點是,當棧的空間大小自動變化時,棧內的數據要被復制一遍,這務必會影響效率。但沒有辦法,暫時之能這樣了。唯一的辦法是在時間和空間上做一個選擇。 棧的存儲結構如下: (圖1.2 棧的存儲結構)typedef struct _stack int item_len; int item_num; int stack_size; char *p;stack_t; 說明: item_len: 保存每個節點的長度 item_num: 棧中節點的個數 stack_size: 棧中可保存的

9、節點個數 p: 指向棧空間 a.當節點的個數item_num大于stack_size,那么必須重新申請空間,將原來的數據拷貝到新的空間。 b.當節點的個數減小到一定的數量時,可以重新申請小的數據空間,釋放原來大的空間。3.hash表 hash由于其快速的查找能力而著稱,但是它太浪費內存了,所以用得的比較少,僅僅是在函數的調用時被使用。因為函數的調用是頻繁的,如果從頭查找函數,那將浪費很多的時間。這里引入hash也是必要的。#define HH_TAB_SIZE128typedef struct _hh_node unsigned int hash, klen, dlen; void * key

10、; void * data; struct _hh_node *next;hh_node_t;typedef struct _hh_head unsigned int node_num; hh_node_t * node_list;hh_head_t;typedef struct _hh_hash hh_opts_t opts; hh_head_t tabsHH_TAB_SIZE;hh_hash_t;typedef struct _hh_opts int (*cmp_key)(void *key1, void *key2); unsigned int (*get_hash)(void *key

11、); void * (*new_key)(int); void * (*new_data)(int); void (*del_key)(void *key); void (*del_data)(void *data);hh_opts_t;(三)詞法分析是編譯原理中最容易理解的,就算沒有了解過編譯原理,也能寫出一個詞法分析器。我們不用理解正則表達式,不用理解狀態機原理,就可以輕松的完成詞法的分析。 這里首先介紹下自頂向下的解析過程,所謂的自頂向下,按我的理解,就是從一個大的集合解析到小的集合。例如:解析一個文件,那么進入文件,解析一個函數,進入一個函數,解析局部變量,解析表達式,進入表達式,解析

12、變量、常量等等,最終完成一個C文件的解析過程。整個過程,其實就是一個猜測的過程。但是這個過程中,我們必須依賴于文件中的每個詞(token),token可以看成是解析過程中的一個單位。 例如: 1. 關鍵詞有:int char double long for while . 2. 運算符有:+ - * / . 3. 數字常量:12 0 x34 3.45 4. 字符串 :hello . 等等. 那么我們必須實現一個函數get_token,執行這個函數,我們獲取文件中的一個token。例如現在一個C文件: int main(int agrc, char *argv ) return 0; 那么多次執行get_token,分別得到的token為: int main ( pos = prog;dcl_args(ty);break; dcl_pointers(ty); while(tok_top = 0) if( *tok_stacktok_top.token = ( )/左邊是( 繼續向右解析 token_pop();

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論