实验一 词法分析

合集下载

实验1 词法分析

实验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 词法分析实验报告

实验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");}七:实验心得通过这次实验、我对于词法分析需要做的任务有了一个更加深刻的理解。

词法分析设计实验报告(附代码)

词法分析设计实验报告(附代码)

实验一词法分析设计实验学时: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.词法分析

实验1.词法分析

实验1. 词法分析实验报告一、实验目的调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求1、待分析的简单语言的词法(1)关键字:begin if then while do end所有关键字都是小写。

(2)运算符和界符::= + –* / < <= <> > >= = ; ( ) #(3) 其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)*NUM=digit digit *(4)空格由空白、制表符和换行符组成。

空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。

2、各种单词符号对应的种别码3、词法分析程序的功能输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

三、源程序代码#include<stdio.h>#include<string.h>#include<iostream>using namespace std;char prog[80],token[8];char ch;int syn,p,m=0,n,sum=0; //p是缓冲区prog的指针,m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};//关键字void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' ') //跳过空字符ch=prog[p++];//执行语句1;if((ch>='a')&&(ch<='z')||(ch>='A')&&(ch<='Z'))//判断是否是字母字符{ m=0;while((ch>='A')&&(ch<='Z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}elseif(ch>='0'&&ch<='9'){ sum=0;while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11; //执行语句2;}elseswitch(ch){case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else {syn=23;p--;}break;case'<': m=0;token[m++]=ch; //补充程序;ch=prog[p++];if(ch=='='){syn=22;token[m++]=ch;}else {syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'-':syn=13;token[0]=ch;break;case'+':syn=14;token[0]=ch;break;case'*':syn=15;token[0]=ch;break;case'/':syn=16;token[0]=ch;break;case';':syn=26;token[0]=ch;break;case')':syn=27;token[0]=ch;break;case'(':syn=28;token[0]=ch;break;case'#':syn=0;token[0]=ch;break;default:syn=-1;}}void main(){p=0;cout<<"\n please input string: \n";do {ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){ case 11: cout<<"(11,"<<sum<<")"; break;case -1: cout<<"error!"; break;default: cout<<"("<<syn<<","<<token<<")";}}while (syn!=0);}四、结果验证(1) 给定源程序begin x:=9;if x>0 then x:=2*x+1/3; end#输出结果。

[实验1] 词法分析

[实验1] 词法分析

[实验1] 词法分析《编译原理》课程实验实验1实验1 词法分析1.实验说明实验题目:词法分析器的设计与实现实验目的:加深对词法分析基本理论的理解,锻炼实现词法分析器程序的实践能力。

实验过程:(1)按照给定的表达式的词法要求,构造分DFA;(2)整合各分DFA,构造总DFA;(3)设计词法分析器算法;(4)根据DFA实现单词识别程序;(5)保存词法分析结果到文件。

输入:(1)输入为数学表达式,其中可能含有空格;(2)运算符包括+,-,*,/,(,)。

(3)运算数包括自然数和变量;(4)变量以下划线或字母开头,其后可以跟字母、下划线或数字。

输出:输出到文本文件。

每个单词输出为二元组(单词类别,单词值)。

单词类别编码见下表:编码 0 1 2例1:表达式xy-(x-100)/2的输出2,xy 0,- 0,( 2,x 0,- 1,100 0,) 0,/ 1,2第-1-页类别说明算符常量(自然数)变量《编译原理》课程实验实验1例2:表达式2x * (_x2 �C y)的输出1,2 2,x 0,* 0,( 2,_x2 0,- 2,y 0,)注意: 2x识别为两个单词2和x,虽然2x在语法上不合法(中间需要一个运算符),但在词法分析时不能发现这个错误。

例3:表达式x y * 012注意:该表达式x和y之间有一个空格,该词法分析程序的预处理程序简单的将空格全部去掉,因此与表达式xy*012的输出相同。

2,xy 0,* 1,0122.分DFA 2.1 自然数 2.2 标识符 2.3 算符3.合DFA说明:(1)状态0为初态。

(2)状态4为程序正常出口,说明识别出一个单词,单词类别由前一个状态决定。

(3)状态5为出错状态。

