实验一词法分析器
实验一 词法分析
实验名称: 词法分析器设计专业: 计算机科学与技术**: ***学号: *********词法分析器设计一. 实验要求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语言的一个子集)中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验要求1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。
单词示例单词种别码要求保留字if、else、int、while、do 每个保留字的单词种别都单独为一种标识符以字母开头且包含字母和数字的字符串标识符作为一种常数(只识别无符号整数)123、343 无符号整数作为一种运算符+、-、*、/、=、= = 、!=、> 、<、>=、<= 每符一种,也可以每一类符号一种分隔符,、;、{、}、(、) 每符一种2、上述要求仅为基本要求,可以在此基础上扩充,例如删除注释,增加识别单词的类型,将标识符和常量分别插入到相应的符号表中,增加错误处理等。
3、编程语言不限。
四、实验设计方案1、数据字典本实验用到的数据字典如下表所示:单词示例标识ID1 保留字void、if、else、for、while、do、return、break、main、int、float、char、double、String标识符以字母开头且包含字母和数字的字符串 2无符号整数和小数 3 常数(只识别无符号整数)运算符+、-、*、/、=、> 、<、 4分隔符,、;、{、}、(、) 5 本实验所使用的开发语言是C语言,在Test2类中定义了以下几个函数:2.程序流程图:YNY NNY YN Y N Y YN NN Y YN N N Y Y开始读入文件,把内容存入string 中,m=0,check=ture ,error=false从string 中读出一个字符放入ch 中输出str ,标识为无法识别的串check=ture ,error=falsech 是运算符?error=ture ? check=false ? 输出str ,标识为标示符check=ture 输出str ,标识为运算符输出str ,标识为无法识别的串check=ture ,error=falseerror=ture ? check=false ? 输出str ,标识为标示符check=ture 输出str ,标识为分隔符ch 是分隔符?ch 是数字?check=ture ?清空str ,ch 加到str 中,check=false ch 加到str 中Ch 是字母?check=ture ?清空str ,ch 加到str 中,check=falsech 加到str 中打印出错ch 是最后一个字符? 结束YN Y N3、实验程序#include<stdio.h> #include<string.h> #include<ctype.h> #include<windows.h>//判断读入的字符是否为字母 bool isLetter(char c){if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){ return true; } else return false; }//判断读入的字符是否为数字 bool isDigit(char c){if(c >='0' && c <= '9'){ return true; } else return false; }//判断是否为关键字 bool isKey(char *string) { if(!strcmp(string,"void")|| !strcmp(string,"if")|| !strcmp(string,"for")|| !strcmp(string,"while")|| !strcmp(string,"do")|| !strcmp(string,"return")|| !strcmp(string,"break")|| !strcmp(string,"main")|| !strcmp(string,"int")|| !strcmp(string,"float")|| !st rcmp(string,"char") || !strcmp(string,"double")|| !strcmp(string,"String")) { return true;ch 是数字?ch 加到str 中,error=true ch 是关键字? 输出str ,标识为关键字,check=true}else return false;}bool isError(char ch){if(ch == '@' || ch == '$' || ch == '&' || ch == '#' || ch == '~' || ch == '^'){return true;}elsereturn false;}void main(){char string[500]="";//存放文件中读出来的字符串char str[10]="";//存放需要对比的字符串char ch,c;//ch存放文件中的单个字符(翻译时用),c存放文件中的单个字符(从文件中提取信息时用)char filename[20];//文件名int j=0;printf("请输入文件名进行词法翻译:");scanf("%s",filename);FILE *cfPtr;if((cfPtr=fopen(filename,"r"))==NULL)printf("文件未找到!");else{while(!feof(cfPtr)){if(isspace(c=fgetc(cfPtr))){//判断是否是字符串;}else{string[j]=c;//从文件中一一提取字符j++;}}}int m = 0,k=0;//m翻译时用,k是str数组的下标string[j]=' ';j++;bool check=true,error=false;//用于判断标识for(int i = 0;i < j;i++){//实现语法翻译器switch (m){ch = string[i];if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '='|| ch == '>' || ch == '<'){if(error){printf("%s,此字符无法是识别!\n",str);error=false;check=true;}else if(!check){printf("(2,%s)标示符\n",str);check=true;}m = 4;}else if(ch == ',' || ch == ';' || ch == '{' || ch == '}' || ch == '(' || ch == ')'){if(error){printf("%s此字符无法识别\n",str);error=false;check=true;}else if(!check){printf("(2,%s)标示符\n",str);check=true;}m = 5;}else if ( isDigit((ch =string[i]) ) ){if(check){memset(str, 0, strlen(str));//清空k=0;str[k]=ch;k++;m = 3;check=false;} else{str[k]=ch;k++;}}else if ( isLetter(ch = string[i]) )if(check){check=false;memset(str, 0, strlen(str));k=0;str[k]=ch;k++;}else{str[k]=ch;k++;if(isKey(str)){printf("(1,%s)关键字\n",str);check=true;}}}else if(isError(ch = string[i])){if(check){memset(str, 0, strlen(str));//清空k=0;str[k]=ch;k++;check=false;error=true;}else{str[k]=ch;k++;error=true;}}else{}break;case 3:if(isLetter(ch =string[i])){printf("程序有错误!!!\n");str[k] = ch;k++;error=true;m = 0;break;}if(isError(ch = string[i])){printf("程序有错误!!!\n");str[k] = ch;k++;error=true;m = 0;break;}if (isDigit((ch =string[i] ) )){str[k] = ch;k++;}else if(ch=='.'){str[k]=ch;k++;}else{printf("( 3,%s) 数字\n",str);i --;m = 0;check=true;}break;case 4:i--;printf("( 4 ,%c) 运算符\n",ch);m = 0;break;case 5:i --;printf("( 5 ,%c) 分隔符\n",ch);m = 0;break;}}return;}五、实验结果六、实验小结本次实验中,运用C语言进行实验,实验刚开始的时候,能够对输入的字符进行判断,但是却不能排错以及只能识别全是字母的标识符,后来经过修改程序代码和编程的逻辑最终实现了,既能排错又能分析句子;通过实验掌握了词法分析,能实现对普通程序的语法分析翻译。
词法分析器实验报告
词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。
二、实验目标本实验的目标是设计和实现一个能够对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.C语言关键字的子集,以文件形式保存,待判断的C语言语句以文件形式保存。
2.关键字文件包括标识符、基本字、常数、运算符和界符以及相应的种别码。
3.在计算机终端顺次输出各词法单位的种别码和值。
若为标识符,其值为该标识符在标识符表中的位置;若为常数,其值为该常数在常数表中的位置;其余值为-1。
非法输入单词的种别码为-1,值为-2。
4.“单词”定义:C语言中最小的语法单位。
“标识符”定义:用户自定义的标志符。
5.测试数据:文本文件为unknowedword.text二.概要设计1.单词种别码设计如表一所示:2.单词规划的状态图:A标识符及关键字如图一所示:图一.标识符状态转换图B实数如图二所示:图二.实数状态转换图C图三.运算符状态转换图D其它与运算符雷同,此处略3. 数据结构know[N] 用来存放构成单词符号的字符串;unknow[N]用来存放待辨别的字符串;chartab[T][N] 用来存放识别出的标识符;keytab[M][N] 用来存放从文件中读入的基本字;consttab[T] 用来存放识别出的实数。
以上均设为全局变量。
4.基本操作Getchar()初始条件:unknow中读入了一串待辨别的字符串。
操作结果:从unknow读入一个字符到ch中,指向unknow的指针加1。
Getbc()初始条件:unknow中读入了一串待辨别的字符串。
操作结果:从unknow中读入不是空格的下一个字符。
Concat()初始条件:know中为字母且ch中为字母,或know中为数字(包括小数点)ch中也为数字。
操作结果:将ch中的字符连接到know中。
Isletter()初始条件:ch中已经读入了一个新的字符。
操作结果:判断ch中的字符是否字母。
Isdigit()初始条件:ch中已经读入了一个新的字符。
操作结果:判断ch中的字符是否数字。
Keyword()初始条件:已判断出know中的字符串为标识符。
实验一简易词法分析器的实现-实验一实现简单的词法分析器
实验一实现简单的词法分析器一、实验内容实现一个C语言子集的词法分析程序。
二、实验要求1、要求能识别整数、自定义标识符及以下关键字:+ - * / < <= == != > >= & && || = ( ) [ ] { } : ; , void int float char if else while do !main2、自己任意书写一小段包含上述部分关键字的C语言代码,编写词法分析程序分析所写的代码,可以用任何语言实现,输出程序中所有关键字、整数、自定义标识符对应的二元式。
3、关键字、自定义标识符、整数的类号自己确定,要求将确定的类号以表格的形式书写在纸质实验报告上。
4、要求输出的格式是:假设float的类号是28,则识别float的输出结果是(float,28);对于整数与自定义标识符,假设标识符的类号是1,则识别标识符的输出结果是(标识符名称, 1),同时将该标识符放入一张符号表。
5、实例如下:三、提示1、程序代码提交给课代表。
2、纸质实验报告内容:实验内容、自己写的待扫描的C语言源程序,类号分配表,所实现代码的核心代码,词法分析结果。
实验指导一、实验涉及的数据结构与变量1、关键字列表struct{char symbol[30];int classID;}keywordtable[33];用于存放实验要求的33个关键字,可以在定义该结构数组时直接初始化,给每个关键字分配唯一的类号。
2、符号表struct{char name[20];int type;}symtable[100];用于存放源程序中的自定义标识符与整数(不考虑浮点数),其中整数的类号与自定义标识符的类号自行确定,但是不能与关键字的类号相同。
3、二元式列表struct{char sign[20];int classID;}eryuanshi[100];用于存放所有识别的二元式,包含关键字、整数、自定义标识符。
实验一_词法分析器
计算机与信息工程学院实验报告姓名:_ _学号:专业:_软件工程年级:_2017_课程:编译原理主讲教师: _辅导教师:实验时间:2020年5月28日上午8时至10时,实验地点:201_ 实验题目:实验:词法分析实验目的:通过实现PL/0语言(一种示例小语言)的词法分析器,理解词法分析过程,掌握程序各部分之间的接口安排。
实验环境(硬件和软件)Code Blocks实验内容:1、PL/0语言的单词结构关键字(10个):begin, end ,if ,then, while, do, const, var,call,procedure标识符:字母序列,最大长度10常数:整型常数算符和界符(17个):+, -, *,/,odd,=,<>,<,>,<=,>=,:=,(,) ,, ,.,;2、单词的种别划分标识符作为一种常数作为一种算符和界符每个单词作为一个单独种别3、PL/0的语言的词法分析器将要完成以下工作:(1)跳过分隔符(如空格,回车,制表符);(2)识别诸如begin,end,if,while等保留字;(3)识别非保留字的一般标识符。
(4)识别数字序列。
(5)识别:=,<=,>=之类的特殊符号。
4、词法分析器的实现方式:把词法分析器设计成一个独立子程序,以便于语法分析器调用。
词法分析器运行一次产生一个单词符号。
5、词法分析器的输出形式(种别,属性值)其中:种别在“2、单词的种别”中进行了定义;属性值:若单词种别只代表唯一单词,属性值为空;若单词种别是SYM_IDENTIFIER,属性值为该单词在标识符表中的位置;若单词种别是SYM_ NUMBER,属性值为该单词在常数表中的位置。
6、标识符表可以是如下结构:7、常数表可以是如下结构:实验步骤:int n;///输入文本的行数char buffer[MAXN][MAXN];///缓冲区int len[MAXN];///输入文本每行的列数struct out///输出格式{string id;int val;out(){}out(string a,int b){id=a;val=b;}}res[MAXN*MAXN];///输出表int rescnt;///输出计数器set<string> cal;///运算符set<string> key;///关键字+标识符struct indent///标识符格式{string name;int val;indent(){}indent(string a,int b){name=a;val=b;} }iden[MAXN*MAXN];///标识符表int idencnt;///标识符计数器int num[MAXN*MAXN];///常数表int numcnt;///常数计数器实验数据记录:问题讨论:PL/0的词法和其状态图并不难,原因就是它的状态不牵涉到转化的问题,标识符关键字都是只有字母没有数字,所以在遍历搜索的时候只要读取的字符的状态发生改变时就时状态图走到终结结点的时候。
编译原理实验报告——词法分析器(内含源代码)
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
编译原理实验--词法分析器
实验一词法分析器设计【实验目的】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); 所以实际绘制出的图形是在屏幕左上角的一个点。 所以实际绘制出的图形是在屏幕左上角的一个点。
编译原理实验词法分析器与语法分析器实现
编译原理实验词法分析器与语法分析器实现词法分析器与语法分析器是编译器的两个重要组成部分,它们在编译过程中扮演着至关重要的角色。
词法分析器负责将源代码转化为一个个标记(token)序列,而语法分析器则根据词法分析器生成的标记序列构建语法树,验证源代码的语法正确性。
本实验旨在实现一个简单的词法分析器和语法分析器。
实验一:词法分析器实现在实现词法分析器之前,需要定义所需词法项的规则。
以C语言为例,常见的词法项包括关键字(如int、if、for等)、标识符、运算符(如+、-、*、/等)、常量(如整数、浮点数等)和分隔符(如括号、逗号等)。
接下来,我们来实现一个简单的C语言词法分析器。
1. 定义词法项的规则在C语言中,关键字和标识符由字母、数字和下划线组成,且首字符不能为数字。
运算符包括各种数学运算符和逻辑运算符。
常量包括整数和浮点数。
分隔符包括括号、逗号等。
2. 实现词法分析器的代码下面是一个简单的C语言词法分析器的实现代码:```pythondef lexer(source_code):keywords = ['int', 'if', 'for'] # 关键字列表operators = ['+', '-', '*', '/'] # 运算符列表separators = ['(', ')', '{', '}', ',', ';'] # 分隔符列表tokens = [] # 标记序列列表current_token = '' # 当前标记for char in source_code:if char.isspace(): # 如果是空格,则忽略continueelif char.isalpha(): # 如果是字母,则可能是关键字或标识符的一部分current_token += charelif char.isdigit(): # 如果是数字,则可能是常量的一部分current_token += charelif char in operators or char in separators: # 如果是运算符或分隔符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''tokens.append(char)else: # 如果是其他字符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''return tokens```以上代码通过遍历源代码的字符,根据定义的规则生成一个个标记,存储在`tokens`列表中。
实验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。
词法分析器实验报告
词法分析器实验报告一、实验目的本实验旨在通过构建一个简单的词法分析器来加深对编译原理中词法分析的理解,并掌握基本的词法分析算法和程序设计技巧。
二、实验环境操作系统: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、测试报告(测试用例,测试结果);首先输入一个不含错误的程序(两种注释)进行检测:运行后在控制台上得到的结果如下所示:得到的二元组序列如下:经检验,输出的是正确的二元组序列。
词法分析器实验报告_5
一、实验目的1.1总体目的1.1.1 掌握词法分析的基本原理;1.1.2.理解词法分析在编译程序过程中的作用;1.1.3.熟悉关键字表等相关的数据结构与单词的分类方法.1.1.4.加深对编译原理的理解,掌握词法分析器的实现方法和技术,同时,将JA V A 的理论知识结合实际,锻炼编程技术,强调良好的程序设计风格。
1.2程序目的利用JAVA语言针对C语言编制一个一遍扫描的编译程序。
从文件中识别出各个单词, 识别出所取的单词的类型, 并且对代码中的词法错误进行提示。
二、实验内容根据编译原理中的词法分析原理, 利用Java语言针对C语言编写一个词法分析程序: 输入: 打开一个C语言程序的源代码文件, 将其读入程序输入框。
处理: 对输入框中的代码进行词法分析,分离出关键字、标识符、数值、运算符和界符。
输出:在词法分析结果表中输出每个单词所在行号、类型以及它所对应的编码。
其中, 编码是自定义的,一种类型对应一组编码。
词法分析结果显示在词法分析错误信息栏, 提示错误个数、错误所在行号, 并对某些词法错误原因进行说明。
三、实验需求针对C语言程序代码进行词法分析器, 从指定文件中读入预分析的源程序, 从左至右扫描源程序的字符串, 按照词法规则(正则文法规则)识别出一个个正确的单词, 并转换成该单词相应的二元式(种别码、属性值)以便之后进行语法分析使用。
同时, 按照给定的规则, 识别出单词符号作为输出, 发现其中的语法错误, 不同类别的字符通过相应的函数模块来分析识别, 使程序能够正确识别文法所规定的任何组织形式的字符组合, 将所有的分析状态显示在词法分析器中。
最后在错误分析栏中显示该文件中C语言代码的词法错误个数、错误所在行, 并对错误原因进行说明。
四、主要数据结构介绍4.1关键字编码4.2标识符统一编码1004.3数值统一编码2004.4界符编码4.5运算符编码4.6全局变量含义int row: 语法错误出现的所在列数int line: 语法错误出现的所在行数int err: 语法错误的个数int begin: 当前程序扫描在字符串中的开始位置int end: 当前程序扫描在字符串中的结束位置4.7局部变量定义int i: 选择第i 个字符进行检测 int state: 单词类型判断标志 int N: 文件长度char c: 当前遍历的字符 string str: 输入字符串 int flag: 退出标志五、主要模块算法介绍5.1总体流程介绍说明: state 为输入字符状态标志, 根据输入字符不同类型选择不同处理。
实验一 词法分析器
实验一词法分析器一、实验目的通过设计编译调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
二、实验要求编译一个能读单词的程序,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,并依次输出各个单词的内部编码及单词符号的自身值。
单词的内部编码如下: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.掌握词法分析的原理2.设计一个词法分析程序,掌握程序设计语言中的各类单词的词法分析方法,加深对词法分析原理的理解。
3.熟悉保留字表等相关的数据结构与单词的分类方法。
4.掌握词法分析器的设计与调试。
二.实验要求2.1根据编译中的分词原理,编写一个词法分析程序:(1)输入:所给文法的源程序字符串。
(2)处理:对输入的内容进行分析,分离出保留字、标识符、常量、算符和界符。
(3)输出:对应的二元式(类别编码由自己定,一个单词符号对应一个类别码)2.2需要分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略2.3各种单词符号对应的类别码1.算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,词法分析基本思想是从左向右扫描每行源程序的符号,拼成单词,换成统一的二元式 (单词种别码,单词符号的属性值)表示。
对给定的程序通过词法分析器识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。
(1)主程序示意图主程序的初始包括以下两个方面:① 关键字表的初值。
关键字作为特殊标识符处理,把它们预先放在一张表中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:否首先设置3个变量:(1)token 用来存放构成单词符号的字符串;(2)sum 用来存放整型单词(3)syn 用来存放单词符号的类别码。
编译原理实验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,使它能识别标识符、无符号的十进制和十 六进制整数(假定各单词之间用界限符或空格分开),并 编制相应的词法识别程序。 输入:可以自定义符号串的输入形式,如键盘输入、 文本文件、字符数组等。 输出:标识出规范的符号串与不合规范的符号串。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
词法分析器实验报告一、实验目的及要求本次实验通过用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语言的一些基本知识,特别就是对文件,字符串进行基本操作的方法。