编译原理课设---布尔表达式的LR翻译器

2024-02-10 00:20

本文主要是介绍编译原理课设---布尔表达式的LR翻译器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

布尔表达式的LR翻译器

1引言

编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。 编译原理是计算机专业设置的一门重要的专业课程这门课在理论、技术、方法上都对学生提供了系统而有效的训练,有利于提高软件人员的素质和能力。

所谓LR(K)分析,是指从左至右扫描和自底向上的语法分析,且在分析的每一步,只须根据分析栈当前已移进和归约出的全部文法符号,并至多再向前查看K个输入符号,就能确定相对于某一产生式左左部符号的句柄是否已在分析栈的顶部形成,从而也就可以确定当前所应采取的分析动作(是移进还是按某一产生式进行归约等)。

2需求分析

已知有如下的布尔表达式文法:

B ®B and T | T

               T®T or F | F

               F®notF|true|false |(B)|i rop i

利用LR分析法编制、调试其语法及语义分析程序,生成的中间代码为四元式。编制好分析程序后计若干用例,上机测试并通过所设计的分析程序。

布尔表达式的LR分析分为扩展文法,构造识别活动前缀的DFA图,判断有误冲突,若有冲突,则消除冲突和构造LR分析表等步骤。

l  首先要拓广文法:

非二义性文法如下:

   (0)  B’ ® B               

   (1)  B ® B and T

   (2)  B ® T

    (3)  T  ® T or F

     (4) T ® F

    (5)  F ® not F

(6)  F ®  ( B )

(7)  F ®  true

(8)  F ®  false

(9)  F ®  i rop i

l  构造识别活动前缀的DFA图

l  判断有无冲突

LR(0)分析时有移进—规约冲突,但冲突可以由SLR(1)分析解决。

l  构造LR分析表

 

状态

Si

ACTION

GOTO

and

or

not

true

false

(

)

i

rop

#

B

T

F

0

 

 

S4

S5

S6

S7

 

S8

 

 

1

2

3

1

S9

 

 

 

 

 

R2

 

 

ACC

 

 

 

2

R2

S10

 

 

 

 

R2

 

 

R2

 

 

 

3

R4

R4

 

 

 

 

R4

 

 

R4

 

 

 

4

 

 

S4

S5

S6

S7

 

S8

 

 

 

 

11

5

R7

R7

 

 

 

 

R7

 

 

R7

 

 

 

6

R8

R8

 

 

 

 

R8

 

 

R8

 

 

 

7

 

 

S4

S5

S6

S7

 

S8

 

 

12

2

3

8

 

 

 

 

 

 

 

 

S13

 

 

 

 

9

 

 

S4

S5

S6

S7

 

S8

 

 

 

14

3

10

 

 

S4

S5

S6

S7

 

S8

 

 

 

 

15

11

R5

R5

 

 

 

 

R5

 

 

R5

 

 

 

12

S9

 

 

 

 

 

S16

 

 

 

 

 

 

13

 

 

 

 

R3

 

 

S17

 

 

 

 

 

14

R1

S10

 

 

 

 

R1

 

 

R1

 

 

 

15

R3

R3

 

 

 

 

R3

 

 

R3

 

 

 

16

R6

R6

 

 

 

 

R6

 

 

R6

 

 

 

17

R9

R9

 

 

 

 

R9

 

 

R9

 

 

 

 

3总体设计及开发工具的选择

3.1设计分析

        编译器设计的编译程序涉及到编译五个阶段中的三个,即词法分析器、语法分析器和中间代码生成器。编译程序的输出结果为中间代码即逆波兰式。整个编译程序分为三部分:词法分析部分、语法分析处理及逆波兰式生成部分、输出显示部分。

        编译程序需要在单词级别上来分析和翻译源程序,所以首先要识别出单词,而词法分析部分的任务是:从左至右扫描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。因此,词法分析是编译的基础。执行词法分析的程序称为词法分析器。

语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。

