实验一、词法分析器
编译原理实验一词法分析

编译原理实验⼀词法分析实验⼀词法分析【实验⽬的】 (1)熟悉词法分析器的基本功能和设计⽅法; (2)掌握状态转换图及其实现; (3)掌握编写简单的词法分析器⽅法。
【实验内容】 对⼀个简单语⾔的⼦集编制⼀个⼀遍扫描的词法分析程序。
【实验要求】 (1)待分析的简单语⾔的词法 1) 关键字 begin if then while do end 2) 运算符和界符 := + - * / < <= <> > >= = ; ( ) # 3) 其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义: ID=letter(letter|digit)* NUM=digitdigit* 4) 空格由空⽩、制表符和换⾏符组成。
空格⼀般⽤来分隔 ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。
(2)各种单词符号对应的种别编码 (3)词法分析程序的功能 输⼊:所给⽂法的源程序字符串 输出:⼆元组(syn,token 或 sum)构成的序列。
syn 为单词种别码; token 为存放的单词⾃⾝字符串; sum 为整形常数。
【实验代码】1 #include<iostream>2 #include<string.h>3 #include<conio.h>4 #include<ctype.h>5using namespace std;6int sum,syn,p,m,n;7char ch,chs[8],s[100];8char *tab[6]={"begin","if","then","while","do","end"};910int scanner(){11for(n=0;n<8;n++) chs[n]='\0';12 m=0;13 n=0;14 ch=s[p++];15while(ch=='') ch=s[p++];16if(isalpha(ch)){17while(isalpha(ch)||isdigit(ch)){18//isalpha(ch)函数:判断字符ch是否为英⽂字母,⼩写字母为2,⼤写字母为1,若不是字母019//isdigit(ch)函数:判断字符ch是否为数字,是返回1,不是返回020 chs[m++]=ch;21 ch=s[p++];22 }23 syn=10;24for(n=0;n<6;n++)25if(strcmp(chs,tab[n])==0) syn=n+1;26 p--;27 }else if(isdigit(ch)){28 sum=0;29while(isdigit(ch)){30 sum=sum*10+(ch-'0');31 ch=s[p++];32 }33 syn=11;34 p--;35 }else if(ch==':'){36 syn=17;37 chs[m++]=ch;38 ch=s[p++];39if(ch=='='){ syn=18;chs[m]=ch;p++;}40 p--;41 }else if(ch=='<'){42 syn=20;43 chs[m++]=ch;44 ch=s[p++];45if(ch=='>') { syn=21;chs[m]=ch;p++;}46if(ch=='=') { syn=22;chs[m]=ch;p++;}47 p--;48 }else if(ch=='>'){49 syn=23;50 chs[m++]=ch;51 ch=s[p++];52if(ch=='=') { syn=24;chs[m]=ch;p++;}53 p--;54 }else switch(ch){55case'+':syn=13;chs[m]=ch;break;56case'-':syn=14;chs[m]=ch;break;57case'*':syn=15;chs[m]=ch;break;58case'/':syn=16;chs[m]=ch;break;59case'=':syn=25;chs[m]=ch;break;60case';':syn=26;chs[m]=ch;break;61case'(':syn=27;chs[m]=ch;break;62case')':syn=28;chs[m]=ch;break;63case'#':syn=0;chs[m]=ch;break;64default:syn=-1;65 }66return0;67 }68int main(){69 p=0;70 cout<<"Please input code and end with character '#':"<<endl;71do{72//cin>>ch;不识别空格73 ch=getchar();74 s[p++]=ch;75 }while(ch!='#');76 p=0;77do{78 scanner();79switch(syn){80case11:cout<<'('<<syn<<','<<sum<<')'<<endl;break;81case -1:cout<<'('<<syn<<','<<"error"<<')'<<endl;break;82default:cout<<'('<<syn<<','<<chs<<')'<<endl;83 }84 }while(syn!=0);85//getch():是⼀个不回显函数,当⽤户按下某个字符时,函数⾃动读取,⽆需按回车,所在头⽂件是conio.h。
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
实验一 词法分析

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

