Lua原始碼解析之一 lexical

2021-07-08 15:50:05 字數 1358 閱讀 6778

我們知道,任何高階一點的編譯器,在解析源**時,都需要進行詞法分析。而詞法分析的過程就是先識別token的乙個過程,總體來說,lua裡面的token大致分為:

1. 數字和字串

2. 特殊字元:包括運算子和括號

對於每一類token lua都有唯一的id與之對應,此id用int來表示,對於第2種型別,直接用該字元的ascii碼來表示,對於1,3兩類,則定義一組列舉,為了與第2種區別開,列舉從257開始。比如關鍵字break 對應 tk_break,do 對應 tk_do。

先來看看luax_next,它用來識別下乙個token,會呼叫 llex 函式,返回token type和seminfo。有了token,接下來就會分析一條條的語句。

乙個statementlist 的 production為: statlist -> ,下面先將乙個statement的grammer production列出:

stat =

以ifstat為例:

ifstat -> if exprstat then statlist end

exprstat -> subexpr

subexpr ->(******exp | unop subexpr)

******exp -> number | string | nil | true | false | ... | constructor | function body | suffixedexp */

說到這裡,似乎詞法分析很簡單,單論詞法分析,lua確實很簡單,但lua是解釋型的指令碼語言,實際在是一邊做詞法分析,一邊再做語義分析,同時根據語義分析結果,生成lua指令。也就是說,在詞法分析的同時,幹了很多事情。

具體來看看lua指令,乙個lua指令用乙個32位的整數來表示。其中6bit用於表示指令碼,8bit表示運算元a,9bit表示b,9bit表示c(這種做法在邏輯上有點類似彙編),運算元一般來說分幾種型別:

1) r(x): 表示該運算元在暫存器中

2) kst(x):表示該運算元在常量表中

3) rk(x):表示該運算元如果是常量的話,則表示2),否則表示1)

舉例:指令op_move,看**注釋為r(a) := r(b),這就表示將暫存器b的值賦值給暫存器a。

到這裡不禁要問,lua暫存器是個什麼概念?我們知道,對彙編來說,具體的暫存器是使用具體暫存器名字來指定的,例如mov ax, bx ...,而lua則由下標來指向暫存器。實質上r(x) = [base+x] ,其中base表示當前函式呼叫的乙個基位址。

lua解析是以function為單位來進行的,載入乙個檔案,可以看作是在乙個全域性的大函式裡面對檔案進行解析。那麼,最終生成的指令都會放在歸屬函式proto的opcodes陣列裡面。執行乙個函式的時候,vm直接取指令分析運算元,接著往下執行就可以了。

spark原始碼解析之一 整體概述

任務提交後,指令碼會啟動使用者程式 初始化sparkcontext完成,使用者程式暫停執行,啟動driver程式 driver向集群管理器註冊應用程式 集群管理器根據此任務的配置檔案分配executor並啟動 driver獲取所需資源的同時,driver繼續執行使用者main函式,spark查詢為懶...

LUA 原始碼閱讀筆記(一)

背景介紹 因為工作的需要,後台svr要能夠動態修改更新,使用c當然沒有問題,問題就在於修改原始碼後,需要重啟服務。所以就想到在c裡能夠嵌入一種指令碼,最好是和c無縫結合的。因此就想到使用到lua,lua的大名圈內人士應該早有耳聞,只不過一直沒有機會接觸。機緣巧合,有幸一見。俗話說得好,耳聞不如一見。...

lua 原始碼編譯

對於乙個開源工程,開始學習它的第一步自然是編譯工程。使用vc編譯lua,在網上已有許多介紹,但 紙上得來終覺淺 自己走一遍還是有必要的。步驟如下 2.開啟vc建立乙個solution,就叫lua.sln 3.建立乙個名為liblua的project lua庫 新增除lua.c和luac.c以外的所有...