(4)为进一步确定下一步要做什么,需要向前“假读”一个单词。

状态2、3的假读是必须的,状态1是为了程序上的统一进行假读。

4.数据结构说明 4.1 单词结点单词序列采用链表存储,每个结点表示一个单词,用如下结构表示:第-2-页《编译原理》课程实验实验1struct WORDNODE {unsigned short byType; // 单词类别 char Value[MAX_DATA_LEN]; // 值WORDNODE *pNext; // 下一结点 };单词链表结构在WordAnalysis()函数中创建,并由此函数返回头结点指针;在main()函数中销毁。

实验一词法分析

实验一词法分析

编译原理实验一词法分析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’表示出了语言中的十六进制。

实验一(词法分析)

实验一(词法分析)

实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。

2、深刻领会状态转换图的含义,逐步理解有限自动机。

3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。

二.实验内容计算机程序设计语言的编译程序的词法分析部分实现。

给出算法的流程图及有穷状态自动机的模型(可以用矩阵或者状态图表示)从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。

为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。

(2)空白符仅仅是空格、回车符、制表符。

(3)代码是自由格式。

(4)注释应放在花括号之内,并且不允许嵌套三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符 (空格、回车符、制表符)(4)列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。

(2)词法分析程序当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。

(3)标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。

(选做)四.实验结果(1)测试用例(2)实验结果的屏幕截图五.实验总结。

实验一:词法分析JN

实验一:词法分析JN

实验一:词法分析一、实验目的给出PL/0文法规范,要求编写PL/0语言的词法分析程序。

二、实验准备微机CPU主频1.3G以上,128M内存,安装好C语言,PASCAL语言,或C++。

三、实验时间6学时四、实验内容已给PL/0语言文法,输出单词(关键字、专用符号以及其它标记)。

二.实验内容1、格式输入:源程序文件。

输出:关键字、专用符号以及其它标记。

2、编译对象:包含如下基本内容 1)变量说其它标记: 明语句 2)赋值语句 3)条件转移语句 4)表达式(算术表达式和逻辑表达式) 5)循环语句 6)过程调用语句3、实现过程本次实验所用的语言为标准C,以下同。

本功能实现的主函数为getToken函数。

通过从文件中读取字符到缓冲区中并由C语言字符的状态转换图流程判断返回一个字符(Token)。

分析出来的Token主要分为关键字,专用符号,标记符号。

本实验实现的C语言的基本词法如下:关键字: els if int return void while专用符号: + - * / < >= == != = ; , ( ) [ ] { } /* */其它标记: id numID = letter letter*NUM = digit digit*letter = a|b|...|z|A|B|...|Z|ditit= 0|1|...|9通过在C语言中定义一个枚举类型来识别这些符号:PL/0语言的EBNF表示<常量定义>::=<标识符>=<无符号整数>;<标识符>::=<字母>={<字母>|<数字>};<加法运算符>::=+|-<乘法运算符>::=*|/<关系运算符>::==|#|<|<=|>|>=<字母>::=a|b|…|X|Y|Z<数字>::=0|1|2|…|8|94、主体结构的说明在这里说明部分告诉我们使用的LETTER,DIGIT, IDENT(标识符,通常定义为字母开头的字母数字串)和STR(字符串常量,通常定义为双引号括起来的一串字符)是什么意思.这部分也可以包含一些初始化代码.例如用#include来使用标准的头文件和前向说明(forward ,references).这些代码应该再标记"%{"和"%}"之间;规则部分&gt;可以包括任何你想用来分析的代码;我们这里包括了忽略所有注释中字符的功能,传送ID名称和字符串常量内容到主调函数和main函数的功能.5、实现原理程序中先判断这个句语句中每个单元为关键字、常数、运算符、界符,对与不同的单词符号给出不同编码形式的编码,用以区分之。

词法分析实验报告(实验一)

词法分析实验报告(实验一)

词法分析实验报告(鲍小伟20032320)一.实验目的:通过设计、编程、调试出一个具体词法分析程序,加深对词法分析原理的理解,掌握其设计方法。

二.实验内容:用C/C++实现对PASCAL的子集程序设计语言的词法识别程序。

