天天看點

<轉>lua解析腳本過程中的關鍵資料結構介紹

在這一篇文章中我先來介紹一下lua解析一個腳本檔案時要用到的一些關鍵的資料結構,為将來的一系列代碼分析打下一個良好的基礎。在整個過程中,比較重要的幾個源碼檔案分别是:llex.h,lparse.h、lobject.h和lopcode.h。

在llex.h中

Token代表了一個詞法單元,其中token表示詞法類型如TK_NAME、TK_NUMBER等如果不是這些類型則存放則詞素的字元表示,例如分析的代碼會這麼判斷詞素單元:

<a></a>

在Token中SemInfo存放了一些語義相關的一些内容資訊

其中當token是數字是内容存放在r中,其他情況存放在ts指向的TString中。

下面是最重要的一個資料結構之一

LexState不僅用于儲存目前的詞法分析狀态資訊,而且也儲存了整個編譯系統的全局狀态。current指向了目前字元,t存放了目前的toekn,lookahead存放了向前看的token,由此我認為lua應該是ll(1)的~哈哈(不知道對不對)。fs指向了parser目前解析的函數的一些相關的資訊,L指向了目前lua_State結構,z指向輸入流,buff指向了token buffer,其他的看注釋吧。

下面看看lparse.h檔案中的重要結構:

expdesc是存放了表達式的相關描述資訊,k是表達式的種類,u在不同的表達式中有不同的含義。

upvaldesc是存放了upval的相關描述資訊。

最後是本檔案中最重要的結構:

在編譯過程中,使用FuncState結構體來儲存一個函數編譯的狀态資料。其中,f指向了本函數的協定描述結構體,prev指向了其父函數的FuncState描述,因為在lua中可以在一個函數中定義另一個函數,是以當parse到一個函數的内部函數的定義時會new一個FuncState來描述内部函數,同時開始parse這個内部函數,将這個FuncState的prev指向其外部函數的FuncState,prev變量用來引用外圍函數的FuncState,使目前所有沒有分析完成的FuncState形成一個棧結構。bl指向目前parse的block,在一個函數中會有很多block代碼,lua會将這些同屬于同一個函數的block用連結清單串聯起來。jpc是一個OP_JMP指令的連結清單,因為lua是一遍過的parse,在開始的時候有一些跳轉指令不能決定其跳轉位置,是以jpc将這些pending jmp指令串聯起來,在以後能确定的時候回填,freereg為第一個空閑寄存器的下标,upvalues數組儲存了目前函數的所有upvalue,nactvar是目前作用域的局部變量數。

在lparse.c中定義了BlockCnt

Lua使用BlockCnt來儲存一個block的資料。與FuncState的分析方法類似,BlockCnt使用一個previous變量儲存外圍block的引用,形成一個棧結構。

&lt;轉&gt;lua解析腳本過程中的關鍵資料結構介紹

下面介紹一些在lobject.h檔案裡面的資料結構

結構體Proto是lua函數協定的描述,在lua解析腳本時首先會将main chunk代碼包裹為一個函數,用main proto描述,接着将裡面定義的内部函數一一用Proto結構體描述,将這些Proto的關系用樹來組合起來,例如有lua源碼檔案如下

則parse完成後會有如圖如下關系

&lt;轉&gt;lua解析腳本過程中的關鍵資料結構介紹

在Proto結構體中,k指向一個const變量數組,存放則函數要用到的常量;code指向lua parse過程中生成的本函數的instruction集合;p就是指向本函數内部定義的函數的那些proto;locvars指向本函數局部變量數組;upvalues指向本函數upvalue變量數組;nups為upvalue的數量;numparams為函數參數的數量;is_vararg表示函數是否接收可變參數;maxstacksize為函數stack的max大小。

在編譯期間lua使用Proto描述函數的,當lua vm開始運作vm時需要根據Proto生成相應的Closure來執行vm instructions。

Closure要麼代表了c函數,要麼為lua函數,在這裡我們隻看lua函數的LClosure

在LClousre中,p就是指向對應函數的Proto結構體啦,upvals顧名思義就是此closure的upvalue數組羅。在ClosureHeader宏中isC表示此closure是否是c函數,nupvalues為upvalue數目,env指向了此closue運作時的函數環境,在lua中可以用stefenv來改變目前函數的環境,就是改變env變量的指向啦。

最後,在檔案lopcode.h中定義了lua vm的指令結構

&lt;轉&gt;lua解析腳本過程中的關鍵資料結構介紹

下面是vm指令的一些定義與描述,我在相應vm指令的上方添加了一些注釋