lr分析器实验报告分析Word格式文档下载.docx
《lr分析器实验报告分析Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《lr分析器实验报告分析Word格式文档下载.docx(11页珍藏版)》请在冰豆网上搜索。
姓名,学号,班级
(2)输入一以#结束的符号串(包括+—*/()i#):
在此位置输入符号串
(3)输出过程如下:
步骤
状态栈
符号栈
剩余输入串
动作
1
#
i+i*i#
移进
(4)输入符号串为非法符号串(或者为合法符号串)
备注:
(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;
如果为匹配终结符则写明匹配的终结符;
如分析异常出错则写为“分析出错”;
若成功结束则写为“分析成功”。
(2)在此位置输入符号串为用户自行输入的符号串。
原理:
LR分析方法是已知的最一般的无回溯移进-归约方法,它能够和其他移进-归约方法一样有效地实现。
同时利用数据结构中堆栈的性质,来分析一个具体的句型。
步骤:
分析一个LR
(1)文法的产生式。
正确无误的构造一个LR
(1)的项目集。
根据LR
(1)的项目集构建LR
(1)分析表。
针对具体句型进行实例分析。
关键技术分析:
LR
(1)文法中只有三个动作:
移进,规约和接受,这三个动作也是通过查表得来的额,任何时候如果都是唯一确定这三个动作中的一个,我们就可以让LR
(1)文法正确的运行。
首先需要构建项目集,才能根据项目集的状态转换构建分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
而分析器的动作就是由栈顶状态和当前输入符号所决定。
流程图:
代码:
#include<
iostream>
stack>
string>
usingnamespacestd;
stringaction[12][6]={
"
S5"
"
0"
S4"
//ACTION表
"
S6"
acc"
r2"
S7"
r4"
r6"
S11"
r1"
r3"
r5"
};
intgotoarr[12][3]={1,2,3,//GOTO表
0,0,0,
8,2,3,
0,9,3,
0,0,10,
0,0,0};
charvt[6]={'
i'
'
+'
*'
('
)'
#'
//存放终结符
charvn[3]={'
E'
T'
F'
//存放非终结符
stringProduction[6]={"
E->
E+T"
T"
T->
T*F"
F"
F->
(E)"
i"
//产生式集合
intcount=0;
//记录当前进行处理的输入字符串字符位置
intline=1;
//记录处理的步骤数
boolflag=false;
intStatusNumber=1;
//栈中状态数
stringstacktd="
#"
;
//记录符号栈中内容
intStatus[50]={0};
//记录状态栈
stack<
char>
Stack;
//创建一个符号栈
int>
status;
//创建一个状态栈
voidJudge(int&
i,intj,chararr[],charch,strings){//判断输入串是否由文法终结符组成
flag=false;
for(intl=0;
l<
j;
l++)
{
if(ch==arr[l])
{
flag=true;
i=l;
break;
}
}
if(flag==false)
cout<
<
"
\tError"
endl;
count=s.size();
}
voidOutputstatus()
{
//输出状态集
for(inti=0;
i<
StatusNumber;
i++)
Status[i];
voidOutputstring(strings)
//输出未处理的字符串
for(inti=count;
s.size();
s.at(i);
voidOutput(strings)
//输出步骤、状态集、符号集、输入串
cout<
line<
\t"
Outputstatus();
stacktd<
Outputstring(s);
\t\t"
line++;
voidShift(inti,strings)
{//移进函数S
Output(s);
ACTION["
status.top()<
s.at(count)<
]=S"
状态"
入栈"
status.push(i);
//将状态i压进状态栈
Status[StatusNumber]=i;
//Status记录状态栈的内容
Stack.push(s.at(count));
//将当前面临的输入串符号压进符号栈
stacktd=stacktd+s.at(count);
//stacktd记录符号栈的内容
count++;
//当前面临的输入串字符往后移一位
StatusNumber++;
//状态数加一
voidGoto(stack<
st1,stack<
st2,strings)
{//GoTo语句
intj=-1;
intch1=st1.top();
charch2=st2.top();
Judge(j,3,vn,ch2,s);
//求得ch2在非终结符表中的位置
if(gotoarr[ch1][j]==0)
else
status.push(gotoarr[ch1][j]);
//新状态进栈
Status[StatusNumber]=gotoarr[ch1][j];
StatusNumber++;
}
voidReduction(inti,strings)
{//归约函数R
r"
:
Production[i-1]<
归约,GoTo("
intN=Production[i-1].length()-3;
for(intj=0;
j<
N;
j++)
{//消除要归约的状态及符号
status.pop();
Stack.pop();
StatusNumber--;
stacktd.erase(stacktd.length()-1);
Production[i-1].at(0)<
)="
Stack.push(Production[i-1].at(0));
//符号进栈
stacktd=stacktd+Stack.top();
Goto(status,Stack,s);
Status[StatusNumber]=status.top();
voidAnalyse(strings)
{//具体分析函数
Stack.push('
);
//初始化
status.push(0);
s=s+"
intt=-1;
//记录ch在数组vt的位置
while(count<
s.size())
inti=status.top();
charch=s.at(count);
Judge(t,6,vt,ch,s);
if(flag==true)
if(action[i][t]!
="
&
action[i][t]!
{
if(action[i][t].at(0)=='
S'
{
action[i][t].erase(0,1);
//删除action[i][t]的首字母S
Shift(atoi(action[i][t].c_str()),s);
//atoi(action[i][t].c_str()),将action[i][t]转换为整型
action[i][t].insert(0,"
S"
//将S添加回action[i][t]
}
elseif(action[i][t].at(0)=='
r'
){
//删除action[i][t]的首字母r
Reduction(atoi(action[i][t].c_str()),s);
//将r添加回action[i][t]
}
elseif(action[i][t]=="
cout<
break;
Output(s);
\t分析成功"
elseif(flag==false)
intmain()
{
strings;
************************LR
(1)分析*************************"
本分析文法产生式为"
6;
j++)
Production[j]<
charT;
do
输入字符串"
cin>
>
s;
//输入要分析的字符串
************************现进行如下分析*************************"
步骤"
状态栈"
符号栈"
剩余输入串"
动作说明"