三.实验要求与原理:(1)实验要求:将该语言的源程序,即相应字符流转换成内部表示,并对标识符填写相应的符号表供编译程序以后各阶段使用,输出的单词符号格式为二元组(单词种别,单词在标识符表中的地址),标识符表格式有“序号”和“标识符本身的值”两项。

写出设计报告,内容为:状态转换图、单词符号及内部表示、符号表、出错处理、编程方法等。

(2)实验原理:状态转换图:空白8923单词符号及内部表示:标志符表和常数表:void getchar();//将下一输入字符读到ch中,指针后移一字符位置void getbc();//保证ch是一个非空白字符void concat();//将ch连接到字符串stroken的末尾void retract();//置ch为空白字符,指针前移一字符位置int isdigit();//判断是否整数int isletter();//首字母的判断int reserve();//对stroken进行关键字表的查找,返回其编码值int insertid();//将stroken中的标识符插入符号表,返回在符号表中的位置int insertconst();//将stroken中的常数插入常数表,返回在常数表中的位置四.主要源代码:Scanner::Scanner(char str[], int n) //构造函数{strcpy(buffer, str);length = n;i = j = 0;}int Scanner::isdigit()//判断是否整数{if(ch>='0' && ch<='9')return 1;elsereturn 0;}int Scanner::isletter()//首字母的判断{if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))return 1;elsereturn 0;}void Scanner::getchar() //将下一输入字符读到ch中,指针后移一字符位置{ch = buffer[i];i++;}void Scanner::getbc() //保证ch是一个非空白字符{while(ch == ' ')getchar();}void Scanner::concat() //将ch连接到字符串stroken的末尾{strtoken[j] = ch;j++;}void Scanner::retract() //置ch为空白字符,指针前移一字符位置{ch = ' ';i--;}int Scanner::reserve() //对stroken进行关键字表的查找,返回其编码值{int i, flag = 0;for(i=0; i<15; i++){if( strncmp(reservechar[i],strupr(strtoken), j) == 0 ){flag = 1;break;}}if(flag == 1) return i+1;else return 0;}int Scanner::insertid() //将stroken中的标识符插入符号表,返回在符号表中的位置{for(int a = 0; a < m; a++)for(int b = 0; b < x[a]; b++)if( strncmp(&id[a][0], strtoken, j) == 0 ){return m+1;break;}for(a = 0; a < j; a++)id[m][a] = strtoken[a];x[m] = j;m++;return m;}int Scanner::insertconst() //将stroken中的常数插入常数表,返回在常数表中的位置{for(int i = 0; i < j; i++)cst[n][i] = strtoken[i];y[n] = j;n++;return n;}void Scanner::scan(){while(i < length){j = 0;int code, value;strcpy(strtoken, " "); //置strtoken为空串getchar();getbc();if(isletter()) //如果打头的是字母{while(isletter() || isdigit()){concat();getchar();}retract();code = reserve();if(code == 0) //如果扫描到的是标识符{value = insertid();cout<<"<34,"<<value<<">"<<'\n';}else cout<<"<"<<code<<",*>"<<'\n'; //如果扫描到的是关键字}else if(isdigit()) //如果打头的是数字{while(isdigit()){concat();getchar();}retract();value = insertconst();cout<<"<33,"<<value<<">"<<'\n';}else if(ch == '+')cout<<"<16,*>"<<'\n';else if(ch == '-')cout<<"<17,*>"<<'\n';else if(ch == '*')cout<<"<18,*>"<<'\n';else if(ch == '/')cout<<"<19,*>"<<'\n';else if(ch == '=')cout<<"<20,*>"<<'\n';else if(ch == '<'){getchar();if(ch == '>')cout<<"<21,*>"<<'\n';else if(ch == '=')cout<<"<23,*>"<<'\n';else{retract();cout<<"<22,*>"<<'\n';}}else if(ch == '>'){getchar();if(ch == '=')cout<<"<25,*>"<<'\n';else{retract();cout<<"<24,*>"<<'\n';}}else if(ch == '.')cout<<"<26,*>"<<'\n';else if(ch == ',')cout<<"<27,*>"<<'\n';else if(ch == ';')cout<<"<28,*>"<<'\n';else if(ch == ':'){getchar();if(ch == '=')cout<<"<30,*>"<<'\n';else{retract();cout<<"<29,*>"<<'\n';}}else if(ch == '(')cout<<"<31,*>"<<'\n';else if(ch == ')')cout<<"<32,*>"<<'\n';else if(ch == '{'){while(ch != '}')getchar();}else cout<<"出错!"<<'\n';}}void main(void){fstream file;file.open("F:/20032320/20032320.txt", ios::in||ios::nocreate); //以只读方式打开file.unsetf(ios::skipws); //不跳过文本中的空格char buffer[100]; //缓冲区定义cout<<"扫描结果如下所示"<<'\n';while(file.getline(buffer, 100)){Scanner SS(buffer, strlen(buffer));SS.scan();}cout<<"标识符表如下:\n"<<"编号\t"<<"值\n";for(int i=0; i<m; i++){cout<<i+1<<'\t';for(int j=0; j<x[i]; j++)cout<<id[i][j];cout<<'\n';}cout<<"常数表如下:\n"<<"编号\t"<<"值\n";for(i=0; i<n; i++){cout<<i+1<<'\t';for(int j=0; j<y[i]; j++)cout<<cst[i][j];cout<<'\n';}}五.运行结果:程序的运行结果如下图所示:。

