【编译原理】LR语法分析器的设计与实现

LR语法分析器的设计与实现

本文为当时编译原理实验作业,要求用设计的思想完成,小题大做,仅供参考

实验要求

实现功能

1)使用LR(1)分析方法构造识别活前缀的DFA;
2)构造文法的分析表(Action表和Goto表);
3)构造LR语法分析器的总控程序;
3)输入文法(语言语法结构的文法描述存储在文本文件中);
4)输出文法的项目集簇(标准输出设备);
5)输出识别活前缀的DFA(标准输出设备);
6)输出文法的Action表和Goto表(标准输出设备);
7)对给定的输入串(存储在文本文件中),输出其是否该文法正确句子的判断,并输出文本形式的分析过程。

输入输出

文件结构:
1)非终结符个数;
2)所有非终结符,空格分隔;
3)终结符个数;
4)所有终结符,空格分隔;
5)规则个数;
6)所有规则,每行一个规则,规则输入格式:左部,右部符号数,右部符号,空格分隔;
7)开始符号。
8)待分析的符号串。

样例

描述:

文法G =(VN,VT,P,S)其中:
	VN = { S', S }
	VT = { a, (, ) }
	P = { 	S' -> S
     		S -> ( S )
S -> a
}
	S = S’

输入:

4
S' S L R 

3
= * i

6
S' -> S
S -> L = R
S -> R
L -> * R 
L -> i
R -> L

S'

* i = i #

输出:

 CFG=(VN,VT,P,S)
  VN: S' S L R
  VT: = * i
  Production:
     0: S' -> S
     1: S -> L = R
     2: S -> R
     3: L -> * R
     4: L -> i
     5: R -> L
  StartSymbol: S'

[LR(1) item set cluster]
  I0 :
        S' -> . S, #
        S -> . L = R, #
        S -> . R, #
        L -> . * R, #
        L -> . * R, =
        L -> . i, #
        L -> . i, =
        R -> . L, #
  I1 :
        S' -> S ., #
  I2 :
        S -> L . = R, #
        R -> L ., #
  I3 :
        S -> R ., #
  I4 :
        L -> . * R, #
        L -> . * R, =
        L -> * . R, #
        L -> * . R, =
        L -> . i, #
        L -> . i, =
        R -> . L, #
        R -> . L, =
  I5 :
        L -> i ., #
        L -> i ., =
  I6 :
        L -> * R ., #
        L -> * R ., =
  I7 :
        R -> L ., #
        R -> L ., =
  I8 :
        S -> L = . R, #
        L -> . * R, #
        L -> . i, #
        R -> . L, #
  I9 :
        S -> L = R ., #
  I10:
        L -> . * R, #
        L -> * . R, #
        L -> . i, #
        R -> . L, #
  I11:
        L -> i ., #
  I12:
        R -> L ., #
  I13:
        L -> * R ., #

[LR(0) analytical table]
  Action:
         #    =    *    i
    0             s4   s5
    1  acc               
    2   r5   s8          
    3   r2               
    4             s4   s5
    5   r4   r4          
    6   r3   r3          
    7   r5   r5          
    8            s10  s11
    9   r1               
   10            s10  s11
   11   r4               
   12   r5               
   13   r3               
  Goto:
        S   L   R
    0   1   2   3
    1            
    2            
    3            
    4       7   6
    5            
    6            
    7            
    8      12   9
    9            
   10      12  13
   11            
   12            
   13            

文法是 LR(1) 文法!

[parsing]
栈顶         输入     查表 动作                                  注
------------+--------+----+-------------------------------------+-----------
  0 #        *        s4   进栈  4 *
  4 *        i        s5   进栈  5 i
  5 i        =        r4   出栈 1 个符号和状态  进栈  7 L        L -> i
  7 L        =        r5   出栈 1 个符号和状态  进栈  6 R        R -> L
  6 R        =        r3   出栈 2 个符号和状态  进栈  2 L        L -> * R
  2 L        =        s8   进栈  8 =
  8 =        i        s11  进栈 11 i
 11 i        #        r4   出栈 1 个符号和状态  进栈 12 L        L -> i
 12 L        #        r5   出栈 1 个符号和状态  进栈  9 R        R -> L
  9 R        #        r1   出栈 3 个符号和状态  进栈  1 S        S -> L = R
  1 S        #        acc  成功接收!
------------+--------+----+-------------------------------------+-----------
 end!

一、LR语法分析器问题定义

1.1 语法分析器定义

语法分析器(Parser)通常是作为编译器或解释器的组件出现的,它的作用是进行语法检查、并构建由输入的单词组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“单词”,并将单词流作为其输入。实际开发中,语法分析器可以手工编写,也可以使用工具(半)自动生成。

1.2 自上而下语法分析原理

(1)自上而下语法分析基本思想

  • 将输入符号按从左到右顺序依次移入文法符号的栈栈中,边移入边分析;
  • 当栈顶符号串形成某条规则右部时就进行一次归约,即用该规则左部非终结符替换相应规则右部符号串。重复这一过程直到整个输入串分析完毕。
  • 最终若栈中剩下句子右界符“#”和文法的开始符号,则所分析的输入符号串是文法的正确句子。否则,就不是的正确句子,报告错误。

(2)自上而下语法分析常用方法
LR(0)、LR(1)、SLR、LALR等。

二、LR语法分析器需求陈述

  • 使用LR(0)、LR(1)分析方法构造识别活前缀的DFA;
  • 构造文法的分析表(Action表和Goto表);
  • 构造LR语法分析器的总控程序;
  • 输入文法(语言语法结构的文法描述存储在文本文件中);
  • 输出文法的项目集簇(标准输出设备);
  • 输出识别活前缀的DFA(标准输出设备);
  • 输出文法的Action表和Goto表(标准输出设备);
  • 对给定的输入串(存储在文本文件中),输出其是否该文法正确句子的判断,并输出文本形式的分析过程。

三、LR语法分析器分析模型

3.1 LR语法分析器领域模型

3.1.1 确定LR法分析器类与对象

从语法分析器的问题定义中筛选出可能作为对象的候选对象。
根据编译程序使用的基本概念,将所有概念实体作为候选对象,下图是根据概念之间的组成关系总结出的所有候选对象。
在这里插入图片描述

3.1.2 绘制领域模型(对象模型)

生成对象模型的方法:

  • 对候选对象确定初步关联,筛选出必要关联和必要的类;
  • 确定各个对象的属性;
  • 绘制出各个类之间的联系。

初步的对象模型(领域模型):
在这里插入图片描述
3.2 LR语法分析器动态模型
3.2.1 编写系统状态脚本
以下给出了文法分析系统的正常和异常情况脚本
(1)文法分析系统正常情况脚本:
在这里插入图片描述

(2)文法分析系统异常情况脚本:
在这里插入图片描述

3.2.2绘制事件跟踪图

文法分析系统的主要事件有两个:
(1)文法处理事件:
用户通过文件或中端输入文法,文法系统接收后初始化文法进行文法分析,分析后生成预测分析表,最后将文法的组成信息和分析信息打印在终端上或输出在文件中。
在这里插入图片描述
(2)文法分析事件:
用户通过文件或中端输入待分析串,文法系统接收后初对照预测分析表进行文法分析,分析后生成移进归约序列,最后将字符串的文法分析信息打印在终端上或输出在文件中。
在这里插入图片描述

3.2.3 绘制状态图

状态图描绘事件与对象之间的关系。将事件跟踪图中两个事件整合绘制系统状态图如下:
在这里插入图片描述

3.3 LR语法分析器功能模型

3.3.1 绘制基本系统模型图

基本的系统模型图指明了目标系统的边界,绘制语法分析器基本系统模型图如下:
在这里插入图片描述

3.3.2 绘制功能级数据流图

把基本系统模型中单一的处理框分解成若干个处理框,以描述系统加工,变换数据的基本功能,得到以下LR文法分析系统的功能级数据流图:
在这里插入图片描述

3.3.3 用例建模

(1)用例文本
LR文法分析系统的使用者主要有两类:文法处理使用者、文法分析使用者;
文法处理分为LR0文法处理和LR1文法处理;
文法分析分为LR0文法分析和LR1文法处分析。

(2)LR文法分析用例图:
在这里插入图片描述

四、LR语法分析器设计模型

4.1 LR法分析器对象模型

4.1.1 完善对象模型

利用继承机制共享公共性质,对系统中的类加以组织:

  • 终结符和非终结符继承符号类
  • LR0文法类和LR1文法类及其相关的类继承LR文法及其相关的类。
4.1.2 绘制类图

在这里插入图片描述

4.2 主要算法

4.2.1 LR(0)项目集的闭包算法

LR0项目集闭包算法:

  • 输入:LR0项目集。
  • 输出:LR0项目集的闭包。
function CLOSURE (I)
begin
    J:= I;
    repeat for J 中的每个项目A →α·Bβ和规则 B→γ
        若 B→·γ不在 J 中 Do{
            将 B→·γ加到J中
        } until 再没有项目加到 J 中
 return J
end;
4.2.2 LR(1)项目集的闭包算法

LR1项目集闭包算法:

  • 输入:LR1项目集。
  • 输出:LR1项目集的闭包。
function CLOSURE (I)
begin
  J:= I;
 repeat for J 中的每个项目 A→α·Bβ,a和产生式 B→γ;
        α,β,γ∈V*;b∈FIRST(βa),
        若 B→·γ, b 不在 J 中
        Do {
            将 B→·γ, b 加到 J 中
        } until 再没有项目加到J中
 return J
end.
4.2.3 计算GO函数和LR0项目集规范族

计算GO函数和LR0项目集规范族算法:

  • 输入:LR0项目集。
  • 输出:GO函数和LR0项目集规范族。
C={I0 ,I1 , ... ,In }
procedure itemsets(G’);
begin C := { CLOSURE ({S’→·S})}
repeat
  for C 中每一项目集 I 和每一文法符号 x 
        do{
            if GO(I,x) 非空且不属于C
         then 把 GO(I,x) 放入 C 中
        }until C 不再增大
end;
4.2.4 计算GO函数和LR1项目集规范族

计算GO函数和LR1项目集规范族算法:

  • 输入:LR1项目集。
  • 输出:GO函数和LR1项目集规范族。
C={I0 ,I1 , ... ,In }
procedure itemsets(G’);
Begain
    C:={ Closure( {S′→·S,#}) };
    Repeat For C 中的每个项目集 I 和每个符号 X Do
        If Go(I,X)非空且不属于 C  
        Then 把 Go(I,X)加入 C 中
    Until C 不再增大
End
4.2.5 分析输入串

LR分析程序算法:

  • 输入:待分析符号串。
  • 输出:LR文法分析结果。
初始化,初始状态 S0 在分析栈栈顶;
输入串 W# 的第一个符号读入 a 中。
while (ACTION[S,a]!=acc) 
{
    if (ACTION[S,a]==Si)
    {
        将 Si 和 a 进栈,将下一个输入符号读入 a ;
    }
    else if (ACTION[S,a]==rj) 
    {
        用第 j 条规则 A→x 规约;
        将 |x|个状态和|a|个文法符号退栈;
        假设当前栈顶状态为 S’,将 A 和GOTO[S’,A]=S”进栈;
    }
    else if (ACTION[S,a]==ERROR) 
        error();
}

五、LR语法分析器系统实现

5.1 文法类及其子类的定义

5.1.1上下文无关文法类(基类)

在这里插入图片描述

5.1.2 LR0文法类(子类)

在这里插入图片描述

5.1.3LR1文法类(子类)

在这里插入图片描述

5.2 分析类的定义

5.2.1 文法分析类(父类)

在这里插入图片描述

5.2.2 LR分析类(子类)

在这里插入图片描述

六、系统测试

6.1测试主程序

在这里插入图片描述

6.2 测试数据及测试结果

6.2.1测试样例

测试样例一:
在这里插入图片描述
测试样例二:
在这里插入图片描述

6.2.2 测试结果

样例一分析结果如下:

*i=i#   分析过程:
[parsing]
栈顶         输入     查表 动作                                  注
------------+--------+----+-------------------------------------+------
 0 #            *      s2  进栈  2  *
 2 *            i      s3  进栈  3  i
 3 i            =      r4  出栈  1 个符号和状态 进栈:7  L       L -> i
 7 L            =      r5  出栈  1 个符号和状态 进栈:6  R       R -> L
 6 R            =      r3  出栈  2 个符号和状态 进栈:5  L       L -> * R
 5 L            =      s8  进栈  8  =
 8 =            i      s10 进栈  10 i
10 i            #      r4  出栈  1 个符号和状态 进栈:12 L       L -> i
12 L            #      r5  出栈  1 个符号和状态 进栈:11 R       R -> L
11 R            #      r1  出栈  3 个符号和状态 进栈:1  S       S -> L = R
 1 S            #      acc 成功接收!
------------+--------+----+-------------------------------------+------
 end!
文法分析正确!

在这里插入图片描述
样例二分析结果如下:

abab#   分析过程:
[parsing]
栈顶         输入     查表 动作                                  注
------------+--------+----+-------------------------------------+------
 0 #            a      s3  进栈  3  a
 3 a            b      s4  进栈  4  b
 4 b            a      r3  出栈  1 个符号和状态 进栈:8  B       B -> b
 8 B            a      r2  出栈  2 个符号和状态 进栈:2  B       B -> a B
 2 B            a      s6  进栈  6  a
 6 a            b      s7  进栈  7  b
 7 b            #      r3  出栈  1 个符号和状态 进栈:9  B       B -> b
 9 B            #      r2  出栈  2 个符号和状态 进栈:5  B       B -> a B
 5 B            #      r1  出栈  2 个符号和状态 进栈:1  S       S -> B B
 1 S            #      acc 成功接收!
------------+--------+----+-------------------------------------+------
 end!
文法分析正确!

在这里插入图片描述

附录(cpp源代码):

#include <bits/stdc++.h>
using namespace std;

// seta=seta U setb seta未改变返回值为false,否则为true
bool insertSet(set<string> &seta, set<string> setb)
{
    int asize = seta.size();
    for (auto i : setb)
    {
        seta.insert(i);
    }
    return seta.size() != asize;
}

struct Reflect
{
    int first;
    string sign;
    int next;
};

struct Formula
{
    string left;
    vector<string> right;
    Formula() {}
    Formula(string l, vector<string> r)
    {
        left = l;
        right = r;
    }
    bool operator<(Formula it) const //重载<,放入map.key
    {
        if (left != it.left)
            return (left < it.left);
        else
        {
            if (right.size() != it.right.size())
                return right.size() < it.right.size();
            else
            {
                for (int i = 0; i < right.size(); i++)
                {
                    if (right[i] != it.right[i])
                        return right[i] < it.right[i];
                }
            }
        }
        return false;
    }
    bool operator==(Formula f) const //重载==比较
    {
        return (left == f.left && right == f.right);
    }
};

struct item
{
    Formula formula;    //产生式
    int dot;            //点的位置,-1表示到达最后
    set<string> symbol; //展望串
    item() {}
    item(Formula f, int d)
    {
        formula = f;
        dot = d;
    }

    bool operator<(item it) const //重载<,放入set
    {
        if (symbol != it.symbol)
        {
            return symbol < it.symbol;
        }
        if (dot != it.dot)
            return dot < it.dot;
        return formula < it.formula;
    }
    bool operator==(item it) const //重载==比较
    {
        return (formula == it.formula && dot == it.dot && symbol == it.symbol);
    }
};

class CFG
{
protected:
    unordered_set<string> VT;     //终结符集
    unordered_set<string> VN;     //非终结符集
    string startSymbol;           //开始符号
    map<int, Formula> production; //产生式集

public:
    CFG() {}
    ~CFG() {}

    //是终结符
    bool isVT(string str)
    {
        return VT.find(str) != VT.end();
    }

    //是非终结符
    bool isVN(string str)
    {
        return VN.find(str) != VN.end();
    }

    string getStartSymbol()
    {
        return startSymbol;
    }
    void setStartSymbol(string str)
    {
        startSymbol = str;
    }
    unordered_set<string> getVT()
    {
        return VT;
    }
    void setVT(unordered_set<string> vt)
    {
        VT = vt;
    }
    unordered_set<string> getVN()
    {
        return VN;
    }
    void setVN(unordered_set<string> vn)
    {
        VN = vn;
    }
    map<int, Formula> getProduction()
    {
        return production;
    }
    void setProduction(map<int, Formula> pr)
    {
        production = pr;
    }

    //重载>>
    friend istream &operator>>(istream &in, CFG &cfg)
    {
        int num;
        in >> num;
        for (int i = 0; i < num; i++)
        {

            string s;
            in >> s;
            cfg.VN.insert(s);
        }
        in >> num;
        for (int i = 0; i < num; i++)
        {
            string s;
            in >> s;
            cfg.VT.insert(s);
        }
        in >> num;
        getchar();
        for (int i = 0; i < num; i++)
        {
            string str;
            string s;
            char ch;
            vector<string> vct;
            in >> s;
            in >> str;

            while (true)
            {
                ch = in.get();
                if (ch != ' ')
                    break;
                in >> str;
                vct.push_back(str);
            }
            Formula f(s, vct);
            cfg.production[i] = f;
        }
        string s;
        in >> s;
        cfg.setStartSymbol(s);

        return in;
    }
    //重载<<
    friend ostream &operator<<(ostream &os, CFG &cfg)
    {
        os << " CFG=(VN,VT,P,S)";
        os << "\n  VN:";
        for (auto i : cfg.VN)
        {
            os << ' ' << i;
        }
        os << "\n  VT:";
        for (auto i : cfg.VT)
        {
            os << ' ' << i;
        }
        os << "\n  Production:" << endl;
        for (auto pr : cfg.production)
        {
            os << "     " << pr.first << ':' << ' ' << pr.second.left << " ->";
            for (auto j : pr.second.right)
            {
                os << ' ' << j;
            }
            os << endl;
        }
        os << "  StartSymbol:";
        os << ' ' << cfg.startSymbol << endl;
        return os;
    }
};

class CFG_LR1 : public CFG
{
private:
    map<string, set<string>> firstSet; // first集
    map<int, set<item>> itemset;       //项目集
    vector<Reflect> GOfuction;         // GO映射
public:
    CFG_LR1();
    ~CFG_LR1();
    map<int, set<item>> getItemset();
    vector<Reflect> getGOfuction();
    //计算First集合
    void culculateFirstSet();
    //建立项目集
    void createItem();
    //输出项目集
    void outPutItem();
    //求闭包
    void Closure(set<item> &ist);
};

CFG_LR1::CFG_LR1() {}

CFG_LR1::~CFG_LR1() {}

vector<Reflect> CFG_LR1::getGOfuction()
{
    return GOfuction;
}

map<int, set<item>> CFG_LR1::getItemset()
{
    return itemset;
}

void CFG_LR1::culculateFirstSet()
{
    //初始化空集合
    set<string> us;
    for (auto i : getVN())
    {
        firstSet[i] = us;
    }
    //遍历表达式
    while (true)
    {
        bool changeFlag = false;
        for (auto pr : getProduction())
        {
            //如果X->ε,把ε加入first(X)
            if (pr.second.right[0] == "ε")
            {
                if (firstSet[pr.second.left].find("ε") != firstSet[pr.second.left].end())
                    continue;
                firstSet[pr.second.left].insert("ε");
                changeFlag = true;
            }
            else // X->Y1Y2...
            {
                for (int i = 0; i < pr.second.right.size(); i++)
                {
                    string symbol = pr.second.right[i];
                    if (getVT().find(symbol) != getVT().end())
                    {
                        if (firstSet[pr.second.left].find(symbol) != firstSet[pr.second.left].end())
                            break;
                        firstSet[pr.second.left].insert(symbol);
                        changeFlag = true;
                        break;
                    }
                    else
                    {
                        if (insertSet(firstSet[pr.second.left], firstSet[symbol]))
                            changeFlag = true;
                        if (firstSet[symbol].find("ε") == firstSet[symbol].end())
                        {
                            break;
                        }
                        else
                        {
                            if (i == pr.second.right.size() - 1) //最后一个非终结符含有ε
                            {
                                if (firstSet[pr.second.left].find("ε") != firstSet[pr.second.left].end())
                                    continue;
                                firstSet[pr.second.left].insert("ε");
                                changeFlag = true;
                            }
                        }
                    }
                }
            }
        }

        if (changeFlag == false)
            break;
    }
}

void CFG_LR1::createItem()
{
    //计算First集合
    culculateFirstSet();
    //项目编号
    int index = 0;
    //初始化符号集合
    unordered_set<string> sign = getVT();
    for (auto vn : getVN())
    {
        sign.insert(vn);
    }
    queue<int> deal; //项目集处理队列
    //开始项目入队列
    set<item> beginist;
    string start = getStartSymbol();
    for (auto pr : getProduction())
    {
        if (pr.second.left == start)
        {
            item i(pr.second, 0);
            i.symbol.insert("#");
            beginist.insert(i);
        }
    }
    Closure(beginist);
    itemset[index] = beginist;
    deal.push(index); //初始项目集编号入队
    index++;
    while (!deal.empty()) //处理队列不空
    {
        int num = deal.front();
        set<item> ist = itemset[num];
        //遍历符号
        for (auto v : sign)
        {
            set<item> st;
            for (auto it : ist)
            {
                if (it.dot != -1) //未到末尾
                {
                    if (it.formula.right[it.dot] == v) //下一个读入的符号是v
                    {
                        item i(it.formula, it.dot + 1);
                        if (i.dot >= i.formula.right.size())
                            i.dot = -1;
                        i.symbol = it.symbol;
                        st.insert(i);
                    }
                }
            }
            Closure(st);
            if (!st.empty())
            {
                int flag = -1;
                for (auto it : itemset)
                {
                    if (st == it.second)
                        flag = it.first;
                }

                if (flag == -1)
                {
                    itemset[index] = st;
                    Reflect r;
                    r.first = num;
                    r.sign = v;
                    r.next = index;
                    GOfuction.push_back(r);
                    deal.push(index);
                    index++;
                }
                else
                {
                    Reflect r;
                    r.first = num;
                    r.sign = v;
                    r.next = flag;
                    GOfuction.push_back(r);
                }
            }
        }
        deal.pop();
    }
}

void CFG_LR1::outPutItem()
{
    cout << "\n[LR(1) item set cluster]" << endl;
    for (auto it0 : itemset)
    {
        cout << "  I" << it0.first << ':' << endl;

        for (auto it1 : it0.second)
        {
            cout << "    ";
            cout << it1.formula.left << ' ' << "->";
            for (int i = 0; i < it1.formula.right.size(); i++)
            {
                if (i == it1.dot)
                {
                    cout << " .";
                }
                cout << ' ' << it1.formula.right[i];
            }
            if (it1.dot == -1)
                cout << " .";
            cout << " , ";
            for (auto s : it1.symbol)
            {
                cout << s << ' ';
            }
            cout << endl;
        }
    }
}

void CFG_LR1::Closure(set<item> &ist)
{
    queue<item> que; //处理队列
    for (auto it : ist)
    {
        que.push(it);
    }
    while (!que.empty())
    {
        item it = que.front();
        if (it.dot != -1)
        {
            // dot后面是非终结符
            string str = it.formula.right[it.dot];
            if (isVN(str))
            {
                for (auto pr : getProduction())
                {
                    if (pr.second.left == str)
                    {
                        item i(pr.second, 0);
                        //如果待归约符号后面为空
                        if (it.dot == it.formula.right.size() - 1)
                        {
                            i.symbol = it.symbol;
                        }
                        else //如果待归约符号后面不为空
                        {
                            string next = it.formula.right[it.dot + 1];
                            if (isVN(next))
                            {
                                if (firstSet[next].find("ε") == firstSet[next].end())
                                {
                                    i.symbol = firstSet[next];
                                }
                                else
                                {
                                    for (auto a : firstSet[next])
                                    {
                                        if (a != "ε")
                                            i.symbol.insert(a);
                                    }
                                }
                            }
                            else
                            {
                                i.symbol.insert(next);
                            }
                        }
                        que.push(i);
                        ist.insert(i);
                    }
                }
            }
        }
        que.pop();
    }
}

enum ActionState
{
    STATE,
    REVERSE,
    ACCEPT,
    ERROR,
};

struct action
{
    ActionState state;
    int num = -1;
};

class PredictTable
{
private:
    map<int, Formula> production; //产生式集
public:
    PredictTable(){};
    ~PredictTable(){};
    map<int, Formula> getProduction()
    {
        return production;
    }
    void setProduction(map<int, Formula> pr)
    {
        production = pr;
    }
    int getFormulaNum(Formula f)
    {
        for (auto pr : production)
        {
            if (pr.second == f)
                return pr.first;
        }
        return -1; //未找到返回-1
    }
};

class PredictTable_LR : public PredictTable
{
private:
    unordered_set<string> actionHeader; // action表头
    unordered_set<string> gotoheader;   // goto表头
    map<int, map<string, action>> table;

public:
    PredictTable_LR();
    PredictTable_LR(CFG_LR1 lr1);
    ~PredictTable_LR();
    unordered_set<string> getActionHeader();
    unordered_set<string> getGotoHeader();
    //分析程序
    bool analyse(vector<string> l);
    //重载<<输出分析表
    friend ostream &operator<<(ostream &os, PredictTable_LR &lrtable);
    //分析串
    bool analyse();
};

PredictTable_LR::PredictTable_LR() {}

PredictTable_LR::PredictTable_LR(CFG_LR1 lr1)
{
    //是否是LR1
    bool isLLR1 = true;
    //初始化产生式
    setProduction(lr1.getProduction());
    //初始化表头
    actionHeader = lr1.getVT();
    actionHeader.insert("#");
    for (auto vn : lr1.getVN())
    {
        if (vn != lr1.getStartSymbol())
        {
            gotoheader.insert(vn);
        }
    }

    // 初始化表格
    for (auto it : lr1.getItemset())
    {
        action a;
        a.state = ERROR;
        for (auto vt : actionHeader)
        {
            table[it.first][vt] = a;
        }
        for (auto vn : gotoheader)
        {
            table[it.first][vn] = a;
        }
    }
    // 赋值ACCET
    for (auto it : lr1.getItemset())
    {
        for (auto it0 : it.second)
        {
            if (it0.dot == -1 && it0.formula.left == lr1.getStartSymbol())
            {
                action i;
                i.state = ACCEPT;
                if (table[it.first]["#"].state != ERROR)
                {
                    isLLR1 = false;
                }
                table[it.first]["#"] = i;
            }
        }
    }
    //移进项
    for (auto g : lr1.getGOfuction())
    {
        action a;
        a.state = STATE;
        a.num = g.next;
        if (table[g.first][g.sign].state != ERROR)
        {
            isLLR1 = false;
        }
        table[g.first][g.sign] = a;
    }
    //归约项
    for (auto its : lr1.getItemset())
    {
        for (auto it : its.second)
        {
            if (it.dot == -1 && it.formula.left != lr1.getStartSymbol())
            {
                action a;
                a.state = REVERSE;
                a.num = getFormulaNum(it.formula);
                for (auto s : it.symbol)
                {
                    if (table[its.first][s].state != ERROR)
                    {
                        isLLR1 = false;
                    }
                    table[its.first][s] = a;
                }
            }
        }
    }

    if (isLLR1)
    {
        cout << "\n文法是 LR(1) 文法!\n";
    }
    else
    {
        cout << "\n文法不是 LR(1) 文法!\n";
    }
}

PredictTable_LR::~PredictTable_LR() {}

unordered_set<string> PredictTable_LR::getActionHeader()
{
    return actionHeader;
}

unordered_set<string> PredictTable_LR::getGotoHeader()
{
    return gotoheader;
}

bool PredictTable_LR::analyse()
{
    vector<string> l;
    string str;
    do
    {
        cin >> str;
        l.push_back(str);
    } while (str != "#");
    cout << endl;
    for (auto i : l)
    {
        cout << i;
    }
    cout << "   分析过程:" << endl;
    stack<int> st_state;
    stack<string> st_str;
    st_str.push("#");
    st_state.push(0);
    cout << "[parsing]" << endl;
    cout << "栈顶         输入     查表 动作";
    cout << "                                  注" << endl;
    cout << "------------+--------+----+";
    cout << "-------------------------------------+-----------" << endl;

    for (int i = 0; i < l.size(); i++)
    {
        string s = l[i];
        int top = st_state.top();
        action a = table[top][s];
        string str_top = st_str.top();
        cout << right << setw(2) << top << " " << str_top << "            ";
        cout << s << "      ";
        if (a.state == ERROR)
        {
            cout << "错误,分析终止。" << endl;
            return false;
        }
        else if (a.state == STATE)
        {
            cout << 's' << left << setw(2) << a.num << " ";
            st_str.push(s);
            st_state.push(a.num);
            cout << "进栈  " << left << setw(2) << a.num << ' ' << s << endl;
            continue;
        }
        else if (a.state == REVERSE)
        {
            cout << 'r' << left << setw(2) << a.num << " ";
            Formula f = getProduction()[a.num];
            cout << "出栈  " << left << setw(2) << f.right.size() << "个符号和状态";

            for (int k = 0; k < f.right.size(); k++)
            {
                st_str.pop();
                st_state.pop();
            }
            top = st_state.top();
            cout << " 进栈:";
            int x = table[top][f.left].num;
            if (x == -1)
            {
                cout << "错误,分析终止。" << endl;
                return false;
            }
            st_state.push(x);
            cout << left << setw(2) << x << ' ';
            st_str.push(f.left);
            cout << f.left << "       ";
            cout << f.left << " ->";
            for (auto i : f.right)
            {
                cout << ' ' << i;
            }
            i--;
            cout << endl;
        }
        else if (a.state == ACCEPT)
        {
            cout << "acc"
                 << " ";
            cout << "成功接收!" << endl;
            cout << "------------+--------+----+";
            cout << "-------------------------------------+-----------" << endl;
            cout << " end!" << endl;
            return true;
        }
    }

    return false;
}

ostream &operator<<(ostream &os, PredictTable_LR &lrtable)
{
    os << "\nLR(1)分析表" << endl;
    os << "  Action:" << endl;
    os << "      ";

    for (auto vt : lrtable.actionHeader)
    {
        os.setf(ios::left);
        os.width(6);
        os << vt;
    }
    os << endl;

    for (int i = 0; i < lrtable.table.size(); i++)
    {
        os.setf(ios::left);
        os.width(5);
        os << i << ':';
        for (auto ah : lrtable.actionHeader)
        {
            action a = lrtable.table[i][ah];
            if (a.state == ACCEPT)
            {
                os.setf(ios::left);
                os.width(6);
                os << "acc";
            }
            else if (a.state == REVERSE)
            {
                string s = "r" + to_string(a.num);
                os.setf(ios::left);
                os.width(6);
                os << s;
            }
            else if (a.state == STATE)
            {
                string s = "s" + to_string(a.num);
                os.setf(ios::left);
                os.width(6);
                os << s;
            }
            else
            {
                os << "      ";
            }
        }
        os << endl;
    }
    os << "\n  Goto:" << endl;
    os << "      ";
    for (auto gh : lrtable.gotoheader)
    {
        os.setf(ios::left);
        os.width(6);
        os << gh;
    }
    os << endl;
    for (int i = 0; i < lrtable.table.size(); i++)
    {
        os.setf(ios::left);
        os.width(5);
        os << i << ':';
        for (auto gh : lrtable.gotoheader)
        {
            action a = lrtable.table[i][gh];
            if (a.num != -1)
            {
                os.setf(ios::left);
                os.width(6);
                os << a.num;
            }
            else
            {
                os << "      ";
            }
        }
        os << endl;
    }
    return os;
}

int main()
{
    CFG_LR1 lr1;
    cin >> lr1;
    cout << lr1;
    lr1.createItem();
    lr1.outPutItem();
    PredictTable_LR lr1table(lr1);
    cout << lr1table;
    if (lr1table.analyse())
        cout << "文法分析正确!" << endl;
    else
        cout << "文法分析错误!" << endl;
    return 0;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BkbK-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值