算符优先分析器设计实验报告--宁剑

合集下载

实验三_算符优先分析算法的设计与实现

实验三_算符优先分析算法的设计与实现

实验三 算符优先分析算法的设计与实现(8学时)一、 实验目的根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。

通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。

二、 实验要求1、输入文法。

可以是如下算术表达式的文法(你可以根据需要适当改变):E→E+T|E-T|TT→T*F|T/F|FF→(E)|i2、对给定表达式进行分析,输出表达式正确与否的判断。

程序输入/输出示例:输入:1+2;输出:正确输入:(1+2)/3+4-(5+6/7);输出:正确输入:((1-2)/3+4输出:错误输入:1+2-3+(*4/5)输出:错误三、实验步骤1、参考数据结构char *VN=0,*VT=0;//非终结符和终结符数组char firstvt[N][N],lastvt[N][N],table[N][N];typedef struct //符号对(P,a){char Vn;char Vt;} VN_VT;typedef struct //栈{VN_VT *top;VN_VT *bollow;int size;}stack;2、根据文法求FIRSTVT集和LASTVT集给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。

算符描述如下:/*求 FirstVT 集的算法*/PROCEDURE insert(P,a);IF not F[P,a] thenbeginF[P,a] = true; //(P,a)进栈end;Procedure FirstVT;Beginfor 对每个非终结符 P和终结符 a doF[P,a] = falsefor 对每个形如 P a…或 P→Qa…的产生式 doInsert(P,a)while stack 非空begin栈顶项出栈,记为(Q,a)for 对每条形如 P→Q…的产生式 doinsert(P,a)end;end.同理,可构造计算LASTVT的算法。

二语法分析程序(算符优先分析法)

二语法分析程序(算符优先分析法)

实验二语法分析程序(算符优先分析法)一、实验目的通过设计调试算符优先分析程序,加深对课堂教学的理解,深刻理解自底向上语法分析方法的归约过程,提高语法分析方法的实践能力。

二、实验要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。

(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。

(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。

实验二--语法分析(算符优先)-(2)

实验二--语法分析(算符优先)-(2)

实验二--语法分析(算符优先)-(2)编译原理实验报告实验名称:语法分析器设计专业:计算机科学与技术姓名:田莉莉学号:201117906语法分析—算符优先分析程序一.实验要求⑴选择最有代表性的语法分析方法,如算符优先法、递归子程序法或LR 分析法⑵选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。

⑶实习时间为6学时。

二.实验内容及要求(1)根据给定文法,先求出FirstVt和LastVt 集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4)分析的句子为:(i+i)*i和i+i)*i三.程序设计思想及实现步骤程序的设计思想:按照编译原理教材提供的算法,本程序的设计主要实现三个主要的过程:(1)求解FristVT集和LastVT集:利用CString数组存放VT集,利用数组下标对应非终结符关系;(2)输出算符优先分析表:利用MFC中的ClistCtrl控件输出显示算符表,比利用二维数组对应其在内存中的关系。

(3)利用算符优先分析表进行归约:根据教材所给算法,并对其进行实现在屏幕上输出归约过程。

实现步骤:1、为程序各变量设计存储形式,具体设计如下所示:CString m_strTElem[T_LEN]; //终结符CString m_strNTElem[NT_LEN]; //非终结符CMapStringToPtr m_mapProdu; //存放产生式CMapStringToPtr m_mapProduEX; //存放扩展产生式CString m_strFristVT[NT_LEN]; //fristVT集CString m_strLastVT[NT_LEN]; //lastVT集int m_nPriSheet[T_LEN+1][T_LEN+1];//优先表;无穷表示空白,-1表示小于,0表示相等,1表示于Find m_F[STACK_LEN]; //bool数组CStrack m_stack; //堆栈2、为程序设计各个过程,具体设计如下所示:void CreateFristVT(Find* F); //为每一个非终建FristVT集void CreateLastVT(Find* F); //为每一个非终建LastVT集void SearchPForFirtVT(Find& f); //搜索形如P-P->Qa…. 的产生式void SearchQForFristVT(void); //搜索形如P->..生式void SearchPForLastVT(Find& f); //搜索形如P-> P->...a的产生式void SearchQForLastVT(void); //搜索形如P->..生式OnBnClickedBtnAnasysic(); //点击按钮启动3、对各个过程进行实现;4、调试运行并检验实验结果,结果如图2.1和2.2所示:图2.1 分析成功图图2.2 分析失败图四.程序源码产生式初始化://产生式CString* str = new CString; *str = _T("|E+T|T|");m_mapProdu.SetAt(_T("E"),(void*)str); CString* str1 = new CString; *str1 = _T("|T*F|F|");m_mapProdu.SetAt(_T("T"),(void*)str1);CString* str2 = new CString ; *str2 = _T("|(E)|i|");m_mapProdu.SetAt(_T("F"),(void*)str2); CString* str3 = new CString;*str3 = _T("|E+T|F+F|F*F|E+F|T|F|"); m_mapProduEX.SetAt(_T("E"),(void*)str3); CString* str4 = new CString; *str4 = _T("|T*F|F|");m_mapProduEX.SetAt(_T("T"),(void*)str4); CString* str5 = new CString ; *str5 = _T("|(E)|i|(F)|");m_mapProduEX.SetAt(_T("F"),(void*)str5);程序主要代码:void CGrammarAnalysisDlg::InitFind(void) { int i,j; int k = 0;while(k<STACK_LEN) { for(i=0;i<NT_LEN;i++) for(j=0;j<T_LEN;j++) { m_F[k].m_strNTerm = m_strNTElem[i]; m_F[k].m_strTerm = m_strTElem[j]; m_F[k].m_bIsVT = FALSE; k++;}} }//查找 P->a... 和 P->Qa... void CGrammarAnalysisDlg::SearchPForFirtVT(Find& f) { CString* str; m_mapProdu.Lookup(f.m_strNTerm,(void*&)str); int nFrist = 0;int nLen = 0; while(nLen+1 < str->GetLength())// P->a... P 和 P->Qa... { nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nFrist-1);if(IsNT(strProduce,0) && IsT(strProduce,1)) { if(strProduce.GetAt(1) == f.m_strTerm){ if(!f.m_bIsVT) { f.m_bIsVT = TRUE; //CreateFristVT(f); m_stack.PushStack(f);}}}if(IsT(strProduce,0)){ if(strProduce.GetAt(0) == f.m_strTerm) {if(!f.m_bIsVT) {f.m_bIsVT = TRUE;//CreateFristVT(f); m_stack.PushStack(f);}}}}}//判断产生式第nLocat 位置的字符是否是非终结符 BOOL CGrammarAnalysisDlg::IsNT(CString strProduc,int nLocat) { for(int i=0;i<NT_LEN;i++) { if(strProduc.GetAt(nLocat) == m_strNTElem[i])return 1;}return 0;}//判断产生式第nLocat 位置的字符是否是终结符 BOOL CGrammarAnalysisDlg::IsT(CString strProduc, int nLocat) { for(int i=0;i<T_LEN;i++) { if(strProduc.GetAt(nLocat) == m_strTElem[i])return 1;}if(strProduc.GetAt(nLocat) == '#')return 1; return 0;}//遍历所有的产生式 P->Q void CGrammarAnalysisDlg::SearchQForFristVT(void) { Find Q; CString strNT; CString* str;while(m_stack.m_nTop != 0) {m_stack.PopStack(Q);POSITION pos = m_mapProdu.GetStartPosition();while(pos) { m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength()) { nFrist = nLen;nLen = str->Find('|',nFrist+1); CString strProduce = str->Mid(nFrist+1,nLen-nif(IsNT(strProduce,0)) { if(strProduce.GetAt(0) == Q.m_strNTerm) {//Q.m_bIsVT = TRUE;for(int i=0;i<STACK_LEN;i++) { if(m_F[i].m_strNTerm == strNT &&== Q.m_strTerm){ if(!m_F[i].m_bIsVT) { m_F[i].m_bIsVT = TRUE; m_stack.PushStack(m_F[break;}}}} }}}}}// //P->...aQ 或P->...avoid CGrammarAnalysisDlg::SearchPForLastVT(Find& f) { CString* str;m_mapProdu.Lookup(f.m_strNTerm,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength())// P->a... P 和 P->Qa...{nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nFrist-1); int nLocat = strProduce.GetLength(); if(nLocat-2>0) { if(IsNT(strProduce,nLocat-1) && IsT(strProduce,nLocat-2)) { if(strProduce.GetAt(nLocat-2) == f.m_strTerm) { if(!f.m_bIsVT) {f.m_bIsVT = TRUE;m_stack.PushStack(f); }}}}if(IsT(strProduce,nLocat-1)) { if(strProduce.GetAt(nLocat-1) == f.m_strTerm) { if(!f.m_bIsVT) {f.m_bIsVT = TRUE; m_stack.PushStack(f);}}}} }// //P->....Q void CGrammarAnalysisDlg::SearchQForLastVT(void) { Find Q; CString strNT; CString* str;while(m_stack.m_nTop != 0) {m_stack.PopStack(Q);POSITION pos = m_mapProdu.GetStartPosition();while(pos){m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength()) { nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nint nLocat = strProduce.GetLength(); if(IsNT(strProduce,nLocat-1)) { if(strProduce.GetAt(nLocat-1) == Q.m_strN{ //Q.m_bIsVT = TRUE;for(int i=0;i<STACK_LEN;i++) { if(m_F[i].m_strNTerm == strNT &&== Q.m_strTerm){if(!m_F[i].m_bIsVT) { m_F[i].m_bIsVT = TRUE; m_stack.PushStack(m_F[break;} }}} }}}}}void CGrammarAnalysisDlg::OnBnClickedBtnAnsysic() { // TODO: 在此添加控件通知处理程序代码 //初始化列表控件//m_lbResult.AddString(_T("kjl"));m_lst.SetExtendedStyle(LVS_EX_AUTOSIZECOLUMNS|LVS_EX_GRIDLI CRect rc;m_lst.GetClientRect(rc);int nWidth = rc.Width()/(T_LEN+2); int i = 0;m_lst.InsertColumn(i,_T(""),LVCFMT_CENTER,nWidth); for(i=1;i<T_LEN+1;i++) { m_lst.InsertColumn(i,m_strTElem[i-1],LVCFMT_CENTER,nWidth); }m_lst.InsertColumn(i,_T("#"),LVCFMT_CENTER,nWidth); for(i=0;i<T_LEN;i++) { m_lst.InsertItem(i,m_strTElem[i]); }m_lst.InsertItem(i,_T("#")); // //FirstVT InitFind();//Find f(_T("+"),_T("E")); for(int i=0;i<STACK_LEN;i++)SearchPForFirtVT(m_F[i]); SearchQForFristVT(); CreateFristVT(m_F);//LastVT InitFind();//Find f(_T("+"),_T("E")); for(int i=0;i<STACK_LEN;i++)SearchPForLastVT(m_F[i]); SearchQForLastVT(); CreateLastVT(m_F); //遍历产生式构造算符优先表 CString* str; POSITION pos =m_mapProdu.GetStartPosition(); CString strNT; int nColumn; int nItem; while(pos) { m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength()){ nFrist = nLen;nLen = str->Find('|',nFrist+1); CString strProduce = str->Mid(nFrist+1,nLen-nFristint nLocat = strProduce.GetLength(); for(int i=0;i<nLocat-1;i++) {if(IsT(strProduce,i) && IsT(strProduce,i+1)){ nItem = FindTLocat(strProduce.GetAt(i)); nColumn = FindTLocat(strProduce.GetAt(i+1m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("=")}if(i<=nLocat-2 && IsT(strProduce,i) && IsT(s IsNT(strProduce,i+1)){ nItem = FindTLocat(strProduce.GetAt(i)); nColumn = FindTLocat(strProduce.GetAt(i+2m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("=")} if(IsT(strProduce,i) && IsNT(strProduce,i+1)){ nItem = FindTLocat(strProduce.GetAt(i));int nNTLocat = FindNTLocat(strProduce.Get int nVTLen = m_strFristVT[nNTLocat].GetLefor(int j=0;j<nVTLen;j++) { nColumn = FindTLocat(m_strFristVT[nNTm_nPriSheet[nItem][nColumn] = -1;m_lst.SetItemText(nItem,nColumn+1,_T}} if(IsNT(strProduce,i) && IsT(strProduce,i+1)){ nColumn = FindTLocat(strProduce.GetAt(i+1int nNTLocat = FindNTLocat(strProduce.Get int nVTLen = m_strLastVT[nNTLocat].GetLenfor(int j=0;j<nVTLen;j++){ nItem = FindTLocat(m_strLastVT[nNTLom_nPriSheet[nItem][nColumn] = 1;m_lst.SetItemText(nItem,nColumn+1,_T}}}}}//处理‘#',,行nItem = T_LEN;wchar_t ch = '(';for(int i=0;i<T_LEN+1;i++){switch(m_nPriSheet[FindTLocat(ch)][i]){case 0:break;case INFI:break;case -1:m_nPriSheet[nItem][i] = -1;m_lst.SetItemText(nItem,i+1,_T("<"));break;case 1:m_nPriSheet[nItem][i] = 1;m_lst.SetItemText(nItem,i+1,_T(">"));break;}}//处理‘#’,,列nColumn = T_LEN;ch = ')';for(int i=0;i<T_LEN;i++){switch(m_nPriSheet[i][FindTLocat(ch)]){case 0:break;case INFI:break;case -1:m_nPriSheet[i][nColumn] = -1;m_lst.SetItemText(i,nColumn+1,_T("<"));break;case 1:m_nPriSheet[i][nColumn] = 1;m_lst.SetItemText(i,nColumn+1,_T(">"));break;}}//最后一角nItem = T_LEN;nColumn = T_LEN;m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("="));}void CGrammarAnalysisDlg::CreateFristVT(Find* F){for(int i=0;i<STACK_LEN;i++){if(F[i].m_bIsVT){for(int j=0;j<NT_LEN;j++){if(F[i].m_strNTerm == m_strNTElem[j]){m_strFristVT[j] += F[i].m_strTerm;break;}}}}}void CGrammarAnalysisDlg::CreateLastVT(Find* F){for(int i=0;i<STACK_LEN;i++){if(F[i].m_bIsVT){for(int j=0;j<NT_LEN;j++){if(F[i].m_strNTerm == m_strNTElem[j]){m_strLastVT[j] += F[i].m_strTerm;break;}}}}}int CGrammarAnalysisDlg::FindTLocat(wchar_t strT) {for(int i=0;i<T_LEN;i++){if(m_strTElem[i] == strT)return i;}if(strT = '#')return T_LEN;}int CGrammarAnalysisDlg::FindNTLocat(wchar_t strNT) {for(int i=0;i<NT_LEN;i++){if(m_strNTElem[i] == strNT)return i;}return 0;}void CGrammarAnalysisDlg::OnBnClickedBtnAnasysic() {// TODO: 在此添加控件通知处理程序代码//清空列表控件int nCount = m_lbResult.GetCount();for(int i=0;i<nCount;i++)m_lbResult.DeleteString(0);//UpdateData();//清空栈m_stack.m_nTop = 0;//初值int j,k = 1;CString Q;m_stack.m_Ch[k] = (_T("#"));////int nLen = m_strSen.GetLength();m_strSen += _T("#");int i = -1;do{i++; if(IsT(m_stack.m_Ch[k],0))j = k;else j = k-1;int nItem = FindTLocat(m_stack.m_Ch[j].GetAt(0));int nColumn = FindTLocat(m_strSen[i]);while(m_nPriSheet[nItem][nColumn] == 1){int nItem1,nColumn1;do{Q = m_stack.m_Ch[j];if(IsT(m_stack.m_Ch[j-1],0))j = j-1;else j= j-2;nItem1 = FindTLocat(m_stack.m_Ch[j].GetAt(0))nColumn1 = FindTLocat(Q.GetAt(0));} while (m_nPriSheet[nItem1][nColumn1] != -1);CString strToProduce;for(int m = j+1;m<=k;m++){strToProduce += m_stack.m_Ch[m];}//输出产生式POSITION pos = m_mapProduEX.GetStartPosition();CString strNT;CString* str;while(pos){m_mapProduEX.GetNextAssoc(pos,strNT,(void*&)sint nFrist = 0;int nLen = 0;while(nLen+1 < str->GetLength()){nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLif(strProduce == strToProduce){CString strResult;strResult = strNT; strResult += _T("->"); strResult += strToProduce;m_lbResult.AddString(strResult); k = j+1; m_stack.m_Ch[k] = strNT; break;}}}nItem = FindTLocat(m_stack.m_Ch[j].GetAt(0)); nColumn = FindTLocat(m_strSen[i]); //}nItem = FindTLocat(m_stack.m_Ch[j].GetAt(0));nColumn = FindTLocat(m_strSen[i]);if(m_nPriSheet[nItem][nColumn] == -1 || m_nPriSheet[nIt {k += 1;m_stack.m_Ch[k] = m_strSen[i];} else{ MessageBox(_T("错误!"));return;}}while(m_strSen[i] != '#'); MessageBox(_T("成功!"));}五.结果分析及试验心得:本次实验做起来有点复杂,我认为重点在对教材所给算法的理解及个变量存储形式的设计。

二语法分析程序(算符优先分析法)

二语法分析程序(算符优先分析法)

实验二语法分析程序(算符优先分析法)一、实验目的通过设计调试算符优先分析程序,加深对课堂教学的理解,深刻理解自底向上语法分析方法的归约过程,提高语法分析方法的实践能力。

二、实验要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。

(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。

(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。

编译原理算符优先算法语法分析实验报告

编译原理算符优先算法语法分析实验报告

年级专业_学号 _姓名成绩__________________数学与计算机学院编译原理实验报告实验题目算符优先分析法分析器的设计实验日期一、实验目的:设计一个算符优先分析器,理解优先分析方法的原理。

二、实验要求:设计一个算符优先分析器三、实验内容:使用算符优先分析算法分析下面的文法:E' T #E#E T E+T | TT T T*F | FF T P AF | PP T (E) | i其中i可以看作是一个终结符,无需作词法分析。

具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。

四、实验结果及主要代码:1•主要代码 void operatorp()char s[100];char a,Q;int k,j,i,l;string input,temp;cin>>input;"<<'\t'<<" 剩cout<<" 步骤 "<<'\t'<<" 栈 "<<'\t'<<" 优先关系 "<<'\t'<<" 当前符号余输入串 "<<'\t'<<" 移进或归约 "<<endl;k=1;s[k]='#';i=1;do{a=input[0];temp="";for(l=1;l<input.length();l++)temp+=input[l];input=temp;if(svt(s[k])) j=k;else j=k-1;while (search(s[j],a)=='>'){// 步骤cout<<'('<<i<<')'<<'\t';temp="";// 优先关系 // 当前符号 // 剩余输入串for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; // 栈cout<<'>'<<'\t'<<setw(10);cout<<a<<'\t'<<setw(15);cout<<input<<'\t'<<setw(15);i++;for(;;){Q=s[ j];if(svt(s[j-1])) j=j-1;else j=j-2;if(search(s[j],Q)=='<'){cout<<" 归约 "<<endl;// 归约break;}}temp="";for(l=j+1;l<k+1;l++)temp+=s[l]; for(l=0;l<6;l++)// 优先关系// 当前符号// 剩余输入串if(temp==key[l]){k=j+1; s[k]=v[l]; break;}}cout<<'('<<i<<')'<<'\t'; // 步骤 temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; // 栈if(search(s[j],a)=='<'){cout<<'<'<<'\t'<<setw(10);;cout<<a<<'\t'<<setw(15);cout<<input<<'\t'<<setw(15);cout<<" 移进 "<<endl;i++;k=k+1;s[k]=a;} // 移进else if(search(s[j],a)=='Y')cout<<'='<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<i nput<<'\t'<<setw(15); //剩余输入串cout<<"接受"<<e ndl;i++;}else{cout<<?<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<i nput<<'\t'<<setw(15); //剩余输入串cout<<"出错"<<e ndl;exit(O);}//出错}while(a!='#');2•实验结果优九关系 ■fri 利余输入串 当前符号 i*n few ■ *F ::\2O12\^i§J '^:S\^:SJFt?^=£-\0perator_preredAnce_rpdL4r+ion\cipFr i a J or^preced?nre,red 1! 話讲<2> <3> <4> <5> <6> <7> Pi*es £栈 t 11 tF IF* »F*i tF*F tF any key to continue H inn imtmt欢迎下载,谢谢观看!资料仅供参考学习。

实验四算符优先分析算法

实验四算符优先分析算法

实验四:算符优先分析算法1.实验目的:掌握算符优先分析析程序的分析、设计与实现的基本技术与一般方法。

2.实验题目:编写并上机调试完成识别由下列文法所定义的表达式的算符优先分析程序。

E→E+T | E-T | TT→T*F | T/F |FF→(E) | i3.实验步骤(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, - , * , / , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , / , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }(3)程序参考源码/****************************************/ /* 程序名称:算符优先分析程序*/ /* 程序用途:编译原理实验(四) */ /* 编写日期:2005年11月15日*/ /* 实验题目:对下列文法*/ /* E->E+T|E-T|T */ /* T->T*F|T/F|F */ /* F->(E)|i */ /* 编写算符优先分析程序*/ /* 程序版本: 1.0 Final */ /* 程序作者:黄记瑶B0226047 */ /* 作者邮箱:****************/ /****************************************//****************************************//* 程序相关说明*//* 0=+ 1=- 2=* 3=/ 4=( 5=) 6=i 7=# *//* *//* 算符优先关系表*//* ------------------------------------------------------*//* + - * / ( ) i # *//* + > > < < < > < > *//* - > > < < < > < > *//* * > > > > < > < > *//* / > > > > < > < > *//* ( < < < < < = < ? *//* ) > > > > ? > ? > *//* i > > > > ? > ? > *//* # < < < < < ? < = *//* ------------------------------------------------- *//****************************************/#include "stdio.h"#include "malloc.h"struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;int table[8][8]={{1,1,-1,-1,-1,1,-1,1},{1,1,-1,-1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{-1,-1,-1,-1,-1,-1,-1,0},{1,1,1,1,0,1,0,1},{1,1,1,1,0,1,0,1},{-1,-1,-1,-1,-1,0,-1,-1}};/*存储算符优先关系表,大于为1,小于或等于为-1,其它为0表示出错*/char curchar;char curcmp;int right;/*设置开关项,当出错时为0*/int i,j;int k;/*比较字符在栈的位置*/void push(char pchar)/*入栈函数*/{temp=malloc(sizeof(Lchar));temp->char_ch=pchar;temp->next=top;top=temp;}void pop(void)/*出栈函数*/{if(top->char_ch!='#')top=top->next;}int changchartoint(char ch)/*将字符转为数字,以得到算符优先值*/ {int t;switch(ch){case '+':t=0;break;case '-':t=1;break;case '*':t=2;break;case '/':t=3;break;case '(':t=4;break;case ')':t=5;break;case 'i':t=6;break;case '#':t=7;}return t;}void dosome(void){k=1;for(;;){curchar=h->char_ch;temp=top;for(;;){if(temp->char_ch=='N'){temp=temp->next;k++;}else{curcmp=temp->char_ch;break;}}printf("\n%d\t%d\t",table[i][j],k);temp=top;for(;;)/*打印栈*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}printf("\t");temp=h;for(;;)/*打印待比较的字符*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}i=changchartoint(curcmp);j=changchartoint(curchar);if(table[i][j]==0)/*算符优先值为空*/{printf("\n%d\t%d\t%c\t%c\terror1",table[i][j],k,curcmp,curchar);right=0;break;}else/*算符优先值不为空*/{if(table[i][j]<0)/*算符优先值为-1,移进*/{if(curchar=='#')/*待比较字符为空*/{if(k==2)/*当前比较字符在栈的位置为两个元素*/break;else{printf("\n%d\t%d\t%c\t%c\terror2",table[i][j],k,curcmp,curchar);right=0;break;}}push(curchar);h=h->next;}else/*算符优先值为1,归约*/{if(curcmp=='i')/*当前比较为i,出栈一次*/pop();else/*当前比较不为i,出栈三次*/{pop();pop();pop();}push('N');/*归约到N*/k=1;}}}}void main(void){char ch;right=1;base=malloc(sizeof(Lchar));base->next=NULL;base->char_ch='#';top=base;h=malloc(sizeof(Lchar));h->next=NULL;p=h;do{ /*输入待比较字符串,以'#'结束*/ch=getch();putch(ch);if(ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#'){temp=malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=ch;h->next=temp;h=h->next;}else{temp=p->next;printf("\nInput a wrong char!Input again:\n");for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsebreak;temp=temp->next;}}}while(ch!='#');/*输入待比较字符串,以'#'结束*/p=p->next;h=p;dosome();/*开始识别*/if(right)printf("\nOK!\n");elseprintf("\nError!\n");getch();}。

编译原理 算符优先分析实验报告

编译原理 算符优先分析实验报告

实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。

G[E]:E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
说明:终结符号i 为用户定义的简单变量,即标识符的定义。

(1)构造该算符优先文法的优先关系矩阵或优先函数;(2)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(3)算符优先分析过程应能发现输入串出错。

(4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。

备注:程序中判断该输入串是否为该文法定义的算术表达式的结果,若是则输出“accept”,若不是则输出“error”。

该二元式序列要以“#”为结尾。

主要数据结构描述
程序结构描述
程序测试:
测试1:(i+i*i)
输出:
输入二:i+i*ii
输出:
学习总结
算符优先文法关键点就在于判断各个终结符号的优先级,构造算符优先矩阵是个难点,程序里面没有实现,而是直接定义了优先矩阵,这是需要完善的地方,试试能不能在程序中动态地构造优先矩阵。

另外对于算符优先文法,失败的条件是比较两个非终结符的优先关系,若优先关系表中为空,就返回error.。

算符优先_实验报告

算符优先_实验报告

一、实验目的1. 理解算符优先分析法的原理和过程。

2. 掌握算符优先分析法的实现方法。

3. 通过实验加深对自底向上语法分析方法的理解。

二、实验内容1. 算符优先分析法原理介绍算符优先分析法是一种自底向上的语法分析方法,它通过比较相邻算符的优先次序来识别句型中的句柄,进而执行归约。

该方法的核心是确立文法的终结符之间的优先关系。

2. 实验步骤(1)判断文法是否为OG文法:OG文法要求所有产生式右部至少有一个终结符。

(2)判断文法是否为OPG文法:计算FIRSTVT集、LASTVT集,并构建算符优先矩阵。

(3)对句子进行分析:根据分析表判断句子是否为文法的句子。

(4)实现程序:从文件和键盘读取输入,将结果输出到指定文件和屏幕,并具有一致性。

3. 实验数据(1)文法:g[e]:e->e+t|t(2)测试句子:12+t, t+12, 12+13t, 12+t13三、实验过程1. 判断文法是否为OG文法根据给定的文法,我们可以看到所有产生式右部至少有一个终结符,因此该文法为OG文法。

2. 判断文法是否为OPG文法,并构建算符优先矩阵(1)计算FIRSTVT集FIRSTVT(e) = {t}FIRSTVT(t) = {t}(2)计算LASTVT集LASTVT(e) = {t}LASTVT(t) = {t}(3)构建算符优先矩阵| + - ( ) t e $+ > - - - > > -- > - - - > > -> > > > > > >( > > > > > > >) - - - - - - -t - - - - - - -e - - - - - - -$ - - - - - - -3. 对句子进行分析(1)分析句子“12+t”根据分析表,我们可以得到以下分析过程:12+t -> 12+t -> 12+t -> t -> t(2)分析句子“t+12”根据分析表,我们可以得到以下分析过程:t+12 -> t+12 -> t+12 -> t+12 -> t+12 -> t -> t (3)分析句子“12+13t”根据分析表,我们可以得到以下分析过程:12+13t -> 12+13t -> 12+13t -> 12+13t -> 12+13t -> t -> t(4)分析句子“12+t13”根据分析表,我们可以得到以下分析过程:12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> t13 -> t13 -> t13 -> t -> t四、实验结果1. 测试句子“12+t”分析结果:正确2. 测试句子“t+12”分析结果:正确3. 测试句子“12+13t”分析结果:正确4. 测试句子“12+t13”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理实验报告题目: 算符优先分析法分析器学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx姓 名 宁剑指导教师 xxxx2015年xx 月xx 日算符优先分析法分析器一、实验目的1.理解自底向上优先分析,比较和自顶向下优先分析的不同。

2.理解算符优先分析的特点,体会其和简单优先分析方法的不同。

3.加深对编译器语法分析的理解。

装订线二、实验原理1.自底向上优先分析方法,也称移进-归约分析,粗略地说它的思想是对输入符号串自左向右进行扫描,并将输入符号逐个移入一个后进先出栈,边移入边分析,一旦栈顶符号串形成某个句型的句柄或可归约串时,就将该产生式的左部非终极符代替相应的右边文法符号串。

2.算符优先分析法的基本思想首先确定算符(确切地说是终结符)之间的优先关系和结合性质,然后借助这种关系,比较相邻算符之间的优先级来确定句型的可归约串,并进行归约。

注意:算符优先分析过程是自下而上的归约过程,但它的可归约串未必是句柄,也就是说,算符优先分析过程不是一种规范归约。

3.终结符号间优先关系的确定,用FIRSTVT和LASTVT计算。

4.最左素短语所谓素短语是指这样一个短语,它至少含有一个终结符,并且除它自身之外不再含有其它素短语。

最左素短语是指处于句型最左边的那个素短语。

最左素短语是算符优先分析算法的可归约串。

5.计算得到所给文法的算符优先矩阵6.算符优先分析的基本过程三、实验要求使用算符优先分析算法分析下面的文法:E’→#E#E→E+T|TT→T*F|FF→P^F|PP→(E)|i其中i可以看作是一个终结符,无需作词法分析。

具体要求如下:1.如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2.如果输入符号串不是正确句子,则指示出错位置。

四、实验结果(程序)及分析#include <>#include <cstring>#include <iostream>#include <iomanip>#define MAX 100using namespace std;char S[MAX];char shuru[MAX],yu[MAX];void scanner();int panyouxian(char x);void shengyuchuan();int k;char youxian[7][7]={{'>','<','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','>','$','$','>','>'},{'<','<','<','<','<','=','$'},{'>','>','>','$','$','>','>'},{'<','<','<','<','<','$','='},}; //优先关系表,其中>为大于,<为小于,=为等于,$为空格int main(){int l,j;cout<<"请输入一个字符串:";(shuru,MAX); //将输入的字符串存到数组cout<<"步骤栈优先关系当前符号剩余输入串移进或归约"<<endl;k=0;S[k]='#';S[k+1]='\0';l=strlen(shuru); //求输入字符串的长度for(j=0;j<l;j++)yu[j]=shuru[j];yu[j]='\0';scanner();return 0;}void scanner() //扫描分析输入串{int i,j,l,h1,l1,h2,l2,h3,l3,y1,y2,r1,r2;int step=0;//分析步骤数char a; //存放正在分析的字符char p1,Q,p2;l=strlen(shuru); //算出输入串长度for(i=0;i<l;i++){a=shuru[i];if(S[k]=='+'||S[k]=='*'||S[k]=='^'||S[k]=='i'||S[k]=='('||S[k]==' )'||S[k]=='#')j=k;elsej=k-1;h1=panyouxian(S[j]);// 从优先关系表中查出S[j]和a的优先关系if(a=='+'||a=='*'||a=='^'||a=='i'||a=='('||a==')'||a=='#') l1=panyouxian(a);else //如果句子含有不是终结符集合里的其它字符,不合法{cout<<"错误!不合法的句子!"<<endl;break;}p1=youxian[h1][l1];if(p1=='>'){loop:Q=S[j];if(S[j-1]=='+'||S[j-1]=='*'||S[j-1]=='^'||S[j-1]=='i'||S[j-1]=='( '||S[j-1]==')'||S[j-1]=='#')j=j-1;elsej=j-2;h2=panyouxian(S[j]);l2=panyouxian(Q);p1=youxian[h2][l2];if(p1=='<') //S[j+1]…S[k]归约为F{k=j+1;shengyuchuan();step++;cout<<left<<"("<<step<<setw(6)<<")"<<setw(10)<<S<<setw(10)<<p1<<s etw(10)<<a<<setw(5)<<right<<yu<<setw(15)<<"归约"<<endl;i--;S[k]='F';r1=strlen(S);for(r2=k+1;r2<r2;r2++)S[r2]='\0';//多个字符归约,把栈顶后面的舍弃y1=strlen(yu);for(y2=0;y2<y1;y2++)yu[y1-y2]=yu[y1-y2-1];yu[0]='i';}elsegotoloop;}else{if(p1=='<') //移进如果上一步是不归约,剩余的字符串减少一个{shengyuchuan();shuru[l]='\0';step=step+1;cout<<left<<"("<<step<<setw(6)<<")"<<setw(10)<<S<<setw(10)<<p1<<s etw(10)<<a<<setw(5)<<right<<yu<<setw(15)<<"移近"<<endl;k=k+1;S[k]=a;}else{if(p1=='='){h3=panyouxian(S[j]);l3=panyouxian('#');p2=youxian[h3][l3];if(p2=='='){shengyuchuan();step++;cout<<left<<"("<<step<<setw(6)<<")"<<setw(10)<<S<<setw(10)<<p1<<s etw(10)<<a<<setw(5)<<right<<yu<<setw(15)<<"接受"<<endl;cout<<"合法的句子!"<<endl;;break;}else{k=k+1;S[k]=a;}}else{cout<<"出错!"<<endl;break;}}}}}void shengyuchuan(){int i,j;i=strlen(yu);for(j=0;j<i;j++)yu[j]=yu[j+1];yu[i-1]='\0';}int panyouxian(char x){int m;switch(x){case'+':m=0;break;case'*':m=1;break;case'^':m=2;break;case'i':m=3;break;case'(':m=4;break;case')':m=5;break;case'#':m=6;break;}return m;}输入的程序界面如图:输入一个正确的句子,结果如下:输入一个错误的句子,提示为不合法的句子:。

相关文档
最新文档