LRWord下载.docx
《LRWord下载.docx》由会员分享,可在线阅读,更多相关《LRWord下载.docx(13页珍藏版)》请在冰豆网上搜索。
(1)若ACTION(sm,ai)为移进,且s=GOTO(sm,ai),则三元式变成:
(s0s1……sms,#X1X2……Xmai,ai+1……an#)
(2)若ACTION(sm,ai)={A→β},则按照产生式A→β进行规约。
此时三元式变为
(s0s1……sms,#X1X2……XmA,aiai+1……an#)
此处s=GOTO(Sm-r,A),r为β的长度,β=Xm-r+1……Xm。
(3)若ACTION(sm,ai)为“接受”,则三元式不再变化,变化过程终止,宣布分析成功。
(4)若ACTION(sm,ai)为“报错”,则三元式的变化过程终止,报告错误。
一个LR分析器的工作过程就是一步一步的变换三元式,直至执行“接受”或“报错”为止。
数据结构等
structBNFNODE//产生式节点
{
charLeft;
//产生式左部
charRight[MAX_DATA_LEN];
//产生式右部
intRLen;
//产生式右边长度
}m_Bnf[MAX_DATA_LEN];
enumACTIONTYPE//动作类别
Push,//移进
Sumup,//规约
Accept,//接受
Error//出错
};
structLR1TABLE
intnStatus;
//状态
charCurChar;
//当前符号
ACTIONTYPEActionType;
//动作类别
intnNextStatus;
//下一状态
}m_Lr1[MAX_DATA_LEN];
//清空链表
voidClearWords(WORDNODE*pHeader)
//增加结点
WORDNODE*AddNode(charc[],WORDNODE*pTail)
//c第0个字节为单词类别,第1个为逗号,第2个以后是值
//打印状态
voidPrintState(WORDNODE*pNode,intnBnfIndex)
boolLR1Analysis(WORDNODE*pHeader)
PushInt(0);
//初始化状态栈
InitCharStack();
PushChar('
#'
NULL);
//压入初始符号#
WORDNODE*T;
T=pHeader->
pNext;
//指向第一个单词
PrintState(T,-1);
//打印当前状态
intt=GetLR1Index(a,c);
//根据状态栈栈顶符号和单词对应的文法符号查询分析表
PushInt(m_Lr1[t].nNextStatus);
//压入分析表中的状态
PushChar(m_Lr1[t].CurChar,T);
//压入对应的文法符号
T=T->
//指向下一个单词
intnlen=m_Bnf[m_Lr1[t].nNextStatus].RLen;
//根据产生式索引取得产生式右部长度nLen;
ints=GetLR1Index(m,TopChar()->
cCur);
//根据状态栈栈顶状态和符号栈栈顶符号查询分析表,
//确定转移状态;
returnfalse;
//若转移状态存在,则压入状态栈;
若不存在则返回false
}//if(A==Sumup)
else
if(A==Accept)
returntrue;
//若动作类别为接受(Accept):
返回true
else
returnfalse;
//若查询不成功(返回-1),返回false
//读取文法
if(!
ReadBnfs())
printf("
读取产生式失败!
\n"
);
ClearWords(pHeader);
return0;
}
//读取LR
(1)分析表
ReadLR1())
读取LR
(1)分析表失败!
//语法分析
printf("
语法分析过程:
状态栈归约串输入串产生式\n"
if(LR1Analysis(pHeader))
语法分析成功!
else
语法分析失败!
ClearWords(pHeader);
getchar();
return0;
截图
词法分由于本程序的输入是文件输入的,而输入的文件是通过词法分析产生的,故而先附上词法分析的源代码和程序,而后在附上lr的源程序代码。
说明:
本次代码需要上次文法法分析代码生成的文件如a.txt作为输入,然后根据给定文法bnf.txt和LR1分析表lr1.lr1判断是否语法是否正确
析的源代码:
头文件
Chars.h
#if!
defined(AFX_CHARS_H__D2786D29_6773_4679_93E5_3FC3AF73385F__INCLUDED_)
#defineAFX_CHARS_H__D2786D29_6773_4679_93E5_3FC3AF73385F__INCLUDED_
/***********************************************
*字符类别判断
************************************************/
//c是否为英文字符或下划线
boolIsEnglishCharOr_(charc)
return((c>
='
a'
&
&
c<
z'
)
||(c>
A'
Z'
))
||(c=='
_'
//c是否为数字
boolIsNumChar(charc)
return(c>
0'
9'
//c是否为运算符
boolIsOperator(charc)
switch(c)
case'
+'
:
-'
*'
/'
('
)'
#endif
Stdafx.h
//stdafx.h:
includefileforstandardsystemincludefiles,
//orprojectspecificincludefilesthatareusedfrequently,but
//arechangedinfrequently
defined(AFX_STDAFX_H__780CBCE9_325B_45B9_ACD6_368471BF18B6__INCLUDED_)
#defineAFX_STDAFX_H__780CBCE9_325B_45B9_ACD6_368471BF18B6__INCLUDED_
#if_MSC_VER>
1000
#pragmaonce
#endif//_MSC_VER>
#defineWIN32_LEAN_AND_MEAN//Excluderarely-usedstufffromWindowsheaders
#include<
stdio.h>
//TODO:
referenceadditionalheadersyourprogramrequireshere
//{{AFX_INSERT_LOCATION}}
//MicrosoftVisualC++willinsertadditionaldeclarationsimmediatelybeforethepreviousline.
#endif//!
源文件
#include"
stdafx.h"
malloc.h>
memory.h>
Chars.h"
#defineMAX_DATA_LEN256//数据缓冲区长度
//wordtype
#defineWT_OPERATOR0//操作符
#defineWT_UINT1//非负整数
#defineWT_VARIABLE2//变量
structWORDNODE
unsignedshortbyType;
//类别
charValue[MAX_DATA_LEN];
//值
WORDNODE*pNext;
//下一结点
//预处理:
将多余空格去掉
voidPrefix(charc[])
for(inti=0,j=0;
j<
MAX_DATA_LEN&
c[j]!
\0'
;
j++)
if(c[j]!
'
c[i++]=c[j];
c[i]='
voidClear(WORDNODE*pHeader)
WORDNODE*pNode;
while(pHeader!
=NULL)
pNode=pHeader->
free(pHeader);
pHeader=pNode;
WORDNODE*AddNode(charc[],intnBegin,intnEnd,unsignedshortbyType,WORDNODE*pTail)
WORDNODE*pNode=(WORDNODE*)malloc(sizeof(WORDNODE));
pNode->
byType=byType;
pNext=NULL;
intnChars=nEnd-nBegin+1;
memcpy(pNode->
Value,&
c[nBegin],nChars);
Value[nChars]='
pTail->
pNext=pNode;
returnpNode;
//根据上一状态获取单词类别
unsignedshortGetWordType(intnStatus)
switch(nStatus)
case1:
returnWT_OPERATOR;
case2:
returnWT_UINT;
case3:
returnWT_VARIABLE;
return0xFF;
/***************************************
*函数功能:
识别一个单词
*入口参数:
c扫描缓冲区
*nCur扫描器指针
*pTail单词序列尾指针
*返回值:
识别出的单词指针,NULL表示出错
*****************************************/
WORDNODE*IdentifyOneWord(charc[],int&
nCur,WORDNODE*pTail)
intStatus;
intcur=nCur;
if(IsEnglishCharOr_(c[nCur]))
{Status=3;
while(IsEnglishCharOr_(c[nCur])||IsNumChar(c[nCur]))
nCur=nCur+1;
elseif(IsNumChar(c[nCur]))
Status=2;
while(IsNumChar(c[nCur]))
elseif(IsOperator(c[nCur]))
{nCur=nCur+1;
Status=1;
unsignedshortwordtype=GetWordType(Status);
intb=cur;
inte=nCur-1;
returnAddNode(c,b,e,wordtype,pTail);
//词法分析
WORDNODE*WordAnalysis(charc[])
//第一个结点作为头结点,不使用
WORDNODE*pHeader=(WORDNODE*)malloc(sizeof(WORDNODE));
pHeader->
WORDNODE*pTail=pHeader,*pNode=NULL;
for(intnCur=0;
c[nCur]!
)
//识别一个单词
pNode=IdentifyOneWord(c,nCur,pTail);
if(pNode==NULL)//出错
{
Clear(pHeader);
returnNULL;
}
//识别下一个单词
pTail=pNode;
returnpHeader;
boolSave(WORDNODE*pHeader)
//文件名
charFileName[256];
单词序列输出文件名(如a.txt):
scanf("
%s"
FileName);
//打开文件
FILE*f=fopen(FileName,"
w"
if(f==NULL)
//空出第一个结点
WORDNODE*pNode=pHeader->
//保存数据
while(pNode!
fprintf(f,"
%c,%s\n"
pNode->
byType+'
Value);
pNode=pNode->
//关闭文件
fclose(f);
returntrue;
//主函数
intmain(intargc,char*argv[])
//输入
charc[MAX_DATA_LEN];
请输入表达式:
gets(c);
//预处理
Prefix(c);
WORDNODE*pHeader=WordAnalysis(c);
if(pHeader==NULL)
\n词法分析错误!
//保存
Save(pHeader))
\n保存文件失败\n"
//清空数据
Clear(pHeader);
//完成
\n词法分析成功,并已保存到文件\n"
c);
按任意键退出\n"
词法分析的截图: