QQ浏览器HD iOS 动态化/热修复方案QBDF解释器-语法制导翻译与递归子程序设计(编译原理)(5)简书被冻结-搬运】
原作時(shí)間:2019~2021年
此次共享,騰訊內(nèi)網(wǎng) / 外網(wǎng)同步發(fā)布。
內(nèi)部代碼地址:https://git.code.oa.com/fatboyli/QBDF
外部代碼地址:GitHub - ventureli/QBDF
兩年前的一個(gè)混淆包(無源碼):GitHub - ventureli/VLOCInterpreter
作者:騰訊fatboyli(李文強(qiáng))
終于說到了解釋器里最核心的部分了,語法制導(dǎo)翻譯與遞歸子程序設(shè)計(jì)。另外本章節(jié)和下一章節(jié)(中間代碼指令設(shè)計(jì)與實(shí)現(xiàn))的內(nèi)容交叉很多,建議兩個(gè)章節(jié)同步閱讀。語義解析其實(shí)有很多的方法。但是我覺得遞歸子程序這個(gè)是最簡單的最符合程序員邏輯的一種方式,雖然這種方法效率有點(diǎn)低,但是在真正的使用過程中,把QBDF-OC 編譯成為中間碼的過程可以離線的,并不一定要在客戶端做,所以這一步最重要的并不是效率。語法制導(dǎo)翻譯與遞歸子程序的我們可以這樣通俗理解:
參考BNF表達(dá)式,把文法翻譯成一個(gè)一個(gè)的子程序。每個(gè)子程序處理一個(gè)表達(dá)式。首先我們粗略的對比下 BNF表達(dá)式和表達(dá)式的翻譯的方法列表就能看出來。
這里我節(jié)選了一段 普通表達(dá)式的BNF.大家仔細(xì)的看下,就能發(fā)現(xiàn)子程序設(shè)計(jì)的妙處。
QBDF的BNF示意圖
這里大家注意紅色的部分。就是我說的表達(dá)式的左部分(‘:’左邊的部分),每一個(gè)左邊的定義,都會(huì)對應(yīng)一個(gè)方法。現(xiàn)在把QBDF的解釋器的方法列表截圖給大家看下。
QBDF解釋器的方法列表
可以看到,每一個(gè)BNF表達(dá)式的左邊都對應(yīng)一個(gè)方法。比如 EXP / Add /Condition 等。現(xiàn)在我們那一個(gè)例子來解析。
那么每一個(gè)子程序是如果工作的呢?我們拿一個(gè)簡單的方法做一個(gè)解析。
我們看下。這個(gè)表達(dá)式
exclusive_or_exp:? and_exp (‘^' and_exp)*
我們從這個(gè)里面可以看到,這個(gè)?exclusive_or_exp 被定義為一個(gè) and_exp 或者 and_exp^and_exp 或者?and_exp^and_exp?^and_exp 或者??and_exp^and_exp?^and_exp^....? ? 反正就是后面這個(gè)東西可以有很多個(gè)就是了。
那我們寫代碼的時(shí)候怎么處理這個(gè)事情?如果我們放棄編譯原理,BNF表達(dá)式這一大堆唬人的概念,其實(shí)這個(gè)表達(dá)式非常的簡單,隨便一個(gè)程序員都能寫出來。我們知道 and_exp 也是一個(gè)子程序,那么我們可以不用管and_exp 里怎么操作。我們只需要再需要他的地方調(diào)用就行了,剩下的其實(shí)就是匹配下'^' 這個(gè)字符和循環(huán)就可以了。
好了,現(xiàn)在我們看下代碼。
?-(NSDictionary *)_QBDF_EXP_EXCLUSIVE_OR{
? ? NSDictionary*leftNode = [self_QBDF_EXP_AND];
? ??if(_currentToken->tokenType == '^'? ?)? ? {
? ? ? ??int?type = _currentToken->tokenType;
? ? ? ? [self?match:'^'];
? ? ? ? NSDictionary*rightNode = [self?_QBDF_EXP_AND];
? ? ? ? NSMutableArray *operands = [NSMutableArray new];
? ? ? ? [operands addObject:leftNode];
? ? ? ? [operands addObject:rightNode];
? ? ? ??while?(_currentToken->tokenType == '^')? ? ? ? {
? ? ? ? ? ? [selfmatch:'^'];
? ? ? ? ? ? NSDictionary*newnode = [self_QBDF_EXP_AND];
? ? ? ? ? ? [operands addObject:newnode];
? ? ? ? }
? ? ? ? NSMutableDictionary*newRootNode = [self_createEXPOperatorNode:type left:operands right:nil?thridNode:nil];
? ? ? ??return?newRootNode;
? ? }else? ? {
? ? ??returnleftNode;
? ?}
}
這個(gè)代碼極其的簡單。我們首先讓我們的程序遞歸到左邊,去找and_exp 的返回值,and_exp 會(huì)把單詞;列表里他自己需要的那部分給吃掉。然后他遞歸出來后,我們就判斷當(dāng)前的單詞是否是‘^’ 如果是的話,那么我們根據(jù)BNF表達(dá)式知道了,我們當(dāng)前的至少是一個(gè) and_exp ^ and_exp 至于后面還有沒有 ,先不管,先調(diào)用[self?_QBDF_EXP_AND]; 拿到第二個(gè)操作數(shù),拿到后,開始循環(huán)判斷即可。
至于這段代碼
NSMutableDictionary*newRootNode = [self_createEXPOperatorNode:type left:operands right:nil?thridNode:nil];
?return?newRootNode;
還有這段代碼
? ? ? ?NSDictionary*rightNode = [self?_QBDF_EXP_AND];
? ? ? ? NSMutableArray *operands = [NSMutableArray new];
? ? ? ? [operands addObject:leftNode];
? ? ? ? [operands addObject:rightNode];
的含義,我們放到下一章節(jié)和指令設(shè)計(jì)這塊去處理。因?yàn)楸菊鹿?jié)和下一章是解釋器最核心的部分,本章節(jié)先介紹下,QBDF解釋器的程序設(shè)計(jì)結(jié)構(gòu)。
所以就像我前面章節(jié)說的。BNF真的很重要,寫代碼其實(shí)就是翻譯它的過程。
總結(jié)
以上是生活随笔為你收集整理的QQ浏览器HD iOS 动态化/热修复方案QBDF解释器-语法制导翻译与递归子程序设计(编译原理)(5)简书被冻结-搬运】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络周宏博课后题答案,关于计算机硬
- 下一篇: 2017年html5行业报告,云适配发布