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