右线性文法转换有限自动机.docVIP

  • 126
  • 0
  • 约2.71千字
  • 约 8页
  • 2018-10-11 发布于江苏
  • 举报
右线性文法转换有限自动机

编译原理 实习报告一 191103 魏晓东 PAGE 1 - 编译原理实习 报 告 学院: 计算机学院 专业:计算机科学与技术 目 录 一、题目要求 02 二、算法思想 02 三、程序设计 03 四、运行截图 06 五、心得体会 06 右线性文法转换为有限自动机 一、题目要求 要求编写一个程序,输入一个右线性文法,输出与该文法等价的有限自动机。 二、算法思想 首先输入变量集、终结符集和开始符,输入变量集和终结符集时用逗号隔开,否则会提示出错。然后输入右线性文法的产生式,输入时即区分出产生式的左部和右部,点击添加产生式按钮提取产生式的左部和右部。如果产生式不符合要求,则提示出错,添加的产生式使用链表存储,每个节点表示一个产生式,每次点击添加后,程序将会新生成一个结点来表示产生式。产生式的具体数据结构如下所示: typedef struct List { char leftVar[10]; //左侧字符 char rightVar[10]; //右侧字符 char endVar[10]; //终结符 char endRightVar[10]; //右侧后部字符 List *pNext; //next指针 }dfaList, *pdfaList; 添加完成后,程序将从产生式链表的第一个结点开始扫描,从右部提取出前端的终结符,具体方法是定义一个UCHAR型的指针,从前端向后扫描,如果是小写字母(默认是非终结符),则将小写字母放入终结符集中,当扫描完前端后,指针继续后移,此时判断条件改变,如果不为“\0” 转换成自动机时,将先前提取出的各字符串按照正确位置放置,并以函数的形式输出,例如:产生式V0—aV1,分别提取出V0,a和V1,然后将提取出来的V0,a和V1输出为f(V0,a)={V1},如果产生式形如V1—b类型,则将以f(V1,b)={Q}形式输出。 三、程序设计 程序流程图: 程序开始 程序开始 载入文法 用户输入文法 读取文件内容 输入终结符集 输入变量集 输入开始符 添加产生式 是否继续添加 转换为自动机 是 否 程序结束 添加结点 添加结点 错误判断模块: 根据输入的变量集、终结符集和开始符判断输入的文法是否为右线性文法,如果不是右线性文法,返回0,是右线性文法,则返回1。如果不正确,则不能插入结点,如果正确才可以将该产生式插入到链表中。 //判断产生式输入是否正确 int CDFADlg::ifCorrect() { UpdateData(TRUE); TCHAR *strTmp; int i,iFind=0,ifMeet=0; //ifmeet是否遇到大写字母 strTmp = m_Pro2.GetBuffer(0); if (*strTmpz || *strTmpa) return 0; if (*strTmp=a *strTmp=z) { for (i=0;i20;i++) { if (*strTmp==endVarArray[i] endVarArray[i]!=) iFind=1; } if (1 == iFind) *strTmp++; else return 0; } if (*strTmp == \0) return 1; if (*strTmpA || *strTmpZ) return 0; CString strRight; while (*strTmp!=\0) { strRight+=*strTmp; strTmp++; } iFind = 0; for (i=0;i20;i++) { if (strRight == varArray[i] varArray[i]!=) { iFind=1; return 1; } } if (0 == iFind) return 0; } 产生式右部拆分: 将产生式的右部终结符和非终结符分开,分别存储在链表每个节点的不同属性值中,具体方法就是判断字母符号的大小写,如果是小写,就放入终结符属性中,然后将其后的字符放入非终结符属性中。 //产生式右部拆分 void CDFADlg::GetRightStr(CString strRightTmp) { TCHAR *strTmp; strTmp = strRightTmp.GetBuffer(0); while (*strTmp=a *strTmp=z) { dfa.endvar+=*strTmp; strTmp++

文档评论(0)

1亿VIP精品文档

相关文档