语法分析中主要以二元式作为输入部分,所以输出显示部分的任务是将二元式通过LR分析表对语法分析处理过程进行控制,使逆波兰式翻译的工作有条不紊的进行,同时识别语法分析中的语法错误。

3.2设计原理

3.2.1词法分析

词法分析是编制一个读单词的过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。程序语言的单词符号一般分为五种:关键字(保留字/基本字)、标识符、常数、运算符、界限符。

词法分析的功能是输入源程序,输出单词符号。词法分析的单词符号常常表示成二元式(单词种别码,单词符号的属性值)。

词法分析器的设计方法有如下四个步骤:

1、写出该语言的词法规则。

2、把词法规则转换为相应的状态转换图。

3、把各转换图的初态连在一起,构成识别该语言的自动机。

4、设计扫描器;把扫描器作为语法分析的一个过程,当语法分析需要一个单词时,就调用扫描器。扫描器从初态出发,当识别一个单词后便进入终态,送出二元式

3.2.2语法分析

语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作.法分析的方法有多种多样,常用的方法有递归子程序方法、运算符优先数法、状态矩阵法、LL(K)方法和LR(K)方法。归纳起来,大体上可分为两大类,即自顶向下分析方法和自底向上分析方法. Syntax进行语法分析。对于语法分析,这里采用LR(1)分析法,判断程序是否满足规定的结构.构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

3.2.3中间代码生成

进入编译程序的第三阶段:中间代码产生阶段。为了使编译程序有较高的目标程序质量,或要求从编译程序逻辑结构上把与机器无关和与机器有关的工作明显的分开来时,许多编译程序都采用了某种复杂性介于源程序语言和机器语言之间的中间语言。常用的几种中间语言有: 逆波兰式、四元式、三元式、树表示。本课程设计主要实现逆波兰式的生成。

逆波兰式定义: 将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。

3.3开发工具

Windows环境下使用Visualstudio2012

4设计原则

算法是对问题求解过程的一种描述,是为解决一个或一类问题给出的一个确定的、有限长的操作序列。严格说来,一个算法必须满足以下五个重要特性:

l  有穷性:对于任意一组合法的输入值,在执行有穷步骤之后一定能结束。

l  确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,使算法的执行者或阅读者都能明确其含义及如何执行。并且在任何条件下,算法都只有一条执行路径。 

l  可行性:算法中的所有操作都必须足够基本,都可以通过已经实现的基本操作运算有限次实现之。

l  有输入:作为算法加工对象的量值,通常体现为算法中的一组变量。但有些算法的字面上可以没有输入,实际上已被嵌入算法之中。

l  有输出:它是一组与“输入”有确定关系的量值,是算法进行信息加工后得到的结果,这种确定关系即为算法的功能。

  在设计算法时,通常应考虑以下原则:首先说设计的算法必须是“正确的”,其次应有很好的“可读性”,还必须具有“健壮性”,最后应考虑所设计的算法具有“高效率与低存储量”。

  所谓算法是正确的,除了应该满足算法说明中写明的"功能"之外,应对各组典型的带有苛刻条件的输入数据得出正确的结果。在算法是正确的前提下,算法的可读性是摆在第一位的,这在当今大型软件需要多人合作完成的环境下是换重要的,另一方面,晦涩难读的程序易于隐藏错误而难以调试。算法的效率指的是算法的执行时间,算法的存储量指的是算法执行过程中所需最大存储空间。

算法是程序设计的另一个不可缺的要素,因此在讨论数据结构的同时免不了要讨论相应的算法。这里有两重意思,即算法中的操作步骤为有限个,且每个步骤都能在有限时间内完成。确定性表现在对算法中每一步的描述都没有二义性,只要输入相同,初始状态相同,则无论执行多少遍,所得结果都应该相同。

5数据结构与模块说明

5.1ACTION表和GOTO表