词法分析器实验报告引言:词法分析器(Lexical Analyzer)是编译器的重要组成部分,其主要任务是将源代码转化为一个个独立的词法单元,为语法分析器提供输入。
在本次实验中,我们设计并实现了一个简单的词法分析器,通过对其功能和性能的测试,评估其在不同场景下的表现。
实验目的:1. 确定词法分析器的输入和输出要求;2. 通过构建适当的正则表达式规则,匹配不同类型的词法单元;3. 实现一个高效的词法分析器,确保在处理大型源代码时性能不受影响;4. 对词法分析器的功能和性能进行测试和评估。
实验过程:1. 设计词法分析器的接口:1.1 确定输入:源代码字符串。
1.2 确定输出:词法单元流,每个词法单元包含类型和对应的字符串值。
2. 构建正则表达式规则:2.1 识别关键字:根据编程语言的关键字列表构建正则表达式规则,将关键字与标识符区分开。
2.2 识别标识符:一般由字母、下划线和数字组成,且以字母或下划线开头。
2.3 识别数字:整数和浮点数可以使用不同的规则来识别。
2.4 识别字符串:使用引号(单引号或双引号)包裹的字符序列。
2.5 识别特殊符号:各类操作符、括号、分号等特殊符号需要单独进行规则设计。
3. 实现词法分析器:3.1 读取源代码字符串:逐个字符读取源代码字符串,并根据正则表达式规则进行匹配。
3.2 保存词法单元:将匹配到的词法单元保存到一个词法单元流中。
3.3 返回词法单元流:将词法单元流返回给调用者。
4. 功能测试:4.1 编写测试用例:针对不同类型的词法单元编写测试用例,包括关键字、标识符、数字、字符串和特殊符号。
4.2 执行测试用例:将测试用例作为输入传递给词法分析器,并检查输出是否和预期一致。
4.3 处理错误情况:测试词法分析器对于错误输入的处理情况,如非法字符等。
5. 性能测试:5.1 构建大型源代码文件:生成包含大量代码行数的源代码文件。
5.2 执行词法分析:使用大型源代码文件作为输入,测试词法分析器的性能。
实验一实现简单词法分析器实验内容

实验一实现简单词法分析器实验内容实验一实现简单的词法分析器一、实验内容实现一个C语言子集的词法分析程序。
二、实验要求1、要求能识别整数、自定义标识符及以下关键字:+-*/===!==||=()[]{}:;,voidintfloatcharifelsewhiledo!main2、自己任意书写一小段包含上述部分关键字的C语言代码,编写词法分析程序分析所写的代码,可以用任何语言实现,输出程序中所有关键字、整数、自定义标识符对应的二元式。
3、关键字、自定义标识符、整数的类号自己确定,要求将确定的类号以表格的形式书写在纸质实验报告上。
4、要求输出的格式是:假设float的类号是28,则识别float的输出结果是(float,28);对于整数与自定义标识符,假设标识符的类号是1,则识别标识符的输出结果是(标识符名称,1),同时将该标识符放入一张符号表。
5、实例如下:三、提示1、程序代码提交给课代表。
2、纸质实验报告内容:实验内容、自己写的待扫描的C语言源程序,类号分配表,所实现代码的核心代码,词法分析结果。
实验指导一、实验涉及的数据结构与变量1、关键字列表struct{charsymbol[30];intclassID;}keywordtable[33];用于存放实验要求的33个关键字,可以在定义该结构数组时直接初始化,给每个关键字分配唯一的类号。
2、符号表struct{charname[20];inttype;}symtable[100];用于存放源程序中的自定义标识符与整数(不考虑浮点数),其中整数的类号与自定义标识符的类号自行确定,但是不能与关键字的类号相同。
3、二元式列表struct{charsign[20];intclassID;}eryuanshi[100];用于存放所有识别的二元式,包含关键字、整数、自定义标识符。
4、几个变量intkey_count=33;//关键字的个数intsym_count;//符号表计数器interyuanshi_count;//二元式计数器二、实验涉及的函数1、voidlookup(char*p)【功能说明】首先在关键字列表keywordtable中查询字符串p,若存在就将该字符串及对应的类号插入二元式列表eryuanshi;若没有,在符号表symtable中查询,如果symtable中不存在p就将p插入,这里要分p 是标识符还是整数区别对待,设置不同的type值。
词法分析器实验报告

