实验一词法分析
- 格式:doc
- 大小:136.00 KB
- 文档页数:15
实验1 词法分析一、目的与要求1)目的通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课 堂教学的理解;提高词法分析方法的实践能力。
2)要求u掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文 件的方法。
u掌握词法分析的实现方法。
u上机调试编出的词法分析程序。
二、说明本实验以赋值语句(以#号表示输入结束)为输入文件,BNF表示如下:〈赋值语句〉 ∷= 变量 = 算术表达式〈算术表达式〉∷=〈项〉〈算术表达式〉∷=〈算术表达式〉+〈项〉〈算术表达式〉∷=〈算术表达式〉-〈项〉〈项〉∷=〈因式〉〈项〉∷=〈项〉*〈因式〉〈项〉∷=〈项〉/〈因式〉〈因式〉∷=〈变量〉〈因式〉∷=(〈算术表达式〉)〈变量〉::= 标识符|常整数字母表:Σ={+,,*,\,(,),=,a,b,c….z,A,B,C…Z,0,1,2,…9,#} 单词类型:u标识符 :字母组成,长度不限u常整数 :数字组成u运算符 :+,-,*,\,()u结束符:#数据结构: 标识符用单独的符号表来记录,符号表中标识符的属性只有一项: 标识符本身的字符串值。
输出:二元式,第一部分为单词的类别,第二部分为单词的属性值,其中标识 符的属性值为标识符表的索引值,常整数的属性值为常整数值,其他的属性值为单 词本身的字符串值三、词法分析过程1、背景知识(对源程序或中间结果从头到尾扫 词法分析是作为相对独立的阶段来完成的描一次,并作相应的加工处理,生成新的中间结果或目标程序)。
在词法分析 过程中,编译程序是通过操作系统从外部介质中读取源程序文件中的各个字符 的。
同时,为正确地识别单词,有时还需进行超前搜索和回退字符等操作。
因 此,为了提高读盘效率和便于扫描器进行工作,通常可采用缓冲输入的方案, 即在内存中设置一个适当大小的输入缓冲区,让操作系统直接将磁盘上的源程 序字符串分批送入此缓冲区中,供扫描器进行处理。
词法分析程序的一般设计方案是:1) 程序设计语言词法规则⇒正规文法⇒ FA;或:词法规则⇒正规表达式⇒ FA;2) NFA 确定化⇒ DFA;3) DFA 最简化;4) 确定单词符号输出形式;5) 化简后的DFA+单词符号输出形式⇒构造词法分析程序。
实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
【实验步骤和要求】1.要求绘出词法分析过程的流程图。
2.根据词法分析的目的以及内容,确定完成分析过程所需模块。
3.写出每个模块的源代码。
4.整理程序清单及所得结果。
//源程序如下:#include <iostream>#include <ctype.h>#include <fstream>#include <string.h>#include <malloc.h>#define NULL "abc"using namespace std;ifstream fp("d:\\cifa.cpp",ios::in);char cch;char *key[12]={"if","else","for","while","do","return","break","continue","int","void" ,"main","const"}; //基本字char *border[10]={ "," , ";" , "{" , "}" , "(" , ")" , "[" , "]",""",""" }; //界符char *arithmetic[6]={"+" , "-" , "*" , "/" , "++" , "--"}; //算术运算符char *relation[7]={"<" , "<=" , "=" , ">" , ">=" , "==" ,"!="}; //关系运算符char *lableconst[80]; //标识符int constnum=40;int lableconstnum=0;int search(char searchchar[],int wordtype){int i=0,t=0;switch (wordtype){case 1:{for (i=0;i<=11;i++){if (strcmp(key[i],searchchar)==0)return(i+1);}return(0);}case 2:{for (i=0;i<=9;i++){if (strcmp(border[i],searchchar)==0)return(i+1);}return(0);}case 3:{for (i=0;i<=5;i++){if (strcmp(arithmetic[i],searchchar)==0)return(i+1);}return(0);}case 4:{for (i=0;i<=6;i++){if (strcmp(relation[i],searchchar)==0)return(i+1);}return(0);}case 5:{for (t=40;t<=constnum;t++){if (strcmp(searchchar,lableconst[t])==0)return(t+1);}lableconst[t-1]=(char *)malloc(sizeof(searchchar)); strcpy(lableconst[t-1],searchchar);constnum++;return(t);}case 6:{for (i=0;i<=lableconstnum;i++){if (strcmp(searchchar,lableconst[i])==0)return(i+1);}lableconst[i-1]=(char *)malloc(sizeof(searchchar)); strcpy(lableconst[i-1],searchchar); lableconstnum++;return(i);}default:cout<<"错误!";}}char alphaprocess(char ch){int atype;int i=-1;char alphatp[20];while ( (isalpha(ch)) || (isdigit(ch)) ){alphatp[++i]=ch;fp.get(ch);}alphatp[i+1]='\0';if (atype=search(alphatp,1))cout<<alphatp<<"\t\t\t"<<(atype-1)<<endl; else{atype=search(alphatp,6);cout<<alphatp<<"\t\t\t"<<(atype-1)<<endl; }return(ch);}char digitprocess(char ch){int I = -1;char digittp[20];int dtype;while ((isdigit(ch))){digittp[++i]=ch;fp.get(ch);}digittp[i+1]='\0';dtype=search(digittp,5);cout<<digittp<<"\t\t\t"<<(dtype-40)<<endl; return(ch);}char otherprocess(char ch){int i= -1;char othertp[20];int otype,otypetp;othertp[0]=ch;othertp[1]='\0';if (otype=search(othertp,3)){fp.get(ch);othertp[1]=ch;othertp[2]='\0';if (otypetp=search(othertp,3)){cout<<othertp<<"\t\t\t"<<(otypetp-1)<<endl;fp.get(ch);goto out;}else{othertp[1]='\0';cout<<othertp<<"\t\t\t"<<(otype-1)<<endl;goto out;}}if (otype=search(othertp,4)){fp.get(ch);othertp[1]=ch;othertp[2]='\0';if (otypetp=search(othertp,4)){cout<<othertp<<"\t\t\t"<<(otypetp-1)<<endl;fp.get(ch);goto out;}else{othertp[1]='\0';cout<<othertp<<"\t\t\t"<<(otype-1)<<endl;goto out;}}if (ch=='!'){fp.get(ch);if (ch=='=')cout<<"!= (2,2)\n";fp.get(ch);goto out;}else{if (otype=search(othertp,2)){cout<<othertp<<"\t\t\t"<<(otype-1)<<endl;fp.get(ch);goto out;}}if ((ch!='\n')&&(ch!=' '))cout<<"错误!,字符非法"<<"\t\t\t"<<ch<<endl; fp.get(ch);out: return(ch);}void main(){int i;for (i=0;i<=50;i++){lableconst[i]=NULL;}if (!fp)cout<<"文件打开错误!!"<<endl;else{fp.get (cch);while (!fp.eof()){if (isalpha(cch)){cch=alphaprocess(cch);}else if (isdigit(cch)){cch=digitprocess(cch);}else cch=otherprocess(cch);}}cout<<"成功\n";getchar();}cifa.cpp#include<stdio.h>void main(){cout<<”Hello World”;}【实验小结】通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉C语言的相关内容,加深了对C语言知识的深化和用途的理解。
实验名称: 词法分析器设计专业: 计算机科学与技术**: ***学号: *********词法分析器设计一. 实验要求1.从源程序文件中读取有效字符和并将其转换成二元组机内表示形式输出。
2.掌握词法分析的实现方法。
二. 实验内容1、主程序设计要求:(1)主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
(2)id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。
(3)主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。
2.词法分析过程要求:该过程取名为lexical, 它根据输入单词的第一个有效字符(有时还需读第二个字符), 判断单词类, 产生类号。
对于标识符和常数, 需分别与标识符表和常数表中已登记的元素相比较, 如表中已有该元素, 则记录其在表中的位置, 如未出现过, 将标识符按顺序填入数组id 中, 将常数存入数组中ci 中, 并记录其在表中的位置。
注: 所有识别出的单词都用二元组表示。
第一个表示单词的种类。
关键字的t=1;标识符的t=2;常数t=3;运算符t=4;界符t=5。
第二个为该单词在各自表中的指针或内部码值(常数表和标识符表是在编译过程中建立起来的。
其i 值是将词法分析程序设计成独立一遍扫描源程序的结构。
其主流程图如下:图1 词法分析程序流程图三. 程序设计思想及实现步骤设计思想:本程序使用MFC可视化程序设计实现, 采用vs2010编译环境。
通过Eidt控件输入程序代码, 点击按钮启动词法分析, 将结果显示在CListBox控件中。
实现步骤:1、为程序各变量设计存储形式, 具体设计如下所示:CString m_strToken; 读入的程序代码CString m_strCodes; 得到的一个单词或符号char m_ch; 字符变量, 存放最新读进的源程序字符int m_nLocat; 查找时的位置int m_nId; 标识符表位置int m_nDigit; 常数表中的位置CString WordSheet[WORD_LEN]; 关键字表CString IdSheet[WORD_LEN]; 标识符表CString DigitSheet[WORD_LEN]; 常数表2.为程序设计各个过程, 具体设计如下所示:void GetBC(void); 检查空格符, 并将其舍弃void Concat(void); 连接字符BOOL IsLetter(void); 判断输入的是否为字符BOOL IsDigit(void); 判断输入的是否为数字int Reserve(void); 查找保留字表, 返回在表中对应的位置void Retract(void); 回退一个字符得到单词int InsertId(void); 将单词插入标识符表/int InsertConst(void) 将数字插入常数表3.对各个过程进行实现;4、调试运行并检验实验结果, 结果如图1.1所示:图 1.1 词法分析结果图四. 程序源码1、各过程的实现:void CAnalysisWordsDlg::GetChar(void) {//得到下个输入字符UpdateData();m_ch = m_strCodes.GetAt(m_nLocat);m_nLocat++;}void CAnalysisWordsDlg::GetBC(void) {//检查空白符if(m_ch == ' ')GetChar();}// 连接字符void CAnalysisWordsDlg::Concat(void) {m_strToken += m_ch;} //是否是字符BOOL CAnalysisWordsDlg::IsLetter(void) {if(m_ch>='a' && m_ch<='z')return TRUE;else if(m_ch>='A' && m_ch<='Z')return TRUE;return FALSE;}//是否是数字BOOL CAnalysisWordsDlg::IsDigit(void) {if(m_ch>='0' && m_ch<='9')return TRUE;return FALSE;}// //查找保留字表int CAnalysisWordsDlg::Reserve(void){for(int i=1;i<41;i++){if(m_strToken == WordSheet[i])return i;}return 0;}// //得到字符void CAnalysisWordsDlg::Retract(void){//m_strToken=m_strToken.Left(m_strToken.GetLength()-1);m_nLocat--;m_ch = ' ';}// //将字符插入字符表int CAnalysisWordsDlg::InsertId(void){for(int i=1;i<m_nId+1;i++){if(IdSheet[i] == m_strToken)return i;}m_nId++;IdSheet[m_nId] = m_strToken;return m_nId;}// //将数字插入数字表int CAnalysisWordsDlg::InsertConst(void) {for(int i=1;i<m_nDigit+1;i++){if(m_strToken == DigitSheet[i])return i;}m_nDigit++;DigitSheet[m_nDigit] = m_strToken;return m_nDigit;}2.Edit控件中换行的消息预处理函数:BOOL CAnalysisWordsDlg::PreTranslateMessage(MSG* pMsg) {// TODO: 在此添加专用代码和/或调用基类if(pMsg->message == WM_KEYDOWN){if(pMsg->wParam == VK_RETURN ){return FALSE;}}return CDialogEx::PreTranslateMessage(pMsg);}3.主过程的实现(按钮对应的消息函数):void CAnalysisWordsDlg::OnBnClickedBtnStartAnaly(){// TODO: 在此添加控件通知处理程序代码UpdateData();m_nLocat = 0;//GetDlgItem(IDC_LIST_RESULT)->SetItemText(_T(""));int n = m_lstResult.GetCount();for(int i=0;i<n;i++)m_lstResult.DeleteString(i+1);if(m_strCodes != _T("")){int nLen = m_strCodes.GetLength();while(nLen != m_nLocat){CString strLst;m_strToken = _T("");int code,value;GetChar();GetBC();if(IsLetter()){while (IsLetter() || IsDigit()){Concat();GetChar();}Retract();code = Reserve();if(code == 0){//标识符value = InsertId();strLst.Format(_T("标识符: (2,%d,%s)"),value,m_strToken);m_lstResult.AddString(strLst);}else{strLst.Format(_T("关键字: (1,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}}else if(IsDigit()){while(IsDigit()){Concat();GetChar();}Retract();value = InsertConst();strLst.Format(_T("数字: (3,%d,%s)"),value,m_strToken);m_lstResult.AddString(strLst);}else{while(!(IsLetter() || IsDigit() || m_ch ==' ' || (m_nLocat == nLen+1))){Concat();GetChar();}Retract();code = Reserve();if(code == 14 || (code >= 30&&code <= 38)){//界符strLst.Format(_T("界符: (5,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}else if((code>=15 && code <= 29) || (code>=39 && code<=40)){//运算符strLst.Format(_T("运算符: (4,%d,%s)"),code,m_strToken);m_lstResult.AddString(strLst);}}}}}五. 结果分析及试验心得:(1)本次实验主要的函数及功能教材上提供的很全面, 因此本次实验主要的工作就是对各个函数过程的实现, 做起来还是比较容易的!但对程序的几点思考使我对词法分析有了更深的认识:表结构的存储: 对与各个表的存储开始时我想到是运用数据库存储, 这样实现起来会更容易!但是数据库的引入减少了代码的量, 但却使程序脱离的底层失去了词法分析的意义;程序功能的实现:对于程序中的“++”、“--”等运算符用到了超前搜索的思想, 由于开始设计时的从简原则, 使得在这一块的实现上还存在这问题, 需要以后的继续改进;分析错误的处理: 虽然这次实验我并没有加入错误的处理程序, 但我个人认为对于错误的处理是程序设计中一个很重要的环节, 他对程序的健壮性用很大的影响。
J 实验一词法分析一、实验目的:通过本实验理解词法分析的整个过程,处理对象和处理的结果,了解词法分析在整个编译过程中的作用。
二、实验学时:4学时。
三、实验内容根据给出的简单语言的词法构成规则和单词集合,编制词法分析程序,要求能将用给定简单语言书写的源程序进行词法分析,同时建立相应的符号表文件存放正确的单词。
输出分析结果于文件中,包括:(1)正确的单词符号及其单词种类的序对二元组。
(2)错误单词的信息。
若有错误,必须输出错误单词在源程序中的行位置。
具体输出形式为:二元组:(单词种类,单词内码值)或三元组:(单词种类,单词内码值,源程序中的行号)单词种类见五。
四、实验方法构造识别单词集的自动机,编写程序实现。
五、实验的处理单词集(注:单词种类统一分类如下:)单词符号单词种类任意变量名0( 1) 2{ 3} 4; 5= 6+ 7* 8> 9< 10,11‘ 12整型常数30main 20int 21if 22then 23else 24return 25出错100六、处理程序例和处理结果例例1:源程序:main(){y=x-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{")(0,"y")(6,"=")(0,"x")(,d"-(20,"1")(5,";")(4,")")例2:源程序main(){int a,b;6:a;b=a-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{" }(21,”int”)(0,"a")(11,",")(0,"b")(5,”;”)(30,"6")(100,":")(0,"a")(5,”;”)(0,"b")(6,"=")(0,"a")(100,"-")(30,"1")(5,”;”)(4," })" )七、参考代码#include <io.h>#define n 100main(){char a[n],t;int i,r=1,m=0;a[0]='\n';for(i=1;;i++){scanf("%c",&t);if(t!='#') {a[i]=t; r++;}else break;}for(i=1;i<r;i++){ compare(a[i],a,&i,&m); }if(m==1){clrscr();printf("error"); }getch();}int compare(char c,char a[],int *i,int *m){if(c=='(') printf("( 1\n");else if(c==')') printf(") 2\n");else if(c=='{') printf("{ 3\n");else if(c=='}') printf("} 4\n");else if(c==';') printf("; 5\n");else if(c=='=') printf("= 6\n");else if(c=='+') printf("+ 7\n");else if(c=='*') printf("* 8\n");else if(c=='>') printf("> 9\n");else if(c=='<') printf("< 10\n");else if(c==',') printf(", 11\n");else if(a[*i-1]==' '|| a[*i-1]=='\n'){if(c=='i'){if(a[*i+1]=='n' && a[*i+2]=='t'&& a[*i+3]==' '){printf("int 21\n");*i=*i+2;return *i;}else if(a[*i+1]=='f'&& a[*i+2]==' '){printf("if 22\n");*i=*i+1;return *i;}}else if(c=='t'){if(a[*i+1]=='h' && a[*i+2]=='e' && a[*i+3]=='n' && a[*i+4]==' '){printf("then 23\n");*i=*i+3;return *i;}}else if(c=='e'){if(a[*i+1]=='l' && a[*i+2]=='s' && a[*i+3]=='e' && a[*i+4]==' '){printf("else 24\n");*i=*i+3;return *i;}}else if(c=='r'){if(a[*i+1]=='e' && a[*i+2]=='t' && a[*i+3]=='u' && a[*i+4]=='r' && a[*i+5]=='n' && a[*i+6]==' '){printf("return 25\n");*i=*i+5;return *i;}}}if(a[*i]>='0' && a[*i]<='9' && a[*i-1]=='='){ loop2:printf("%c",a[*i]);if(a[*i+1]>='0' && a[*i+1]<='9') {*i=*i+1;goto loop2; }elseprintf(" 20\n");}else if(a[*i]>='a' && a[*i]<='z' || a[*i]>='A' && a[*i]<='Z' || a[*i]>='0' && a[*i]<='9'){ loop1:printf("%c",a[*i]);if(a[*i+1]>='a' && a[*i+1]<='z' || a[*i+1]>='A' && a[*i+1]<='Z' || a[*i+1]>='1' && a[*i+1]<='9') {*i=*i+1;goto loop1; }elseprintf(" 0\n");}else if(a[*i]!='(' && a[*i]!=')' && a[*i]!='{' && a[*i]!='}' &&a[*i]!=';' && a[*i]!='+' && a[*i]!='<' && a[*i]!='>' && a[*i]!=',' && a[*i]!='=' && a[*i]!=' '&& a[*i]!='#' && a[*i]!='\n') *m=1;}。
实验1 词法分析程序一、实验目的与要求1.复习正规文法、正规式、有限自动机之间的相互转换的原理及技术;2.学会使用Visual C++等高级语言编程实现上述转换,并能合理显示结果;3.以C++的一个真子集为案例,具体分析词法分析程序的设计步骤、基本架构及代码编制,并通过一定实例验证其可行性,以加深对词法分析原理的理解;4.通过本次实验,使学生理解模块化程序设计的思想,从而从全局角度领会一个完整软件的设计精髓,为后续试验的顺利完成奠定坚实的基础。
二、实验仪器及设备1.微型电子计算机80台2.配置Windows 2000及以上版本操作系统3.安装Visual C++6.0/Visual C#2000/Delphi6.0等以上版本的开发环境三、实验内容及步骤(一)正规文法与有限自动机的相互转换1.正规文法⇒有限自动机已知某正规文法G[S]如下:S→aAS→bBS→εA→aBA→bAB→aSB→bAB→ε请编程实现:(1)将G[S]转换为NFA;(2)将上述得到的NFA确定化为DFA;(3)再将DFA最简化为MFA。
2.有限自动机⇒正规文法已知某有限自动机NFA M=(Q,∑,f,q0,Z)如下:状态集:Q={1,2,3,4,5,6,7,8,9}字母表:∑={a,b}转移函数:f(1,a)=5f(1,ε)=2f(1,a)=4f(5,ε)=6f(2,b)=3f(4,ε)=7f(6,ε)=2f(6,b)=9f(3,ε)=8f(8,a)=9f(7,b)=9初态:q0=1终态集:Z={6,7,9}请编程实现:(1)首先将此NFA确定化为DFA;(2)再将得到的DFA最简化为MFA;(3)最后,将MFA转化为正规文法(左线性或右线性均可)。
(二)编程实现MiniC++的词法分析这里的MiniC++为C++语言的一个真子集,其语法结构与C++类似。
基本组成如下:(1)关键字有18个,分别为:void、int、char、bool、float、double、if、else、switch、case、default、break、continue、do、while、for、return以及struct等。
编译原理实验一词法分析1.实验目的通过实验掌握词法分析的理论、原理和方法,为语法分析做准备。
2.实验内容:a)十六进制数识别器:规定是:必须以十六进制数字打头,以H结尾,十六进制数中允许使用的数字为0-9,字母为A,B,C,D,E, F(分别表示0~15)。
试设计一个DFA,使它能识别无符号的十六进制整数,并编制相应的识别程序。
输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。
输出:标识出规范的符号串与不合规范的符号串。
b)词法分析:设计、编制、调试一个识别一个Little语言单词的词法分析程序(见附录1)。
输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。
输出:二元组。
3.实验要求:(1)上机前编写完整的实验报告,报告中要体现分析→设计→实现等几个过程;如无实验报告,则取消本次上机资格,实验成绩以0分记。
(2)严禁相互抄袭,否则实验成绩以0分记;(3)有完整的源代码,源码有规范的注释,无明显的语法错误;4.实验步骤(1)分析与设计a、文法:该语言的十六进制,如:0aH,77H,7BH等由以数字打头及以H结尾;该语言的标识符,如:Num,a3,go等由A到Z(or a到z)和0至9所组成;该语言的无符号的十进制,如:8,90,123等由0到9之间的任意数字组成。
由以上可得出该语言的文法可表示如下:G(S) = (VN,VT,P,S)其中VN={S,X’,Y’,Z’,M’,W’,α,β,γ,μ,υ,ω}VT= {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}α= 0|1| 2|3|4|5|6|7|8|9β= a|b|c|d|e|f|A|B|C|D|E|Fγ=g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|G|H|I|G|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|ZS →X’|Y’|Z’X’→υ|υM’M’→ω|ωM’υ→β|γω→α|β|γY’→α|αY’Z’→αH|αW’HW’→μ|μW’μ→α|β可见,上式方法中,X’表示出了语言的标识符,而Y’表示出了语言的无符号的十进制,Z’表示出了语言中的十六进制。
《编译系统设计实践》实验项目一:词法分析指导老师:陈晖组长:许堃组员:一、实验目的词法分析的目的是将输入的源程序进行划分,给出基本符号(token)的序列,并掠过注解和空格等分隔符号。
基本符号是与输入的语言定义的词法所规定的终结符。
二、实验内容本实验要求学生编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续进行)三、程序设计与实现程序功能描述:程序从文本读入一段程序代码,对每一个字符进行分析,识别出各个具有独立意义的单词,并依次输出各个单词的内部编码及单词符号自身值。
过程描述:过程描述:先从文本中读入字符,定义两个指针begin和forward,begin指向每一个词素的首个字符,forward一直向前扫描,直到发现某个单词被匹配为止,一旦确定了下一个单词,forward指针将指向该词素结尾的字符,确定词素后,根据内部编号输出其编号和自身值。
数据结构:数组程序流程图:正则表达式:标识符 id->letter_(letter_|digit)*无符号数 number->digit optitionalfraction optionalexponent 空白符 ws->(blank|tab|newline)+ 关系运算符 relop-> <|>|<=|>=|=|<> 运算符 operator->+|-|*|/DFA 图:=|<>|<|>|<=|>=|+|-|*|/ a —z A--Z0--9;| ( | ) | ,| [ | ] | .开始(每个词素首个字符)符号转化 符号转化符号转化符号转化关键字?标识符?结束startdelim22other24 23*19 12141316151817 startotherdigit. digit E+ | -digitdigit digitdigit Edigit *startletter9other 11 10letter/dig*start<other= 67 8return(relop, LE) 54>= 123other>=* * return(relop, NE)return(relop, LT)return(relop, EQ)return(relop, GE)return(relop, GT)10四、程序测试第一组测试:输入:输出:第二组测试:输入:输出:第三组测试:输入:输出:五、小组成员分工与实验小结由于有一段时间没有编程序,而且实验本身也有些难度,所以在实验初期遇到了很大阻碍,不知道该从何下手。
编译原理实验报告******************************************************************************* ******************************************************************************* PL0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。
PL/0语言文法的EBNF表示如下:<程序>::=<分程序>.<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句><常量说明> ::=CONST<常量定义>{,<常量定义>};<常量定义> ::=<标识符>=<无符号整数><无符号整数> ::= <数字>{<数字>}<变量说明> ::=V AR <标识符>{, <标识符>};<标识符> ::=<字母>{<字母>|<数字>}<过程说明> ::=<过程首部><分程序>{; <过程说明> };<过程首部> ::=PROCEDURE <标识符>;<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句><写语句>|<空><赋值语句> ::=<标识符>:=<表达式><复合语句> ::=BEGIN <语句> {;<语句> }END<条件语句> ::= <表达式> <关系运算符> <表达式> |ODD<表达式><表达式> ::= [+|-]<项>{<加法运算符> <项>}<项> ::= <因子>{<乘法运算符> <因子>}<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’<加法运算符> ::= +|-<乘法运算符> ::= *|/<关系运算符> ::= =|#|<|<=|>|>=<条件语句> ::= IF <条件> THEN <语句><过程调用语句> ::= CALL 标识符<当循环语句> ::= WHILE <条件> DO <语句><读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’<写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’<字母> ::= a|b|…|X|Y|Z<数字> ::= 0|1|…|8|9【预处理】对于一个pl0文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。
实验一词法分析有如下算术运算文法:1) E->E+T2) E->E-T3) E->T4) T->T*F5) T->T/F6) T->F7) F->(E)8) F->I9) I->十进制实数|十进制整数|十六进制实数|?十六进制整数|八进制实数|八进制整数10) 十进制实数->(0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*).(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9) *11) 八进制实数->0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*.(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7) *12) 十六进制实数 ->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b |c|d|e|f)* .(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6 |7|8|9|a|b|c|d|e|f) *13) 十进制整数->0 | (1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9) * 14) 八进制整数->¥0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7) *15)十六进制整数->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f) *单词分类:运算符:+ - * / ()常数:十进制实数十进制整数十六进制实数十六进制整数|八进制实数八进制整数1. 实验目的实现一个词法分析程序,将输入字符串流分解成单词流供语法分析使用。
2. 实验要求输入算术运算式,输出分解后的单词流,例如:输入(+)*12输出:运算符 (/八进制实数运算符 +十六进制实数运算符 )运算符 *十进制整数 12注意:输入可以是键盘输入,也可以是文件输入如果单词输入错误,必须有提示,例如:输入 12a+45*013468-0x23a3输出.错误数据12a运算符 +十进制整数 45运算符 *错误数据 0123468运算符 -十六进制整数 0x23a3){nowChar[a_long]=*a;doc=1;—*a++;a_long++;}nowChar[a_long]='\0'; ){nowChar[a_long]=*a;doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) ){|nowChar[a_long]=*a;doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) ||(*a=='_'))){ d=id; ind[i]=kinds[id][i];link[link_long].=y;} ind[i]=a[i];link[link_long].[0]='-';—link[link_long].[1]='\0';}link_long++; } ind[i]=kinds[id][i]; i]=a[i];link[link_long].[i]='\0'; }else x; }link_long++; ;i++)x=x*10+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/10;y=y+x; ;i++)x=x*8+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)'y=(y+(a[i]-48))/8;y=y+x; ;i++) ;i--)y=(y+(a[i]-48))/16;y=y+x; //整数部分与小数部分换算后相加printf("REAL16\t%f\n",y); //存入结构数组save(a,id,x,y);return;}printf("Wrong Enter"); //所得的具体类型值为,则输入有错误return;}。
实验一词法分析1.实验要求(1)从源程序文件中读取有效字符并将其转换成二元组内部表示形式输出。
(2)掌握词法分析的实现方法。
(3)实验时间4学时。
(4)实验完成后,要提交实验报告(包括源程序清单)。
2.实验内容2.1主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。
主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。
建议从文件中读取要分析的符号串。
2.2词法分析过程考虑该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。
对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将三:主流程图如下:四:实验思路(1)我首先把这个单词的种类分成了五类,包括:关键字、标识符、常数、算符、界符。
然后利用状态转换图进行单词的识别(2)对于关键字、算符、界符。
因为这些单词的个数有限。
所以我单独给每个单词一个种别编码。
能够做到每个单词的种别编码是不一样的。
而对于常数和标识符,我先把它们分别单独的作为一类,然后定义一个二维数组,分别存放这个单词的名称和编码。
而这个编码就是这个单词在这个二维数组中的位置;当遇到新的标识符或常数,就把这个单词放入到相应的数组中。
(3)然后构造一个状态转换图的程序。
把每次得到的单词先暂时存放在temp 二维数组中。
然后用这个临时的二维数组去确定这个单词是何种类别五:实验代码using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Word{public partial class Form1 : Form{public Form1(){InitializeComponent();}char[] receive; //从输入得到的源程序char ch; //这是从源程序读取的一个字符string cache; //暂存的单词int index; //记录取到哪个位置了key_word temp; //用来临时存放得到这个单词struct key_word{public string key_name;public int number;}struct num_word{public string num_name;public int number;}struct ID_word{public string ID_name;public int number;}public int num_index;public int ID_index;DataTable dt;private void button1_Click(object sender, EventArgs e){dt = new DataTable();dt.Columns.Add("助记符");dt.Columns.Add("外部编码");dt.Columns.Add("内部编码");dt.Columns.Add("类型");receive = textBox1.Text.ToCharArray();index = 0;num_index = 0;ID_index = 0;;while (index < receive.Length){cache = null;Get_Word();if (temp.number == 1){int i = 0;int flag = 0;if (num_index == 0){Num[num_index].num_name = temp.key_name;Num[num_index].number = num_index;num_index++;}else{for (i = 0; i < num_index; i++){if (Num[i].num_name == temp.key_name){flag = i;break;}}if (i >= num_index){Num[num_index].num_name = temp.key_name;Num[num_index].number = num_index;flag = num_index;num_index++;}}DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;dr["内部编码"] = +Num[flag].number;dr["类型"] = "常数";}else if (temp.number == 0){int i = 0;int flag = 0;if (ID_index == 0){ID[ID_index].ID_name = temp.key_name;ID[ID_index].number = ID_index;ID_index++;}else{for (i = 0; i < ID_index; i++){if (ID[i].ID_name == temp.key_name){flag = i;break;}}if (i >= ID_index){ID[ID_index].ID_name = temp.key_name;ID[ID_index].number = ID_index;flag = ID_index;ID_index++;}}DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;dr["外部编码"] = temp.number;dr["内部编码"] = ID[flag].number;dr["类型"] = "标识符";}else{DataRow dr = dt.NewRow();dt.Rows.Add(dr);dr["助记符"] = temp.key_name;if (temp.number >= 15 && temp.number <= 30){dr["类型"] = "运算符";}else if (temp.number >= 31 && temp.number <= 40){dr["类型"] = "界符";}else{dr["类型"] = "关键字";}}}this.dataGridView1.DataSource = dt;}key_word[] Key;num_word[] Num;ID_word[] ID;private void Form1_Load(object sender, EventArgs e){index = 0;Key = new key_word[41];Key[0].key_name = "$ID"; Key[0].number = 0; //标识符Key[1].key_name = "$INT"; Key[1].number = 1; //数Key[2].key_name = "int"; Key[2].number = 2; Key[3].key_name = "float"; K ey[3].number = 3;Key[4].key_name = "void"; Key[4].number = 4; Key[5].key_name = "const"; Key[5].number = 5; Key[6].key_name = "if"; Key[6].number = 6; Key[7].key_name = "el se"; Key[7].number = 7;Key[8].key_name = "do"; Key[8].number = 8; Key[9].key_name = "while"; Key[9].number = 9; Key[10].key_name = "scanf"; Key[10].number = 10; Key[11].key_nam e = "printf"; Key[11].number = 11;Key[12].key_name = "return"; Key[12].number = 12; Key[13].key_name = " main"; Key[13].number = 13; Key[14].key_name = "read"; Key[14].number = 14;Key[15].key_name = "+"; Key[15].number = 15;Key[16].key_name = "-"; Key[16].number = 16; Key[17].key_name = "*"; K ey[17].number = 17; Key[18].key_name = "/"; Key[18].number = 18; Key[19].key_name = "%"; Key[19].number = 19;Key[20].key_name = "="; Key[20].number = 20; Key[21].key_name = "=="; Key[21].number = 21; Key[22].key_name = ">"; Key[22].number = 22; Key[23].key_name = "<"; Key[23].number = 23;Key[24].key_name = "!="; Key[24].number = 24; Key[25].key_name = ">="; Key[25].number = 25; Key[26].key_name = "<="; Key[26].number = 26; Key[27].key_na me = "&&"; Key[27].number = 27;Key[28].key_name = "||"; Key[28].number = 28; Key[29].key_name = "!"; K ey[29].number = 29; Key[30].key_name = "<>";Key[30].number = 30;Key[31].key_name = "("; Key[31].number = 31;Key[32].key_name = ")"; Key[32].number = 32; Key[33].key_name = "{"; K ey[33].number = 33;Key[34].key_name = "}"; Key[34].number = 34; Key[35].key_name = ";"; K ey[35].number = 35;Key[36].key_name = ","; Key[36].number = 36; Key[37].key_name = "\""; K ey[37].number = 37; Key[38].key_name = "'"; Key[38].number = 38; Key[39].key_name = "++"; Key[39].number = 39;Key[40].key_name = "--"; Key[40].number = 40;Num = new num_word[1024];ID = new ID_word[1024];}public void GetChar() //得到一个字符{if (index < receive.Length){ch = receive[index];index++;}else{ch = '\0';}}public void GetNotKong() //得到一个不是空的字符{while (index < receive.Length){ch = receive[index];index++;if (ch != ' ' && ch != '\r' && ch != '\0' && ch != '\n'){break;}}}public void ConCat() //连接{cache += ch;}public bool IsLetter() //判断是不是字母{if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {return true;}else{return false;}}public bool IsDigit() //判断是不是数字{if (ch >= '0' && ch <= '9'){return true;}else{return false;}}public int Get_Number() //得到这个单词的编码{for (int i = 0; i < 41; i++){if (string.Equals(cache, Key[i].key_name)){return Key[i].number;}}{return 0;}}public void retrace() //退回一个单词{if (ch != '\0'){index--;}private void Get_Word(){int count;GetNotKong();if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {ConCat();GetChar();while (IsLetter() || IsDigit()){ConCat();GetChar();}retrace();count = Get_Number();temp.key_name = cache;if (count == 0){temp.number = 0;}else{temp.number = Key[count].number;}}else if (ch >= '0' && ch <= '9'){ConCat();GetChar();while (IsDigit()){ConCat();GetChar();}retrace();temp.key_name = cache;temp.number = 1;}else if (ch == '+')ConCat();GetChar();if (ch == '+'){ConCat();temp.key_name = cache;temp.number = 39;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '-'){ConCat();GetChar();if (ch == '-'){ConCat();temp.key_name = cache;temp.number = 40;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '<'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 26;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '>'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 25;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '='){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 21;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '!'){ConCat();GetChar();if (ch == '='){ConCat();temp.key_name = cache;temp.number = 24;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '&'){ConCat();GetChar();if (ch == '&'){ConCat();temp.key_name = cache;temp.number = 27;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else if (ch == '|'){ConCat();GetChar();if (ch == '|'){ConCat();temp.key_name = cache;temp.number = 28;}else{retrace();temp.key_name = cache;temp.number = Get_Number();}}else{ConCat();temp.key_name = cache;temp.number = Get_Number();}}}}六:实验截图(1)我测试的程序为void main(){ int a=20;int b=15;if(a==20)printf("A");if(b==20)printf("B");}七:实验心得通过这次实验、我对于词法分析需要做的任务有了一个更加深刻的理解。