在程序中,我们使用两个二维数组存储SLR分析表,并初始化,初始化SLR表,其中action表中:100表示acc,除了100以外整数表示移进状态;负数表示用对应产生式进行规约。

int action[18][10]={ { 0   , 0   ,4  ,5    , 6   ,7  , 0   , 8   ,0   , 0},//0

                                  {9  , 0   ,0  ,0    ,0   ,0  ,-2   , 0   ,0   ,100},//1

                               {-2 ,10  ,0  ,0    , 0   ,0  ,-2   ,0   , 0   ,-2},//2

                                  {-4  ,-4   ,0  ,0    , 0   ,0  ,-4   , 0   ,0   , -4},//3

                                  {0  , 0   ,4  ,5    ,6   ,7  ,0   , 8   ,0   , 0},//4

                                  {-7  ,-7   ,0  ,0    , 0   ,0  ,-7   , 0   ,0   , -7},//5

                                  {-8  ,-8   ,0  ,0    , 0   ,0  ,-8   , 0   ,0   , -8},//6

                                  {0  , 0   ,4  ,5    ,6   ,7  ,0   , 8   ,0   , 0},//7

                                  {0  , 0   ,0  ,0    ,0   ,0  ,0   , 0   ,13  , 0},//8

                                  {0  , 0   ,4  ,5    ,6   ,7  ,0   , 8   ,0   , 0},//9

                                  {0  , 0   ,4  ,5    ,6   ,7  ,0   , 8   ,0   , 0},//10

                               {-5 ,-5   ,0  ,0    , 0   ,0  ,-5   ,0   , 0   ,-5},//11

                                  {9  , 0   ,0  ,0    ,0   ,0  ,16  , 0   , 0   , 0},//12

                                  {0  , 0   ,0  ,0    ,0   ,0  ,0   ,17  ,0   , 0},//13

                                  {-1  ,10  ,0  ,0    , 0   ,0  ,-1   , 0   ,0   , -1},//14

                                  {-3  ,-3   ,0  ,0    , 0   ,0  ,-3   , 0   ,0   , -3},//15

                                  {-6  ,-6   ,0  ,0    , 0   ,0  ,-6   , 0   ,0   , -6},//16

                                  {-9  ,-9   ,0  ,0    , 0   ,0  ,-9   , 0   ,0   , -9}};//17

int gotol[18][3]={  {1  ,2    , 3},{0   ,0    , 0},{0   ,0    , 0},{0   ,0    , 0},       {0   ,0    ,11},

                                  {0   ,0    , 0},{0   ,0    ,0},{12 ,2    ,3},{0   ,0    ,0},{0   ,14  , 3},

                                 {0   ,0    ,15},{0  ,0    , 0},{0   ,0    , 0},{0   ,0    , 0},{0   ,0    , 0},

                                  {0   ,0    ,0},{0   ,0    ,0},{0   ,0    ,0}};

5.2存储符号和产生式的数组

用三个数组来存储和符号以及产生式相关的信息:endls数组存储终结符、noends数组存储非终结符、products数组存储产生式信息。

//终结符集合

stringendls[10]={"and","or","not","true","false","(",")", "i","rop","#" };

//非终结符集合

stringnoends[3]={"B","T","F"};

//产生式集合

stringproducts[10]={"B","B and T", "T","T orF","F","not F","( B )","true","false","i rop i"};

5.3状态栈和符号栈

我们用类来模拟状态栈和符号栈。

这是状态栈:

      classstatestack

