实验一 词法分析
实验1 词法分析

实验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)本次实验主要的函数及功能教材上提供的很全面, 因此本次实验主要的工作就是对各个函数过程的实现, 做起来还是比较容易的!但对程序的几点思考使我对词法分析有了更深的认识:表结构的存储: 对与各个表的存储开始时我想到是运用数据库存储, 这样实现起来会更容易!但是数据库的引入减少了代码的量, 但却使程序脱离的底层失去了词法分析的意义;程序功能的实现:对于程序中的“++”、“--”等运算符用到了超前搜索的思想, 由于开始设计时的从简原则, 使得在这一块的实现上还存在这问题, 需要以后的继续改进;分析错误的处理: 虽然这次实验我并没有加入错误的处理程序, 但我个人认为对于错误的处理是程序设计中一个很重要的环节, 他对程序的健壮性用很大的影响。
词法分析报告设计实验报告材料(附代码)

实验一词法分析设计实验学时:4实验类型:综合实验要求:必修一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验容用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(码,属性)二元式表示。
(属性值——token的机表示) (5)如果发现错误则报告出错(6)根据需要是否填写标识符表供以后各阶段使用。
单词的基本分类:◆关键字:由程序语言定义的具有固定意义的标识符。
也称为保留字例如if、for、while、printf ;单词种别码为1。
◆标识符:用以表示各种名字,如变量名、数组名、函数名;◆常数:任何数值常数。
如125, 1,0.5,3.1416;◆运算符:+、-、*、/;◆关系运算符:<、<=、= 、>、>=、<>;◆分界符:;、,、(、)、[、];三、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。
3、根据测试数据进行测试。
测试实例应包括以下三个部分:◆全部合法的输入。
◆各种组合的非法输入。
◆由记号组成的句子。
4、词法分析程序设计要求输出形式:例:输入VC++语言的实例程序:If i=0 then n++;a﹤= 3b %);输出形式为:单词二元序列类型位置(行,列)(单词种别,单词属性)for (1,for ) 关键字(1,1)i ( 6,i ) 标识符(1,2)= ( 4,= ) 关系运算符(1,3)0 ( 5,0 ) 常数(1,4)then ( 1,then) 关键字(1,5)n (6,n ) 标识符(1,6)++ Error Error (1,7);( 2, ; ) 分界符(1,8)a (6,a ) 标识符(2,1)﹤= (4,<= ) 关系运算符(2,2)3b Error Error (2,4)% Error Error (2,4)) ( 2, ) ) 分界符(2,5);( 2, ; ) 分界符(2,6)实验报告正文:◆功能描述:该程序具有词法分析功能,即面对一段程序源代码,通过该程序,能检查出源代码是否由词法错误。
实验1 词法分析实验报告

p=0;
row=1;
cout<<"Please input string:"<<endl;
do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!='#');
p=0;
do
{
scaner();
switch(syn)
{
case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;
实验二时发现怎么出结果都会出现一个缺:=错误,便回头检查代码才发现实验一时的scaner()函数最后的:和:=的种别码互相写错了,所以回过头来重新修正了代码和实验结果图。
case -1: cout<<"Error in row"<<row<<"!"<<endl; break;
case -2: row=row++;break;
default: cout<<"("<<syn<<","<<token<<")"<<endl;break;
}
}
while (syn!=0);
}
四、结果验证
{
syn=21;
token[m++]=ch;
}
else if(ch=='=')
编译原理 实验一 词法分析

《编译系统设计实践》实验项目一:词法分析指导老师:陈晖组长:许堃组员:一、实验目的词法分析的目的是将输入的源程序进行划分,给出基本符号(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四、程序测试第一组测试:输入:输出:第二组测试:输入:输出:第三组测试:输入:输出:五、小组成员分工与实验小结由于有一段时间没有编程序,而且实验本身也有些难度,所以在实验初期遇到了很大阻碍,不知道该从何下手。
实验一 词法分析

实验一词法分析一、实验目的:通过本实验理解词法分析的整个过程,处理对象和处理的结果,了解词法分析在整个编译过程中的作用。
二、实验学时:2学时。
三、实验内容根据给出的简单语言的词法构成规则和单词集合,编制词法分析程序,要求能用给定的简单语言书写的源程序进行词法分析,同时建立相应的符号表文件存放正确的单词。
输出分析结果于文件中,包括:(1)正确的单词符号及其单词种类的序对二元组。
具体输出形式为:二元组:(单词种类,单词内码值)单词种类见五。
四、实验方法构造识别单词集的自动机,编写程序实现。
五、实验的处理单词集六、处理程序例和处理结果例例1:源程序:main(){y=x-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{")(0,"y")(6,"=")(0,"x")(100,"-")(20,"1")(5,";")(4,")")例2:源程序main(){int a,b;b!=a-1;}处理结果:(26,"main")(1,"(")(2,")")(3,"{" })(21,”int”)(0,"a")(11,",")(0,"b")(5,”;”)(0,"b")(100,"! ")(6,"=")(0,"a")(100,"-")(30,"1")(5,”;”)(4,”}”)七、实验报告要求给出单词识别的状态转换图;带有注释(简单说明)的源程序。
实验一词法分析报告

实验一词法分析1.实验要求(1)从源程序文件中读取有效字符并将其转换成二元组内部表示形式输出。
(2)掌握词法分析的实现方法。
(3)实验时间4学时。
(4)实验完成后,要提交实验报告(包括源程序清单)。
2.实验内容2.1主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。
主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。
建议从文件中读取要分析的符号串。
2.2词法分析过程考虑该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。
对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将常数存入数组中ci 中,并记录其在表中的位置。
三:主流程图如下:四:实验思路(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.T asks;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;DataT able dt;private void button1_Click(object sender, EventArgs e) {dt = new DataT able();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;}}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["外部编码"] = temp.number;dr["内部编码"] = +Num[flag].number;dr["类型"] = "常数";}else if (temp.number == 0){int i = 0;int flag = 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;dr["外部编码"] = temp.number;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"; Key[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 = "else"; 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_ name = "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 = "*"; Key[17].number = 17; Key[18].key_name = "/"; Key[18].number = 18; Key[19].key_n ame = "%"; 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].ke y_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_name = "&&"; Key[27].number = 27;Key[28].key_name = "||"; Key[28].number = 28; Key[29].key_name = "!"; Key[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 = "{";Key[33].number = 33;Key[34].key_name = "}"; Key[34].number = 34; Key[35].key_name = ";"; Key[35].number = 35;Key[36].key_name = ","; Key[36].number = 36; Key[37].key_name = "\" "; Key[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");}七:实验心得通过这次实验、我对于词法分析需要做的任务有了一个更加深刻的理解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一词法分析
有如下算术运算文法:
1) E->E+T
2) E->E-T
3) E->T
4) T->T*F
5) T->T/F
6) T->F
7) F->(E)
8) F->I
9) 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. 实验要求
输入算术运算式,输出分解后的单词流,例如:
输入(0124.3+0x35a.4f)*12
输出:
八进制实数0124.3
运算符+
十六进制实数0x35a.4f
运算符)
运算符*
十进制整数12
注意:
●输入可以是键盘输入,也可以是文件输入
●如果单词输入错误,必须有提示,例如:
输入12a+45*013468-0x23a3
输出
错误数据12a
运算符+
十进制整数45
运算符*
错误数据0123468
运算符-
十六进制整数0x23a3
3.实验代码。