词法分析~实验报告

词法分析~实验报告

词法分析~实验报告实验⼀、词法分析实验专业商业软件3班姓名陈笑璞学号 201506110218⼀、实验⽬的(1)编制⼀个词法分析程序(2)词法分析是编译的第⼀个阶段,主要任务是从左⾄右逐个字符地对源程序进⾏扫描,产⽣⼀个个单词序列,⽤于语法分析。

(3)通过词法分析的练习,能够进⼀步了解编译原理。

(4)通过了解词法分析程序的设计原则、单词的描述技术、识别机制及词法分析程序的⾃动构造原理。

⼆、实验内容和要求(1)输⼊:源程序字符串(2)输出:⼆元组(种别,单词符号本⾝)。

三、实验⽅法、步骤及结果测试实验⽅法、步骤:(1)对字符串表⽰的源程序(2)从左到右进⾏扫描和分解(3)根据词法规则(4)识别出⼀个⼀个具有独⽴意义的单词符号(5)以供语法分析之⽤(6)发现词法错误,则返回出错信息2、原理分析: 我的设计思路是利⽤链队列(好处:先进先出且不浪费存储空间)进⾏存储⽤户输⼊字符串,以回车键结束(其中必须以⾮数字结尾,否则程序出错)(这是我在后来的编程⾥遇到的问题,我知道问题出在哪⾥,但我现在还解决不了,因为我是通过申请⼦针域来存储,所以我是利⽤p->next来作为判断结束条件,如果以数字结束,那p->next指向未知领域,程序出错,同时这也是很危险的),然后我是利⽤出队列来判断,如果是字母存进数组⾥,直到下⼀个字符不是字母,调⽤函数判断数组的字符串,利⽤strcmp来判断,输出数组,再清空数组;void Print(char str[])//调⽤函数来判断关键字与标识符并输出{int i=0;if(strcmp(str,"begin")==0)printf("(1,'%s')\n",str);else if(strcmp(str,"if")==0)printf("(2,'%s')\n",str);else if(strcmp(str,"then")==0)printf("(3,'%s')\n",str);else if(strcmp(str,"while")==0)printf("(4,'%s')\n",str);else if(strcmp(str,"do")==0)printf("(5,'%s')\n",str);else if(strcmp(str,"end")==0)printf("(6,'%s')\n",str);else{if(str[0]=='\0')return;printf("(10,'%s')\n",str);}memset(str,0,N);//清空数组str⾥的所有元素}结果测试:四、实验总结说实话,通过这次的编译原理词法分析的实验,我遇到了不少问题,也学到了不少的东西,因为这次实验我是想⽤我⾃⼰的想法来编写程序,我是⽤链队列来存储字符串的,也许⽤数组来存储字符串会简单点,但我不想,我还是想利⽤链队列来存储字符串,这样可以节约存储空间,还可以利⽤队列先进先出的特点,不好就是利⽤队列不够灵活,每次都要出栈判断、存储,释放p的⼦针域;虽然在编写过程中,遇到不少问题,遇到⼀个,就想办法解决⼀个,通过问朋友⽼师等,也通过发朋友圈问,还通过发博客来问⼤神们,这种途径是最有效的,也是最好的;所以每次就差⼀点就做好了,⼜会遇到⼀个新的问题,就要想办法去解决它,如今除了字符串是以数字结尾会出现问题外(暂时没找到好的⽅法),其他问题已解决。