{

       private:

              int*base;//栈底指针

              int*top;//栈顶指针

              intsize;//栈内元素个数

              intstacksize;//栈的大小

       public:

              statestack()

              {

                     size=0;

                     stacksize=20;

                     base=newint[stacksize];;

                     top=base;     

              }

              intgetTop()//获取栈顶的元素。

              {

                     if(base==top)

                     {

                            return-1; 

                     }

                     else

                     {

                            return*(top-1);

                     }

              } 

              boolstatePush(int elem)//元素入栈

              {

                     ++size;

                     (*top)=elem;

                     ++top;

                     returntrue;

              }

              voidstatePop(int time)//元素出栈

              {

                     for(inti=0;i<time;i++)

                     {

                            --top;

                            --size;

                     }

              }

              voidprintState()//输出栈内的所有元素

              {

                     stringstr=" ";

                     int*pre;

                     for(pre=base;pre<top;pre++)

                     {

                            if(*pre>9)

                            {

                                   charch1=(*pre/10)+48;

                                   charch2=(*pre%10)+48;

                       str+=ch1;

                                   str+=ch2;

                            }

                            else

                            {

                    char ch=*pre+48;

                                str+=ch;

                            }           

                     }

                     cout<<setw(15)<<setiosflags(ios_base::left)<<str;

              }

};

这是符号栈:

    classsymbolstack

{

       private:

              string*base;

              string*top;

              intsize;

              intstacksize;

       public:

              symbolstack()

              {

                     size=0;

                     stacksize=20;

                     base=newstring[stacksize];;

                     top=base;

              }    

              stringgetTop()//获取栈顶的元素。

              {

                     if(base==top)

                     {

                            return" "; 

                     }

                     else

                     {

                            return*(top-1);

                     }

              } 

              //元素入栈

              boolsymbolPush(string elem)

              {

                     ++size;

                     *top=elem;

                     ++top;

                     returntrue;

              }

              //元素出栈

              voidsymbolPop(int time)

              {

                     for(inti=0;i<time;i++)

                     {

                            --top;

                            --size;

                     }

              }

              //输出栈内的所有元素

              voidprintSymbol()

              {

                     stringstr=" ";

                     string*pre;

                     for(pre=base;pre<top;pre++)

                     {

                      str+=*pre;

                     }

                     cout<<setw(15)<<setiosflags(ios_base::left)<<str;

              }

};

 

6算法设计

6.1词法分析算法描述

6.1.1词法分析流程图

6.1.2词法分析算法

     用该函数将布尔表达式分开,并存储在vector中。

//将字符串按空格分开,并存入vector中。

       vector<string> separatestrEX(stringstr)

       {

              vector<string> vec;

              int pos=0;

              for(int i=0;i<str.size();++i)

           {  

                     if(isspace(str[i]))//如果当前字符是空格

                     {

                            vec.push_back(str.substr(pos,i-pos));//复制起始位置为pos且长度为i-pos的字符串。

                            pos=i+1;

                     }

              }

              vec.push_back(str.substr(pos,str.size()-pos));

              return vec;

       }

6.2语法分析算法代码描述

6.2.1语法分析算法流程图

6.2.2语法分析算法

用actionGoto函数对每个符号进行分析:

void actionGoto(string str,string str1)

       {                   

                  int x=state.getTop();//当前栈顶状态

                     inty=strtoInt(str);//当前将要输入的字符

                     if(action[x][y]>0&&judgeSymbol(str)&&(str!="#"))//移进

                     {

                            printfInfoEX(step,state,symbol,str1,"移入"+str);

                            state.statePush(action[x][y]);

                            symbol.symbolPush(str);  

                            ++step;

                     }

                     if(action[x][y]<0&&judgeSymbol(str))//规约

                     {

                            intz=-action[x][y];//用-action[x][y]对应的产生式规约

                            stringlenstr=products[z];//生成需要规约的产生式

                            intn=calculatenum(lenstr);//计算产生式的长度,进行规约

                            intc=chooseNoEnds(z);

                            stringch=noends[c];//生成规约后的非终结符

                            createforchief(n,lenstr,ch);//生成四元式

                            printfInfoEX(step,state,symbol,str1,"规约"+noends[c]+"->"+products[z]);

                            state.statePop(n);

                            symbol.symbolPop(n);

                            intm=state.getTop();//获取规约后的栈顶状态

                            if(gotol[m][c]>0)

                            {

                                   intg=gotol[m][c];

                                   state.statePush(g);

                                   symbol.symbolPush(ch);

                            }

                ++step;

                            actionGoto(str,str1);

                     }

                     if((action[x][y]==100)&&(str=="#"))

                     {

                            printfInfoEX(step,state,symbol,str1,"分析完成");

                     }

       }

