編譯原理學習筆記(四)預測分析器(2)

上次說到了驅動表,這裏給出利用驅動表進行預測分析的算法實現(原書僞碼見p144)

syn_unit end(0);//結束符
syn_unit start(mode, mesh_table[mode]->src.lex, 0, syn_unit::NONTERMINATOR);//mode爲開始符號的參數
stack<syn_unit> stk;
stk.push(end);
stk.push(start);
int pos = 0;
auto lx_unit = lex->getNextToken(code, pos);//讀入第一個詞法單元
while (stk.top() != end && pos < code.length()){
    auto&cur_sig = stk.top();
    switch (cur_sig.type){//符號類型
    case syn_unit::LEX:
        if (lx_unit->compare(cur_sig.token)){//匹配
            output(lx_unit->token);//處理匹配結果
            stk.pop();
        }
        else{//失配 嘗試別的?
            report("不匹配的類型:"+lx_unit->token);
        }
        lx_unit = lex->getNextToken(code, pos);//匹配後才後移
        break;
    case syn_unit::NONTERMINATOR:
        auto&prod = mesh_table[cur_sig.token];//獲取產生式組
        if (prod->drivetable.find(lx_unit) != prod->drivetable.end()){//該單詞在驅動表中
            stk.pop();
            auto&dst = prod->dst[prod->drivetable[lx_unit]];//選擇產生式
            for (auto&var = dst.rbegin(); var != dst.rend(); var++)
                stk.push(*var);//展開並逆序壓入棧
        }
        break;
    }
}

驅動表是是一個二維數組,其行和列分別用產生式頭(非終結符)和當前詞法單元(終結符)爲索引,構造這個表需要每個產生式的FIRST集合以及FOLLOW集合,每個產生式組(各個產生式以‘|’分割開來)的FIRST集合是互不相交的(LL(1)文法的要求),因此根據FIRST集合中的終結符可以確定產生式,但這不是唯一確定,因爲FIRST集合中可能有空符ε的存在,如果ε存在,則需要查看其FOLLOW集合,將FOLLOW集合中含有該詞法單元的產生式添加到表中。
上次的結構中沒有FOLLOW集合,大致說一下FOLLOW集合的構成。舉個例子:A->ABc,其中A B爲非終結符,c爲終結符,A的FOLOW集合在這個產生式中就是FIRST(B)的內容,如果FIRST(B)含有ε,那麼還需要添加c。
至此預測分析器的內容大致結束,由於代碼太長不適合貼出,只留下運行結果。
這裏寫圖片描述
可以看出跟詞法分析的結果類似,但不同的是每個數字都輸出爲詞法單元標識,而不是具體值。每個詞法單元所含的具體值是其一種屬性,需要在制導翻譯的過程中獲得,並通過產生式的語義動作進行運算,得到翻譯結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章