编译原理实验报告 词法分析

编译原理实验报告 词法分析

编译原理实验一·词法分析一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

二、实验内容及要求对某特定语言A ,构造其词法规则。

该语言的单词符号包括:保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。

功能要求如下所示:·按单词符号出现的顺序,返回二元组序列,并输出。

·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。

·如果出现词法错误,报出:错误类型,位置(行,列)。

·处理段注释(/* */),行注释(//)。

·有段注释时仍可以正确指出词法错误位置(行,列)。

三、实验过程1、词法形式化描述使用正则文法进行描述,则可以得到如下的正规式:其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。

A→(ID | NUM | RES | DEL | OPR) *ID→letter(letter | didit)*NUM→digit digit*letter→a | …| z | A | …| Zdigit→0 | …| 9RES→program | begin | end | var | int | and | or | not | if | then | else | while | doDEL→( | ) | . | ; | ,OPR→+ | * | := | > | < | = | >= | <= | <>如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。

空格由空白、制表符和换行符组成。

2、单词种别定义;3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、运行环境介绍;本次实验采用win-tc进行代码的编写和编译及运行程序的运行环境为windows5、关键算法的流程图及文字解释;程序中用到的函数列表:变量ch储存当前最新读进的字符的地址strToken存放当前字符串voidmain() //主函数struct binary *lexicalAnalyze(); //词法分析的主函数,返回一个二元组的指针void GetBC(); //检查ch指向的字符是否为空格、制表或回车符,如果是则调用GetChar()直至不是上述字符void GetChar(); //ch前移一个地址单元int ConCat(); //将ch指向的字符连接到strToken之后int isLetter(); //判断ch指向的字符是否字母int isDigit(); //判断ch指向的字符是否数字int insertId(); //向标识符表中插入当前strToken的字符串int insertConst(); //将strToken的常数插入常数表中int Reserved(); //检测当前strToken中的字符串是否保留字,若是,则返回编码,否则返回0int isId(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回其编号,否则返回0int isConst(); //检测当前strToken中的字符串是否在常数表中已存在,若是,则返回其编号,否则返回0void errProc(int errType); //出错处理过程,errType是错误类型,将错误信息加入错误表中main()函数的流程图如下:lexicalAnalyze()函数的流程图如下所示:Reserved()、isId()和isConst()函数均采用了对链表的遍历算法,errProc()函数通过识别不同的错误编号,向错误链表中添加相应的错误信息。

实验一词法分析

实验一词法分析
cout<<"输出该非标示符:";
for (int i=0;i<50;i++)
{
cout<<a[i];
}
cout<<endl;
cout<<"------------字符串判断完毕------------"<<endl;
}
system("pause");
return 0;
}
Vc6.0新建空工程+源文件
{
b[k]=a[t+1]; //存放是标识符的字符
k++;
}
else if((a[t+1]>='0')&&(a[t+1]<='9')) //识别是非标识符的字符
{
c[m]=a[t+1]; //存放是单个数字的字符
m++;
}
else{
e[p]=a[t+1]; //存放是非标识符的字符
p++;
}
}
cout<<"--------------判断结果----------------"<<endl;
char a[50]={0}; //存放字符串
char b[50]={0}; //存放标志符
char d[50]={0}; //存放非标识符
cout<<"请输入字符串(以$结束):"<<endl;
for(int i=0;i<50;i++)

实验一词法分析(单词识别)

实验一词法分析(单词识别)

实验一:词法分析一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

本实验中,采用的是一类符号一种别码的方式。

2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>-> -<大于关系运算符>-> ><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。

如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。

于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。

但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。

在分析标识符,无符号整数等时也有类似情况。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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.实验代码。

相关文档
最新文档