如下是strtoInt函数的代码:

//将终结符和非终结符转换为action和gotol表中对应的列号

       intstrtoInt(string str)

       {

              if(str=="and")

                     return0;

              if(str=="or")

                     return1;

              if(str=="not")

                     return2;

              if(str=="true")

                     return3;

              if(str=="false")

                     return4;

              if(str=="(")

                     return5;

              if(str==")")

                     return6;

              if(str=="i")

                     return7;

              if(str=="rop")

                     return8;

              if(str=="#")

                     return9;

              if(str=="B")

                     return0;

              if(str=="T")

                     return1;

              if(str=="F")

                     return2;

       }

如下是judgeSymbol函数的代码:

//判断字符是终结符还是非终结符

    booljudgeSymbol(string str)

    {

           for(int i = 0;i<10; i++)

           {

                  if(endls[i]==str)

                         returntrue;  

           }

                         returnfalse;

    }

如下是chooseNoEnds函数的代码:

//根据产生式选择非终结符

       intchooseNoEnds(int num)

       {

              if(num==1||num==2)

                     return0;//选择“B”

              if(num==3||num==4)

                     return1;//选择“T”

           return 2;//选择“F”

       }

如下是calculatenum函数的代码:

       //计算字符串中元素的个数

       intcalculatenum(string str)

       {

              intnum=0;

              for(inti=0;i<str.size();++i)

              {

                     if(isgraph(str[i]))

                            continue;

                     else

                     {

                            ++num;

                     }

              }

              ++num;

       return num;

       }    


6.3中间代码的生成

该函数负责生成中间代码:

//生成四元式

       voidcreateforchief(int num,string lenstr,string ch)

       {

              vector<string>strs=separatestrEX(lenstr);

              vector<string>::iteratoriter=strs.begin();

              stringstr=" ";

       string l1="(";

              stringl2=")";

              stringl3=",";

              if(num==1)

              {

                     stringl0="=";

                     stringarg1=*iter;

                     str=l1+l0+l3+arg1+l3+"_"+l3+ch+l2;

              }

              if(num==2)

              {

                     stringop=*iter;

                     stringarg1=*(iter+1);

                     str=l1+op+l3+arg1+l3+"_"+l3+ch+l2;

              }

              if(num==3)

              {

                     stringarg1=*iter;

                     stringop=*(iter+1);

                     stringarg2=*(iter+2);

                     if(arg1=="(")

                     {

                         string l0="=";

                            str=l1+l0+l3+op+l3+"_"+l3+ch+l2;

                     }

                     else

                     {

                            str=l1+op+l3+arg1+l3+arg2+l3+ch+l2;

                     }           

}

              fors.push_back(str);

       }

       //输出四元式

       voidprintForsInfo()

       {

              printInfo("中间代码四元式为");

              vector<string>::iteratorit=fors.begin();

              for(it;it<fors.end();it++)

              {

                     cout<<*it<<endl;

              }

       }

7软件调试

在整个编译器设计过程中,遇到了很多意想不到的困难,其主要原因是对各个部分要实现的功能考虑不够周全。通过反复查找资料,以及向同学请教,才得以完成。在布尔表达式翻译器的设计过程中,在语法分析器设计过程中,程序相当复杂,需要利用到大量的编译原理,以及数据结构中的相关算法。其中在分析表的构造时遇到了非常大的困难,对输入字符串的移进和归约冲突得不到很好的处理,造成了调试的困难。经过我的努力,通过多次调试,最终构造出来分析表并调试成功。

在调试的过程中,出现了如下的问题:

l  因为函数较多,所以在编程的过程中,多次将函数名写错。