词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。
二、实验目标本实验的目标是设计和实现一个能够对C语言代码进行词法分析的程序。
该程序能够将源代码分解成关键字、标识符、常量、运算符等各种词法单元,并输出其对应的词法类别。
三、实验方法1. 设计词法规则:根据C语言的词法规则,设计相应的正则表达式来描述各种词法单元的模式。
2. 实现词法分析器:利用编程语言(如Python)实现词法分析器,将源代码作为输入,根据词法规则将其分解成各种词法单元,并输出其类别。
3. 测试和调试:编写测试用例,对词法分析器进行测试和调试,确保其能够正确地识别和输出各种词法单元。
四、实验过程1. 设计词法规则:根据C语言的词法规则,我们需要设计正则表达式来描述各种词法单元的模式。
例如,关键字可以使用'|'操作符将所有关键字列举出来,标识符可以使用[a-zA-Z_][a-zA-Z0-9_]*的模式来匹配,常量可以使用[0-9]+的模式来匹配等等。
2. 实现词法分析器:我们选择使用Python来实现词法分析器。
首先,我们需要读取源代码文件,并将其按行分解。
然后,针对每一行的代码,我们使用正则表达式进行匹配,以识别各种词法单元。
最后,我们将识别出的词法单元输出到一个结果文件中。
3. 测试和调试:我们编写了一系列的测试用例,包括各种不同的C语言代码片段,以测试词法分析器的正确性和鲁棒性。
通过逐个测试用例的运行结果,我们可以发现和解决词法分析器中的问题,并进行相应的调试。
五、实验结果经过多次测试和调试,我们的词法分析器能够正确地将C语言代码分解成各种词法单元,并输出其对应的类别。
例如,对于输入的代码片段:```cint main() {int a = 10;printf("Hello, world!\n");return 0;}```我们的词法分析器将输出以下结果:```关键字:int标识符:main运算符:(运算符:)运算符:{关键字:int标识符:a运算符:=常量:10运算符:;标识符:printf运算符:(常量:"Hello, world!\n"运算符:)运算符:;关键字:return常量:0运算符:;```可以看到,词法分析器能够正确地将代码分解成各种词法单元,并输出其对应的类别。
实验一、词法分析器(含源代码)

词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void $关键字流程图、程序流程图:程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
编译原理实验--词法分析器

实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。
实验一词法分析器

