编译原理学习笔记(四)预测分析器(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。
至此预测分析器的内容大致结束,由于代码太长不适合贴出,只留下运行结果。
这里写图片描述
可以看出跟词法分析的结果类似,但不同的是每个数字都输出为词法单元标识,而不是具体值。每个词法单元所含的具体值是其一种属性,需要在制导翻译的过程中获得,并通过产生式的语义动作进行运算,得到翻译结果。

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