l  因为在分析和翻译的过程中,关系较为复杂,所以多次搞混关系。

l  ACTION表计算错误。

l  进栈和出栈的元素关系弄错了。

    当然,错误不止这些,但从这次课设,我觉得自己在某些方面仍有所欠缺,从现在开始,我会继续呢里,在今后的学习中,必须多编写程序,使逻辑思维和动手能力有所提高,努力学好编程。

8软件的测试方法和结果

l 输入字符串为:i rop  i  #

 

l 输入字符串为:true or  false  and  (  i  rop  i  )  #

 


9源码展示

#include<iostream>
#include<string>
#include<vector>
#include<iomanip> 
using namespace std;//and	or	not	true false(	  )	  i	 rop   # int action[18][10]={ { 0	, 0	 ,4	,5	, 6	 ,7	, 0	, 8	, 0	,  0},//0{ 9	, 0	 ,0	,0	, 0	 ,0	,-2	, 0	, 0	,100},//1{-2	,10	 ,0	,0	, 0	 ,0	,-2	, 0	, 0	, -2},//2{-4	,-4	 ,0	,0	, 0	 ,0	,-4	, 0	, 0	, -4},//3{ 0	, 0	 ,4	,5	, 6	 ,7	, 0	, 8	, 0	,  0},//4{-7	,-7	 ,0	,0	, 0	 ,0	,-7	, 0	, 0	, -7},//5{-8	,-8	 ,0	,0	, 0	 ,0	,-8	, 0	, 0	, -8},//6{ 0	, 0	 ,4	,5	, 6	 ,7	, 0	, 8	, 0	,  0},//7{ 0	, 0	 ,0	,0	, 0	 ,0	, 0	, 0	,13	,  0},//8{ 0	, 0	 ,4	,5	, 6	 ,7	, 0	, 8	, 0	,  0},//9{ 0	, 0	 ,4	,5	, 6	 ,7	, 0	, 8	, 0	,  0},//10{-5	,-5	 ,0	,0	, 0	 ,0	,-5	, 0	, 0	, -5},//11{ 9	, 0	 ,0	,0	, 0	 ,0	,16	, 0	, 0	,  0},//12{ 0	, 0	 ,0	,0	, 0	 ,0	, 0	,17	, 0	,  0},//13{-1	,10  ,0	,0	, 0	 ,0	,-1	, 0	, 0	, -1},//14{-3	,-3	 ,0	,0	, 0	 ,0	,-3	, 0	, 0	, -3},//15{-6	,-6	 ,0	,0	, 0	 ,0	,-6	, 0	, 0	, -6},//16{-9	,-9	 ,0	,0	, 0	 ,0	,-9	, 0	, 0	, -9}};//17//B   T    Fint gotol[18][3]={   {1	,2	, 3},//0{0	,0	, 0},//1{0	,0	, 0},//2{0	,0	, 0},//3{0	,0	,11},//4{0	,0	, 0},//5{0	,0	, 0},//6{12	,2	, 3},//7{0	,0	, 0},//8{0	,14	, 3},//9{0	,0	,15},//10{0	,0	, 0},//11{0	,0	, 0},//12{0	,0	, 0},//13{0	,0	, 0},//14{0	,0	, 0},//15{0	,0	, 0},//16{0	,0	, 0}};//17//终结符集合
string endls[10]={"and","or","not","true","false", "(",")", "i","rop","#" };
//非终结符集合
string noends[3]={"B","T","F"};
//产生式集合
string products[10]={"B","B and T", "T","T or F","F","not F","( B )","true", "false","i rop i"};
//栈类
class statestack
{	private:int *base;//栈底指针int *top;//栈顶指针int size;//栈内元素个数int stacksize;//栈的大小public:statestack(){size=0;stacksize=20;base=new int[stacksize];;top=base;	}int getTop()//获取栈顶的元素。{if(base==top){return -1;  }else{return *(top-1);}}  bool statePush(int elem)//元素入栈{++size;(*top)=elem;++top;return true;}void statePop(int time)//元素出栈{for(int i=0;i<time;i++){--top;--size;}}void printState()//输出栈内的所有元素{string str=" ";int *pre;for(pre=base;pre<top;pre++){if(*pre>9){char ch1=(*pre/10)+48;char ch2=(*pre%10)+48;str+=ch1;str+=ch2;}else{char ch=*pre+48;str+=ch;}		}cout<<setw(15)<<setiosflags(ios_base::left)<<str;}
};class symbolstack
{private:string *base;string *top;int size;int stacksize;public:symbolstack(){size=0;stacksize=20;base=new string[stacksize];;top=base;}	string getTop()//获取栈顶的元素。{if(base==top){return " ";  }else{return *(top-1);}}  //元素入栈bool symbolPush(string elem){++size;*top=elem;++top;return true;}//元素出栈void symbolPop(int time){for(int i=0;i<time;i++){--top;--size;}}//输出栈内的所有元素void printSymbol(){string str=" ";string *pre;for(pre=base;pre<top;pre++){str+=*pre;}cout<<setw(15)<<setiosflags(ios_base::left)<<str;}
};class analyseLR
{
private:int step;string inputstr;//布尔表达式statestack state;//状态栈symbolstack symbol;//符号栈vector<string> fors;//四元式
public://构造函数analyseLR(){	step=0;inputstr=" ";state=statestack();symbol=symbolstack();}//初始化两个栈void initstack(){state.statePush(0);symbol.symbolPush("#");}//这是一个输出提示函数void printInfo(string str){cout<<str<<endl;}//这是两个输出提示函数的增强版void printInfoEX(string str1,string str2,string str3,string str4,string str5){cout<<setw(6)<<setiosflags(ios_base::left)<<str1;cout<<setw(15)<<setiosflags(ios_base::left)<<str2;cout<<setw(15)<<setiosflags(ios_base::left)<<str3;cout<<setw(24)<<setiosflags(ios_base::left)<<str4;cout<<setw(10)<<setiosflags(ios_base::left)<<str5<<endl;}void printfInfoEX(int str1,statestack state,symbolstack symbol,string str4,string str5){cout<<setw(5)<<setiosflags(ios_base::left)<<str1;state.printState();symbol.printSymbol();cout<<setw(25)<<setiosflags(ios_base::left)<<str4;cout<<setw(10)<<setiosflags(ios_base::left)<<str5<<endl;}//初始化界面函数void initstageInfo(){printInfo("布尔表达式的文法如下:");cout<<"(0)  B’-> B"<<endl;cout<<"(1)  B -> B and T"<<endl;cout<<"(2)  B -> T"<<endl;cout<<"(3)  T -> T or F"<<endl;cout<<"(4)  T -> F"<<endl;cout<<"(5)  F -> not F"<<endl;cout<<"(6)  F -> ( B )"<<endl;cout<<"(7)  F -> true"<<endl;cout<<"(8)  F -> false "<<endl;cout<<"(9)  F -> i rop i"<<endl;}//这是初始化布尔表达式的函数void initInputstr(){printInfo("请输入布尔表达式:");getline(cin,inputstr);}//将终结符和非终结符转换为action和gotol表中对应的列号int strtoInt(string str){if(str=="and")return 0;if(str=="or")return 1;if(str=="not")return 2;if(str=="true")return 3;if(str=="false")return 4;if(str=="(")return 5;if(str==")")return 6;if(str=="i")return 7;if(str=="rop")return 8;if(str=="#")return 9;if(str=="B")return 0;if(str=="T")return 1;if(str=="F")return 2;}//判断字符是终结符还是非终结符bool judgeSymbol(string str){for (int i = 0;i<10; i++){if(endls[i]==str)return true;	}return false;}//根据产生式选择非终结符int chooseNoEnds(int num){if(num==1||num==2)return 0;//选择“B”if(num==3||num==4)return 1;//选择“T”return 2;//选择“F”}//计算字符串中元素的个数int calculatenum(string str){int num=0;for(int i=0;i<str.size();++i){if(isgraph(str[i]))continue;else{++num;}}++num;return num;}	//将字符串按空格分开,并存入vector中。vector<string> separatestrEX(string str){vector<string> vec;int pos=0;for(int i=0;i<str.size();++i){   if(isspace(str[i]))//如果当前字符是空格{vec.push_back(str.substr(pos,i-pos));//复制起始位置为pos且长度为i-pos的字符串。pos=i+1;}}vec.push_back(str.substr(pos,str.size()-pos));return vec;}//将vector容器中的字符串连起来string linkVectorstr(vector<string> &vecs,vector<string>::iterator iter){string str=" ";vector<string>::iterator it;it=iter;for(it;it<vecs.end();it++){//cout<<*it; str+=*it;}return str;}//生成四元式void createforchief(int num,string lenstr,string ch){vector<string> strs=separatestrEX(lenstr);vector<string>::iterator iter=strs.begin();string str=" ";string l1="(";string l2=")";string l3=",";if(num==1){string l0="=";string arg1=*iter;str=l1+l0+l3+arg1+l3+"_"+l3+ch+l2;}if(num==2){string op=*iter;string arg1=*(iter+1);str=l1+op+l3+arg1+l3+"_"+l3+ch+l2;}if(num==3){string arg1=*iter;string op=*(iter+1);string arg2=*(iter+2);if(arg1=="("){string l0="=";str=l1+l0+l3+op+l3+"_"+l3+ch+l2;}else{str=l1+op+l3+arg1+l3+arg2+l3+ch+l2;}}fors.push_back(str);}//输出四元式void printForsInfo(){printInfo("中间代码四元式为");vector<string>::iterator it=fors.begin();for(it;it<fors.end();it++){cout<<*it<<endl;}}void Start()//开始函数.{initstageInfo();initstack();//初始化两个栈initInputstr();vector<string> vec=separatestrEX(inputstr);//分开布尔表达式vector<string>::iterator iter=vec.begin();printInfo("LR分析法的过程如下");printInfoEX("步骤","状态栈","符号栈","输入串","操作");//printfInfoEX(step,state,symbol,linkVectorstr(vec,iter),"开始");for(iter;iter!=vec.end();++iter)//依次遍历字符{                                                            string str1=linkVectorstr(vec,iter);actionGoto(*iter,str1);}printForsInfo();}//LR分析函数void actionGoto(string str,string str1){      		int x=state.getTop();//当前栈顶状态int y=strtoInt(str);//当前将要输入的字符if(action[x][y]>0&&judgeSymbol(str)&&(str!="#"))//移进{printfInfoEX(step,state,symbol,str1,"移入"+str);state.statePush(action[x][y]);symbol.symbolPush(str);	++step;}if(action[x][y]<0&&judgeSymbol(str))//规约{int z=-action[x][y];//用-action[x][y]对应的产生式规约string lenstr=products[z];//生成需要规约的产生式int n=calculatenum(lenstr);//计算产生式的长度,进行规约int c=chooseNoEnds(z);string ch=noends[c];//生成规约后的非终结符createforchief(n,lenstr,ch);//生成四元式printfInfoEX(step,state,symbol,str1,"规约"+noends[c]+"->"+products[z]);state.statePop(n);symbol.symbolPop(n);int m=state.getTop();//获取规约后的栈顶状态if(gotol[m][c]>0){int g=gotol[m][c];state.statePush(g);symbol.symbolPush(ch);}++step; actionGoto(str,str1);}if((action[x][y]==100)&&(str=="#")){printfInfoEX(step,state,symbol,str1,"分析完成");}}
};                    
int main()
{ analyseLR ana=analyseLR();ana.Start();									system("pause");return 0;                                                  
}


这篇关于编译原理课设---布尔表达式的LR翻译器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695690

相关文章

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类