12
词法分析器 语法分析器 语义子程序
词法分析器 (*.l文件) 语法分析器 (*.y文件)
C/C++编译器 (a) 手工编写
LEX编译器 YACC编译器 语义子程序 (b)工具生成
函数绘图语言 解释器
3.1 解释器的实现方法
C/C++编译器
函数绘图语言 解释器
函数绘图语言 源程序
函数绘图语言 解释器 (c) 解释器工作原理
6
角度旋转(ROT) 2.2.4 角度旋转(ROT)语句
语法: 角度; 语法:ROT IS 角度; 语义:逆时针旋转角度所规定的弧度值。具体计算公式: 语义:逆时针旋转角度所规定的弧度值。具体计算公式: 旋转后X 旋转前X*COS 角度)+旋转前Y*SIN 角度) X*COS( )+旋转前Y*SIN( 旋转后X=旋转前X*COS(角度)+旋转前Y*SIN(角度) 旋转后Y 旋转前Y*COS 角度) 旋转前X*SIN 角度) Y*COS( X*SIN( 旋转后Y=旋转前Y*COS(角度)-旋转前X*SIN(角度) 举例:ROT IS PI/2; 举例: 说明:逆时针旋转PI/2 即逆时针旋转90 PI/2, 90度 说明:逆时针旋转PI/2,即逆时针旋转90度。
4
循环绘图(FOR2.2.1 循环绘图(FOR-DRAW )语句
语法: 语法: DRAW(横坐标, 纵坐标) FOR T FROM 起点 TO 终点 STEP 步长 DRAW(横坐标, 纵坐标); 语义: 语义: 起点到终点、每次改变一个步长 绘制出由(横坐标, 步长, 令T从起点到终点、每次改变一个步长,绘制出由(横坐标,纵 坐标)所规定的点的轨迹。 坐标)所规定的点的轨迹。 举例: 举例: PI/50 sin(T)); FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (cos(T), sin(T)); 说明: 说明: 该语句的作用是令T *PI、 PI/50 50, 该语句的作用是令T从0到2*PI、步长 PI/50,绘制出各个点的 坐标(cos(T) sin(T)),即一个单位园。 (cos(T), 坐标(cos(T),sin(T)),即一个单位园。 注意: 注意: 由于绘图系统的默认值是 ORIGIN IS (0,0); ROT IS 0; SCALE IS (1, 1); 所以实际绘制出的图形是在屏幕左上角的一个点。 所以实际绘制出的图形是在屏幕左上角的一个点。
实验1 词法分析器(优.选)

青岛理工大学实 验 报 告实验课程: 编译原理实验日期: 2014 年 5月28 日 交报告日期:2014 年6月4日 成绩: 实验地点:现代教育技术中心101(计算机实验室)计算机工程 学院,计算机科学与技术 专业, 班级:计算113实验指导教师: 批阅教师:一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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为常数。
例如:对源程序begin x:=9; if x>0 then x:=2*x+1/3; end# 经词法分析后输出如下序列:(1,beigin) (10,x) (18,:=) (11,9) (26,;) (2,if)......三、算法思想1.主程序示意图主程序示意图如下所示:其中初值包括如下两个方面。
1)关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在关键字表,当扫描程序识别出标识符时,查关键字表。
若查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表作为一个字符串数组,其描述如下:char *rwtab[22] = {"begin","if","else","then","while","do","for","switch","case","until","break","goto","constant","return","int","float","double","string","char","short","long","end"};2)程序中的主要变量为syn,token和sum。
编译原理实验报告词法分析器语法分析器

编译原理实验报告词法分析器语法分析器 Document serial number【LGGKGB-LGG98YT-LGGT8CB-LGUT-编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
2、程序流程图(1)主程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s 用来表示正在分析的字符。
字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include <>#include <>#include <>int i,j,k;char c,s,a[20],token[20]={'0'};int letter(char s){if((s>=97)&&(s<=122)) return(1);else return(0);}int digit(char s){if((s>=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else")==0) return(3);else if(strcmp(token,"switch")==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf("please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;j=0;get();while(s!='#'){ memset(token,0,20);switch(s){case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)",6,token);else printf("(%d,-)",k);break;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':while(digit(s)){token[j]=s;j=j+1;get();}retract();printf("%d,%s",7,token);break;case '+':printf("('+',NULL)");break;case '-':printf("('-',null)");break;case '*':printf("('*',null)");break;case '<':get();if(s=='=') printf("(relop,LE)");else{retract();printf("(relop,LT)");}break;case '=':get();if(s=='=')printf("(relop,EQ)");else{retract();printf("('=',null)");}break;case ';':printf("(;,null)");break;case ' ':break;default:printf("!\n");}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术。
词法分析器实验报告

词法分析器实验报告一、实验目的本实验旨在通过构建一个简单的词法分析器来加深对编译原理中词法分析的理解,并掌握基本的词法分析算法和程序设计技巧。
二、实验环境操作系统:Windows 10编程语言:C/C++开发环境:Visual Studio 2019三、实验内容1. 设计并实现一个词法分析器,要求具备以下功能:(1)能够识别并区分关键字、标识符、字符常量、字符串常量、整型常量和浮点型常量等基本单词;(2)能够跳过注释、空格、制表符和换行符等无用字符;(3)能够给出错误提示并指明错误所在位置。
2. 对设计的词法分析器进行测试,并记录测试结果,分析测试结果的正确性和效率。
四、实验方法1. 分析待处理的源程序,并确定需要识别的词法单元;2. 设计状态转换图或状态转换表,并将其转化为程序代码;3. 开发测试程序,对所设计的词法分析器进行测试。
五、实验结果1. 实现的词法分析器程序可以正确识别出源程序中的各个单词,并能够跳过无用字符;2. 在测试过程中发现了一些错误,比如未能正确识别一些特殊情况下的单词,或者给出了错误的错误提示等。
经过修改后,程序可以正确识别这些情况,并给出正确的错误提示信息;3. 程序的效率较高,能够在短时间内对源程序进行词法分析。
六、实验体会通过本次实验,我对编译原理中词法分析的概念、算法和程序设计技巧有了更加深入的了解和掌握。
在实践中,我遇到了许多问题,比如如何设计状态转换图,如何正确识别一些特殊的单词等。
这些问题一一解决后,我对词法分析有了更加深刻的理解。
通过本次实验,我还深刻体会到了编译器设计过程中的思维方式和技术要求。
编译器是计算机科学中的一项重要技术,对于提高程序运行效率、保证程序安全性、增强程序可读性和扩展程序功能等都有重要作用。
因此,编译原理作为计算机科学的重要组成部分,对于我以后的学习和研究具有重要意义。
编译原理实验报告--词法分析器

编译原理实验—词法分析器一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求对某特定语言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、单词种别定义;A语言中的单词符号及其对应的种别编码如下表所示:单词符号种别编码单词符号种别编码3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、java旗舰版5、关键算法的流程图及文字解释;程序中用到的函数列表:A类定义各种类函数以及包含主函数public static void main()变量ch储存当前最新读进的字符的地址strToken存放当前字符串main() //主函数Analysis()//分析函数,每次读入一行文件,进行识别处理;char GetChar(); //取得当前位置的字符的内容放入ch,并提前指向下一个字符;char GetNextChar();//取得当前位置的下一位置的字符,String ConCat(); //将ch指向的字符连接到strToken后面isLetter(); //判断ch指向的字符是否字母isDigit(); //判断ch指向的字符是否数字add(p,str); //向p表中插入当前strToken的字符串Boolean findKeyWord(str); //检测当前strToken中的字符串是否保留字,若是,则执行getKeyWordKey(str),返回保留字的id,否则,判别其是否是已存在的标示符,若是,返回标示符的id以及该标示符在表中的位置;findPunctuation()//判断是否是一个保留的符号;getindex() //返回已经识别的标示符或者是数字的位置下标;Boolean exist(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回true,否则返回falsevoid callError(); //出错处理过程,将错误的位置报告出来(1)main()函数的流程图如下:)具体分析流程图:开始类初始化,变量的初始化,准备执行main()函数调用Analyse()函数分析输出结果表结束Analyse(str)函数读取第一个字符赋给变量Ch继续判读IndexoutofBound6、测试报告(测试用例,测试结果);首先输入一个不含错误的程序(两种注释)进行检测:运行后在控制台上得到的结果如下所示:得到的二元组序列如下:经检验,输出的是正确的二元组序列。
词法分析器实验报告

词法分析器实验报告词法分析器是编译器的一个重要组成部分,用于将输入的字符流转换成一个个词法单元(token)。
本次实验使用Python语言实现了一个简单的词法分析器。
主要包括以下几个步骤:1. 预处理:去除源代码中的空格、换行符等无意义字符,并进行必要的错误检查。
2. 正则表达式定义词法单元:利用正则表达式定义源代码可以被识别为词法单元的模式。
例如,整数可以定义为由数字组成的串,标识符可以定义为以字母或下划线开头,后面跟着任意个字母、数字或下划线的串。
3. 正则表达式匹配:利用Python的re模块,使用定义好的正则表达式对预处理后的源代码进行匹配。
如果匹配成功,则生成对应的词法单元,并存储起来。
4. 输出词法单元:将生成的词法单元按照一定的格式输出。
实验结果:通过对不同的源代码进行测试,可以得到正确的词法单元输出。
例如,对于以下的源代码:```pythonx = 123 + 456 * (789 - 100)```经过词法分析器处理后,可以得到以下的词法单元输出:```Token(ID, 'x')Token(ASSIGN, '=')Token(INT, '123')Token(PLUS, '+')Token(INT, '456')Token(LPAREN, '(')Token(INT, '789')Token(MINUS, '-')Token(INT, '100')Token(RPAREN, ')')```总结与收获:通过本次实验,我对词法分析器的基本原理和实现方法有了更深入的了解。
同时,我学会了如何使用正则表达式进行模式匹配,以及如何使用Python的re模块进行正则表达式匹配。
这对于我进一步学习和理解编译原理以及编译器的工作原理有很大帮助。
编译原理实验-词法分析器

编译原理实验-词法分析器⼀、实验⽬的设计、编制、调试⼀个词法分析程序,对单词进⾏识别和编码,加深对词法分析原理的理解。
⼆、实验内容1.选定语⾔,编辑任意的源程序保存在⽂件中;2.对⽂件中的代码预处理,删除制表符、回车符、换⾏符、注释、多余的空格并将预处理后的代码保存在⽂件中;3.扫描处理后的源程序,分离各个单词符号,显⽰分离的单词类型。
三、实验思路对于实验内容1,选择编写c语⾔的源程序存放在code.txt中,设计⼀个c语⾔的词法分析器,主要包含三部分,⼀部分是预处理函数,第⼆部分是扫描判断单词类型的函数,第三部分是主函数,调⽤其它函数;对于实验内容2,主要实现在预处理函数processor()中,使⽤⽂档操作函数打开源程序⽂件(code.txt),去除两种类型(“//”,“/*…*/”)的注释、多余的空格合并为⼀个、换⾏符、回车符等,然后将处理后的保存在另⼀个新的⽂件(afterdel.txt)中,最后关闭⽂档。
对于实验内容3,打开处理后的⽂件,然后调⽤扫描函数,从⽂件⾥读取⼀个单词调⽤判断单词类型的函数与之前建⽴的符号表进⾏对⽐判断,最后格式化输出。
四、编码设计代码参考了两篇博主的,做了部分改动,添加了预处理函数等1 #include<iostream>2 #include<fstream>3 #include<cstdio>4 #include<cstring>5 #include<string>6 #include<cstdlib>78using namespace std;910int aa;// fseek的时候⽤来接着的11string word="";12string reserved_word[20];//保留13char buffer;//每次读进来的⼀个字符14int num=0;//每个单词中当前字符的位置15int line=1; //⾏数16int row=1; //列数,就是每⾏的第⼏个17bool flag; //⽂件是否结束了18int flag2;//单词的类型192021//预处理函数22int processor(){//预处理函数23 FILE *p;24int falg = 0,len,i=0,j=0;25char str[1000],str1[1000],c;26if((p=fopen("code.txt","rt"))==NULL){27 printf("⽆法打开要编译的源程序");28return0;29 }30else{31//fgets(str,1000,p);32while((c=getc(p))!=EOF){33 str[i++] = c;34 }35 fclose(p);36 str[i] = '\0';37for(i=0;i<strlen(str);i++){38if(str[i]=='/'&&str[i+1]=='/'){39while(str[i++]!='\n'){}40 }//单⾏注释41else if(str[i]=='/'&&str[i+1]=='*'){42while(!(str[i]=='*'&&str[i+1]=='/')){i++;}43 i+=2;44 }//多⾏注释45else if(str[i]==''&&str[i+1]==''){46while(str[i]==''){i++;}47 i--;48if(str1[j-1]!='')49 str1[j++]='';50 }//多个空格,去除空格51else if(str[i]=='\n') {52if(str1[j-1]!='')53 str1[j++]='';54 }//换⾏处理,55else if(str[i]==9){56while(str[i]==9){57 i++;58 }59if(str1[j-1]!='')60 str1[j++]='';61 i--;62 }//tab键处理63else str1[j++] = str[i];//其他字符处理64 }65 str1[j] = '\0';66if((p = fopen("afterdel.txt","w"))==NULL){ 67 printf("can not find it!");68return0;69 }70else{71if(fputs(str1,p)!=0){72 printf("预处理失败!");73 }74else printf("预处理成功!");75 }76 fclose(p);77 }78return0;79 }8081//设置保留字82void set_reserve()83 {84 reserved_word[1]="return";85 reserved_word[2]="def";86 reserved_word[3]="if";87 reserved_word[4]="else";88 reserved_word[5]="while";89 reserved_word[6]="return";90 reserved_word[7]="char";91 reserved_word[8]="for";92 reserved_word[9]="and";93 reserved_word[10]="or";94 reserved_word[11]="int";95 reserved_word[12]="bool";96 }9798//看这个字是不是字母99bool judge_word(char x)100 {101if(x>='a' && x<='z' || x>='A' && x<='Z' ){ 102return true;103 }104else return false;105 }106107//看这个字是不是数字108bool judge_number(char x)109 {110if(x>='0' && x<='9'){111return true;112 }113else return false;114 }115116//看这个字符是不是界符117bool judge_jiefu(char x)118 {119if(x=='('||x==')'||x==','||x==';'||x=='{'||x=='}'){ 120return true;121 }122else return false;123 }124125126//加减乘127bool judge_yunsuanfu1(char x)128 {129if(x=='+'||x=='-'||x=='*')130 {131return true;132 }133else return false;134 }135136//等于赋值,⼤于⼩于⼤于等于,⼩于等于,⼤于⼩于137bool judge_yunsuannfu2(char x)138 {139if(x=='='|| x=='>'||x=='<'||x=='&'||x=='||'){140return true;141 }142else return false;143 }144145146//这个最⼤的函数的总体作⽤是从⽂件⾥读⼀个单词147int scan(FILE *fp)148 {149 buffer=fgetc(fp);//读取⼀个字符150if(feof(fp)){//检测结束符151 flag=0;return0;152 }153else if(buffer=='')154 {155 row++;156return0;157 }158else if(buffer=='\n')159 {160 row=1;161return0;162 }163//如果是字母开头或'_' 看关键字还是普通单词164else if(judge_word(buffer) || buffer=='_')165 {166 word+=buffer;167 row++;168while((buffer=fgetc(fp)) && (judge_word(buffer) || judge_number(buffer) || buffer=='_'))169 {170 word+=buffer;171 row++;172 }173if(feof(fp)){174 flag=0;175return1;176 }177for(int i=1;i<=12;i++){178if(word==reserved_word[i]){179 aa=fseek(fp,-1,SEEK_CUR);//如果执⾏成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。
实验一(词法分析)

实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。
2、深刻领会状态转换图的含义,逐步理解有限自动机。
3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。
二.实验内容计算机程序设计语言的编译程序的词法分析部分实现。
给出算法的流程图及有穷状态自动机的模型(可以用矩阵或者状态图表示)从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。
为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。
(2)空白符仅仅是空格、回车符、制表符。
(3)代码是自由格式。
(4)注释应放在花括号之内,并且不允许嵌套三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符 (空格、回车符、制表符)(4)列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。
(2)词法分析程序当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。
(3)标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。
(选做)四.实验结果(1)测试用例(2)实验结果的屏幕截图五.实验总结。
实验一 词法分析器

实验一词法分析器一、实验目的通过设计编译调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
二、实验要求编译一个能读单词的程序,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,并依次输出各个单词的内部编码及单词符号的自身值。
单词的内部编码如下:1、保留字:main、if、int、for、while、do、return、break、continue,单词种别码分别为1-9,输出的二元组形式为单词种别码,0。
2、标识符:除保留字以外的以字母开头,后跟字母、数字的字符序列,单词的种别码为20,输出的二元组形式为单词种别码,标识符的名字。
3、常数为无符号整数型,单词种别码为30,输出的二元组形式为单词种别码,常数值。
4、运算符:+、-、*、/、=、>、<、>=、<=、==、!=,单词种别码为41-50,输出的二元组形式为单词种别码,0。
5、分隔符:,、;、{、}、(、),单词的种别码为61-66,输出的二元组形式为单词种别码,0。
单词符号种别码单词符号种别码main 1 = 45int 2 > 46if 3 < 47for 4 >= 48while 5 <= 49do 6 == 50return 7 != 51break 8 , 61continue 9 ; 62ID 20 { 63NUM 30 } 64+ 41 ( 65- 42 ) 66* 43 / 44三、实验平台Microsoft Visual C++ 6.0四、程序设计源代码:#include<iostream>#include<fstream>#include<string>using namespace std;typedef struct{char *str;int code;}Word;Wordkey[9]={{"main",1},{"int",2},{"if",3},{"for",4},{"while",5}, {"do",6},{"return",6},{"break",7},{"continue",9}};Wordoptr[11]={{"+",41},{"-",42},{"*",43},{"/",44},{"=",45}, {">",46},{"<",47},{">=",48},{"<=",49},{"==",50},{"!=",51}};Wordseparator[6]={{",",61},{";",62},{"{",63},{"}",64}, {"(",65},{")",66}};char ch;int IsKey(string ss){int i;for(i=0;i<9;i++){if(!strcmp(key[i].str,ss.c_str()))return(key[i].code);}return 0;}int IsLetter(char c){if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z')))return 1;elsereturn 0;}int IsDigit(char c){if(c>='0'&&c<='9')return 1;elsereturn 0;}int IsOptr(string ss){int i;for(i=0;i<11;i++){if(!strcmp(optr[i].str,ss.c_str()))return(optr[i].code);}return 0;}int IsSeparator(string ss){int i;for(i=0;i<6;i++){if(!strcmp(separator[i].str,ss.c_str()))return(separator[i].code);}return 0;}void analyse(ifstream in){string st="";char ch;while((ch=in.get())!=EOF){st="";if((ch==' ')||(ch=='\r')||(ch=='\n')){}else if(IsLetter(ch)){while (IsLetter(ch)||IsDigit(ch)){st+=ch;ch=in.get();}in.seekg(-1,ios::cur);if(IsKey(st))cout<<"("<<IsKey(st)<<","<<0<<")"<<endl;elsecout<<"("<<20<<","<<'\"'<<st<<'\"'<<")"<<endl;}else if(IsDigit(ch)){while(IsDigit(ch)){st+=ch;ch=in.get();}in.seekg(-1,ios::cur);cout<<"("<<30<<","<<st<<")"<<endl;}else{st+=ch;if(IsOptr(st)){ch=in.get();if(ch=='='){string sr(st);sr+=ch;if(IsOptr(sr))cout<<"("<<IsOptr(sr)<<","<<0<<")"<<endl;else{cout<<"("<<IsOptr(st)<<","<<0<<")"<<endl;in.seekg(-1,ios::cur);}}else{cout<<"("<<IsOptr(st)<<","<<0<<")"<<endl;in.seekg(-1,ios::cur);}}else if(IsSeparator(st)){cout<<"("<<IsSeparator(st)<<","<<0<<")"<<endl;}}}}void main(){ifstream inc;inc.open("test.txt");if(inc.is_open()){analyse(inc);inc.close();}elsecout<<"文件操作错误"<<endl;cout<<"finish lalala"<<endl;}在text.txt 文件中输入12357ujiyt ,/==,输出代码应当为(30,12357)、(20,ujiyt),(61,0),(44,0),(50,0)。
编译原理实验1:词法分析器 - 解析

3
4
5
代码框架
6
7
8
9
10
11
适用于编程
12
测试的输入符号串:
" Ae35 6638 5392H A10 83A2Eh 65Ha 3G2H 80 "
13
说明
1)单词清空:strcpy(word,"\0"); 只是逻辑清空,即只 将字符串首字符赋值为结束符'\0'。 推荐使用:memset(word, 0, sizeof(word));
实验1:词法分析器 - 解析
实验题目
假设某语言允许的标识符为字母开头的字母数字串, 允许的数据为无符号的十进制或十六进制整数。其中规 定十六进制数必须以数字打头、以H结尾,数中允许使 用的字母为A,B,C,D,E,F(分别表示10~15)。试设 计一个DFA,使它能识别标识符、无符号的十进制和十 六进制整数(假定各单词之间用界限符或空格分开),并 编制相应的词法识别程序。 输入:可以自定义符号串的输入形式,如键盘输入、 文本文件、字符数组等。 输出:标识出规范的符号串与不合规范的符号串。
编译原理实验报告——词法分析器

编译原理实验报告姓名:关海超学号:200807010209专业:计算机科学与技术班级:08—02班一、实验目的通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
二、词法分析器的实现1、词法分析过程的考虑词法分析器的任务是将程序源代码看做一个字符串,只需从中分离出一个个具有独立意义的单词(包括标识符,符号和常量)即可,而无需考虑其在上下文环境中的正确性。
基于此认识,词法分析的过程可如下描述:本程序中用户源程序存储在文件“E:\prog.txt”文件中,程序首先调用readFromFile()函数将源程序代码从文件中读出,放到数组中暂存,然后主函数调用scaner()函数对其进行逐个扫描,分离出的每个独立单词进行分类判断,构成二元组形式,再将其输出的文件“E:\result.txt”中进行保存。
2、各种单词符号对应的种别码0 标识符21 ret 42 ++ 63 ||1 整型常量22 sho 43 -- 64 ?:2 auto 23 sig 44 - 65 =3 brea 24 siz 45 * 66 +=4 case 25 sta 46 & 67 -=5 char 26 str 47 / 68 *=6 cons 27 swi 48 % 69 /=7 cont 28 typ 49 + 70 %=8 defa 29 uni 50 - 71 >>=9 do 30 uns 51 << 72 <<=10 dou 31 voi 52 >> 73 &=11 els 32 vol 53 < 74 ^=12 enu 33 whi 54 <= 75 |=13 ext 34 ( 55 > 76 ,14 flo 35 ) 56 >= 77 '15 for 36 [ 57 == 78 ;16 got 37 ] 58 != 79 :17 if 38 -> 59 & 80 \{18 int 39 . 60 ^ 81 }19 lon 40 ! 61 | 82 //20 reg 41 ~ 62 &&3、关键数据结构的描述计数器count:将二元组写入文件时通过count判断是否是首次写入,若是则清空文件,否则追加写入;字符串常量endStr:其值为“end”,在分析判断每一单词的种类时,该字符串作为rwtab表的结束标志;数组prog[200]:暂存从文件中读取的源程序代码,该词法分析器约定源代码长度不超过199;数组token[20]:暂存每次分离出的单个具有独立意义的单词,该词法分析器约定每个单词的长度不超过19;结构体result:存放一个单词的种别码和单词本身的值,在写入文件时以结构体中的元素为单位依次写入;4、程序结构的描述本程序采用结构化设计方法,共有两个文件,六个模块,分别介绍如下:rwtab.h文件包含一个模块,即各种单词符号对应的种别码,作为外部文件被main.cpp文件引用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windows xp软件:visual c++二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void $关键字流程图、程序流程图:程序:#include<>#include<>#include<>#include<>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
C语言中没有string类型,因此本实验中的对字符串提取与识别均借助#include<>及字符型数组来实现。