编译原理实验报告——词法分析器(内含源代码)
- 格式:docx
- 大小:181.40 KB
- 文档页数:17
《词法分析》实验报告目录目录 (1)1 实验目的 (2)2 实验容 (2)2.1 TINY计算机语言描述 (2)2.2 实验要求 (2)3 此法分析器的程序实现 (3)3.1 状态转换图 (3)3.2 程序源码 (4)3.3 实验运行效果截图 (9)4 实验体会 (10)1实验目的1、学会针对DFA转换图实现相应的高级语言源程序。
2、深刻领会状态转换图的含义,逐步理解有限自动机。
3、掌握手工生成词法分析器的方法,了解词法分析器的部工作原理。
2实验容2.1TINY计算机语言描述TINY计算机语言的编译程序的词法分析部分实现。
从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的部表示(token)送给语法分析程序。
为了简化程序的编写,有具体的要求如下:1、数仅仅是整数。
2、空白符仅仅是空格、回车符、制表符。
3、代码是自由格式。
4、注释应放在花括号之,并且不允许嵌套TINY语言的单词2.2实验要求要现编译器的以下功能1、按规则拼单词,并转换成二元式形式2、删除注释行3、删除空白符 (空格、回车符、制表符)4、列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式5、发现并定位错误词法分析进行具体的要求1、记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。
2、词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。
这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。
3、标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。
第1篇一、引言编译原理是计算机科学中的一个重要分支,它研究如何将高级语言编写的程序转换成计算机可以执行的机器语言。
为了深入理解编译原理的基本概念和方法,我们进行了一系列的实践操作。
本文将详细记录实践过程,并对实践结果进行分析和总结。
二、实践目标1. 理解编译原理的基本概念和流程。
2. 掌握编译器各个阶段的设计与实现方法。
3. 能够使用编译原理知识解决实际问题。
三、实践内容本次实践主要包括以下内容:1. 词法分析器(Scanner)的设计与实现:- 使用正则表达式定义词法规则。
- 设计状态转换图,实现状态转移函数。
- 编写代码,实现词法分析器。
2. 语法分析器(Parser)的设计与实现:- 设计文法规则,编写产生式。
- 使用递归下降法或LL(1)算法实现语法分析。
- 编写代码,实现语法分析器。
3. 语义分析器的设计与实现:- 定义符号表,实现符号表操作。
- 设计语义规则,实现语义分析。
- 编写代码,实现语义分析器。
4. 中间代码生成器的设计与实现:- 根据语法分析结果,生成中间代码。
- 设计中间代码格式,实现中间代码生成。
- 编写代码,实现中间代码生成器。
5. 代码优化器的设计与实现:- 分析中间代码,找出优化点。
- 实现代码优化算法,优化中间代码。
- 编写代码,实现代码优化器。
6. 目标代码生成器的设计与实现:- 根据优化后的中间代码,生成目标代码。
- 设计目标代码格式,实现目标代码生成。
- 编写代码,实现目标代码生成器。
四、实践过程1. 词法分析器:- 使用Python编写正则表达式,定义词法规则。
- 设计状态转换图,实现状态转移函数。
- 编写词法分析器代码,实现词法分析功能。
2. 语法分析器:- 设计文法规则,编写产生式。
- 使用递归下降法实现语法分析。
- 编写语法分析器代码,实现语法分析功能。
3. 语义分析器:- 定义符号表,实现符号表操作。
- 设计语义规则,实现语义分析。
- 编写语义分析器代码,实现语义分析功能。
中南大学编译原理实验报告班级:计科1205姓名:***学号:**********实验一词法分析程序设计与实现一、实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
二、实验内容自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程语言和编程工具。
从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验要求:1.对单词的构词规则有明确的定义;2.编写的分析程序能够正确识别源程序中的单词符号;3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;四、实验步骤1.定义目标语言的可用符号表和构词规则;2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;4.对不正确的单词,做出错误处理。
五、设计思路和实现过程本实验是词法分析器,我是用的是MFC实现的,我的设计思路就是按照书上提示的算法,先将几个词法分析器所需的基本函数用C++的形式实现,然后使用循环语句读入输入串的每一个字符,然后用if…else…语句实现,具体判断方式如下:1、如果读入的是字母,那么继续读入,知道读入的字符不是字母或者数字为止,对照标识符表,如果是标识符,则显示该串及对应标识符;如果不是,则显示该串和“$ID”;2、如果读入的是数字,则继续读入,知道不是数字为止,并显示该串和“$INT”;3、如果读入的是“=”,“+”,";",“(”,")","{","}",则分别输出该串和“$ASSIGN”,"$PLUS","$SEMICOLON","$LPAR","$RPAR","$LBRACE","$RBRACE";4、如果读入的是“*”,那么继续读入,如果下一个是“*”,则输出该串和"$POWER";否则输出该串和"$STAR",并将指针回退;5、如果独到输入串末尾,则退出。
学年第学期《编译原理》实验报告学院(系):计算机科学与工程学院班级:11303070A学号:***********姓名:无名氏指导教师:保密式时间:2016 年7 月目录1.实验目的 (1)2.实验内容及要求 (1)3.实验方案设计 (1)3.1 编译系统原理介绍 (1)3.1.1 编译程序介绍 (2)3.1.2 对所写编译程序的源语言的描述 (2)3.2 词法分析程序的设计 (3)3.3 语法分析程序设计 (4)3.4 语义分析和中间代码生成程序的设计 (4)4. 结果及测试分析 (4)4.1软件运行环境及限制 (4)4.2测试数据说明 (5)4.3运行结果及功能说明 (5)5.总结及心得体会 (7)1.实验目的根据Sample语言或者自定义的某种语言,设计该语言的编译前端。
包括词法分析,语法分析、语义分析及中间代码生成部分。
2.实验内容及要求(1)词法分析器输入源程序,输出对应的token表,符号表和词法错误信息。
按规则拼单词,并转换成二元形式;滤掉空白符,跳过注释、换行符及一些无用的符号;进行行列计数,用于指出出错的行列号,并复制出错部分;列表打印源程序;发现并定位词法错误;(2)语法分析器输入token串,通过语法分析,寻找其中的语法错误。
要求能实现Sample 语言或自定义语言中几种最常见的、基本的语法单位的分析:算术表达式、布尔表达式、赋值语句、if语句、for语句、while语句、do while语句等。
(3)语义分析和中间代码生成输入token串,进行语义分析,修改符号表,寻找其中的语义错误,并生成中间代码。
要求能实现Sample语言或自定义语言中几种最常见的、基本的语法单位的分析:算术表达式、布尔表达式、赋值语句、if语句、for语句、while 语句、do while语句等。
实验要求:功能相对完善,有输入、输出描述,有测试数据,并介绍不足。
3.实验方案设计3.1 编译系统原理介绍编译器逐行扫描高级语言程序源程序,编译的过程如下:(1).词法分析识别关键字、字面量、标识符(变量名、数据名)、运算符、注释行(给人看的,一般不处理)、特殊符号(续行、语句结束、数组)等六类符号,分别归类等待处理。
.编译原理实验报告实验名称:分析调试语义分析程序TEST抽象机模拟器完整程序保证能用!!!!!一、实验目的通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法畴变换为中间代码的语义翻译方法。
二、实验设计程序流程图.Statement_list()开始es=0读入一个token=}符号 es=0Y{Nes=1Tooken=ifToken=ifNYToken=whilees=0NNToken=for declaration_list()NYes=0Token=readNN N Statement_list()Token=writeNY es=0Token={ YNN}N es=2Token=ID|NUM|(Y N返回token=}YReturn(es)语法分析YYYYYYYIf_stat()while_stat()for_stat()read_stat()N write_stat()Compound_state()expression_stat()开始Es=0词法分析输出词法Es>0Y分析失败N输出词法分析成功语法分析输出语法Es=0Y分析成功N输出语法分析错误结束程序代码:Main.cpp#include<stdio.h>#include<ctype.h>extern bool TESTparse(char *pFileName);extern int TESTScan(FILE *fin,FILE *fout);FILE *fin,*fout;//用于指定输入输出文件的指针int main(){char szFinName[300];char szFoutName[300];printf("请输入源程序文件名(包括路径):");scanf("%s",szFinName);printf("请输入词法分析输出文件名(包括路径):");scanf("%s",szFoutName);if( (fin = fopen(szFinName,"r")) == NULL){printf("\n打开词法分析输入文件出错!\n");return 0;}if( (fout = fopen(szFoutName,"w")) == NULL){printf("\n创建词法分析输出文件出错!\n");return 0;}int es = TESTScan(fin,fout);fclose(fin);fclose(fout);if(es > 0)printf("词法分析有错,编译停止!共有%d个错误! \n",es);else if(es == 0){printf("词法分析成功!\n");int es=0;es =TESTparse(szFoutName);//调语法分析if(es== true) printf("语法分析成功!\n");else printf("语法分析错误!\n");}elseprintf("词法分析出现未知错误!\n");}Parse.cpp#include<stdio.h>#include<string.h>#include<ctype.h>#include<conio.h>#include<vector>// functionbool TESTparse();bool compound_Stat();bool program();bool statement();bool expression_stat();bool expression();bool bool_expr();bool additive_expr();bool term();bool factor();bool if_stat();bool while_stat();bool for_stat();bool write_stat();bool read_stat();bool declaration_stat();bool declaration_list();bool statement_list();bool compound_stat();char token[20],token1[40];//token保存单词符号,token1保存单词值FILE *fp;// 用于指向输入文件的指针int EsLine=0;typedef struct{int es;int line;}EsInf;std::vector<EsInf>StackEs;//语法分析程序void ProcessError(int es){EsInf temp;temp.es=es;temp.line=EsLine;StackEs.push_back(temp);}bool ReadFile(char *tok, char *tok1){if(feof(fp))return false;fscanf(fp,"%s\t%s\n",tok,tok1);printf("%s\t%s\n",tok,tok1);EsLine++;return true;}bool TESTparse(char *pFileName){bool es =true;if((fp=fopen(pFileName,"r"))==NULL){printf("\n打开 %s错误 !\n",pFileName);return false;}elseprogram();if(!feof(fp))ProcessError(9);fclose(fp);printf("===== 语法分析结果!=====\n");if(StackEs.size() == 0){printf("语法分析成功!\n");return true;}else{int i;for(i = 0; i < StackEs.size(); i++){printf("在第 %d行 ",StackEs[i].line);switch(StackEs[i].es){case 1:printf("缺少{!\n");break;case 2:printf("缺少}!\n");break;case 3:printf("缺少标识符!\n");break;case 4:printf("缺少分号!\n");break;case 5:printf("缺少(!\n");break;case 6:printf("缺少)!\n");break;case 7:printf("缺少操作数!\n");break;case 8:printf("文件为空!\n");break;case 9:printf("文件尾有多余字符!\n");break;case 10:printf("\n打开%s错误!\n",pFileName);break;}}return false;}}//《程序》 ::={< 声明序列 ><语句序列 >}//program::={<declaration_;list><statement_list>}bool program(){bool es = true;if( ReadFile(token,token1) == false ){ProcessError(8);//文件结束return false;}if(strcmp(token,"{"))// 判断是否为‘{ ’ProcessError(1);if( ReadFile(token,token1) == false )//文件中仅有{ProcessError(2);es =declaration_list();if(es == false)return false;es =statement_list();if(es == false)return false;if(strcmp(token,"}"))// 判断是否为‘ } ’ ProcessError(2);return true;}//< 声明序列 >::=< 声明序列 ><声明语句 >|< 声明语句 >//<declaration>::=//<declaration_list><declaration_stat>|ε//改成 <declaration_list>::={<declaration_stat>}bool declaration_list(){bool es = true;while (strcmp(token,"int")==0){es = declaration_stat(); if(es== false)return false;}return es;}//< 声明语句 >::=int<变量>;//<declaration_stat>::=int ID;bool declaration_stat(){bool es = true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,"ID"))ProcessError(3); //不是标识符if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,";"))ProcessError(4);if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}return(es);}//< 语句序列 >::=< 语句序列 ><语句 >| ε//<statement_list>::=<statement_list><statement>|ε//改成 <statement_list>::={<statement>}bool statement_list(){bool es =true;if(feof(fp))return false;.while(strcmp(token,"}")){es =statement();if(es == false)return(es);}return(es);}//< 语句 >::=<if语句>|<while语句>|<for语句>|<read语句>//|<write语句>|<复合语句>|<表达式语句>//<statement>::=<if_sttat>|<while_stat>|<for_stat>//|<compound_stat>|<expression_stat>bool statement(){bool es =true;if(strcmp(token,"if")==0 )es=if_stat();//<if语句>else if(strcmp(token,"while")==0 )es=while_stat();//<while语句>else if(strcmp(token,"for")==0 )es=for_stat();//<for语句>else if(strcmp(token,"read")==0 )es=read_stat();//<read语句>else if(strcmp(token,"write")==0 )es=write_stat();//<write语句>else if(strcmp(token,"{")==0 )es=compound_stat();//< 复合语句 >else if(strcmp(token,"ID")==0||strcmp(token,"NUM")==0|| strcmp(token,"(")==0 )es=expression_stat();//< 表达式语句 >return(es);}.//<if 语句 >::=if(<表达式>)<语句>[else<语句>]//<if_stat>::=if(<expressiion>)<statement>[else<statement>]bool if_stat(){bool es =true;//ifif( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,"("))ProcessError(5);// 少左括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es = expression();if(es == false)return(es);if(strcmp(token,")"))ProcessError(6);// 少右括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es=statement();if(es == false)return(es);if(strcmp(token,"else")==0)//else部分处理{if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es=statement();if(es == false)return(es);}return(es);}//<while 语句 >::=while(<表达式>)<语句>//<while_stat>::=while<espr><statement>bool while_stat(){bool es = true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,"("))ProcessError(5);// 少左括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es =expression();if(es == false)return(es);if(strcmp(token,")"))ProcessError(6);// 少右括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es = statement();if(es == false)return es;return(es);}//<for 语句 >::=for(<表达式>;<表达式>;<表达式>)<语句>//<for_stat>::=for(<expression>;<expression>;<expression>)<statement> bool for_stat(){bool es =true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,"(")) ProcessError(5);//少左括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";")) ProcessError(4); //少分号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少 }return false;//文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";"))ProcessError(4);//少分号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少 }return false;//文件结束}es=expression();if(es == false) return (es);if(strcmp(token,")"))ProcessError(6);//少右括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少 }return false;//文件结束}es=statement();if(es == false) return (es);return es;}//<write_语句>::=write<表达式>;//<write_stat>::=write<expression>bool write_stat(){bool es = true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";")) ProcessError(4); //少分号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}return es;}//<read_语句>::=read<变量>//<read_stat>::=read Id;bool read_stat(){bool es =true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}if(strcmp(token,"ID"))ProcessError(3); //少标识符if(strcmp(token,";"))ProcessError(4); //少分号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}return es;}//< 复合语句 >::{< 语句序列 >}//<compound_stat>::={<statement_list>}bool compound_stat()//复合语句函数{bool es =true;if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es =statement_list();if(es == false)return es;//-------------- new----------if(strcmp(token1,"}") != 0)ProcessError(2);else{if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}}//--------------- new ----------return es;}//< 表达式语句 >::=<< 表达式 >; |;//<expression_stat>::=<expression>;|;bool expression_stat(){bool es =true;if(strcmp(token,";")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}return es;}es=expression();if(es == false) return es;if(strcmp(token,";")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}return es;}else{ProcessError(4);//少分号}return es;}//< 表达式 >::=< 标识符 >=<布尔表达式 >|< 布尔表达式 >//<expression>::=ID=<bool_expr>|<bool_expr>bool expression(){bool es =true;int fileadd;char token2[20],token3[40];if(strcmp(token,"ID")==0){fileadd=ftell(fp);//记住当前文件位置if( ReadFile(token2,token3) == false ){ProcessError(2);//缺少}return false;//文件结束.}if(strcmp(token2,"=")==0)//'='{if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}es=bool_expr();if(es == false) return es;}else{fseek(fp,fileadd,0); //若非‘ =’,则文件指针回到‘=’前的标识符EsLine--;es=bool_expr();if(es == false) return es;}}else{es=bool_expr();if(es == false) return es;}return es;}//< 布尔表达式 >::=<算术表达式 >[(>|<|>=|<=|==|!=)<算数表达式>]//<bool_expr>::=<additive_expr> [(>|<|>=|<=|==|!=)<additive_expr>]bool bool_expr(){bool es =true;es=additive_expr();if(es == false) return es;.if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"!=")==0||strcmp(token,"==")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es=additive_expr();if(es == false) return es;}return es;}//< 算数表达式 >::=< 项 >{(+|-)<项>}//<additive_expr>::=<term>{(+|-)<term>}bool additive_expr(){bool es =true;es=term();if(es == false) return es;while(strcmp(token,"+")==0||strcmp(token,"-")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es=term();if(es== false) return es;}return es;}//< 项 >::=< 因子 >{(*|/)<因子>}//<term>::=<factor>{(*|/)<factor>}bool term(){bool es =true;es=factor();if(es == false) return es;while(strcmp(token,"*")==0||strcmp(token,"/")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es=factor();if(es == false) return es;}return es;}//< 因子 >::=(< 表达式 >)|< 标识符 >|< 无符号整数 >//<factor>::=(<expression>)|ID|NUMbool factor(){bool es =true;if(strcmp(token,"(")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少} return false;//文件结束}es=expression();if(es==false)return es;if(strcmp(token,")")) ProcessError(6);//少右括号if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}}else{if(strcmp(token,"ID")==0||strcmp(token,"NUM")==0){if( ReadFile(token,token1) == false ){ProcessError(2);//缺少}return false;//文件结束}return es;}else{ProcessError(7);//缺少操作数}}return es;}Scan.cpp#include<ctype.h>#include<cstring>#include<stdio.h>//保留字#define KEYWORDNUM 8char*pKeyword[KEYWORDNUM] ={"if","else","for","while","do", "int", "read", "write"};//单分界符char szSingleWord[50]="+-(){};,:";//双分界符char szDoubleWord[10]="<>!";//其他符char*szDivide="/";char*szStar="*";char*szEqual="=";#define STATUSNUM16// 状态个数#define DATANUM10//数据流个数// 数据流类型typedef unsigned int DATA;#define OTHER0// wrong input#define LETTER1//字母#define DIGIT2//数字#define SINGLEWORD3//单分界符#define DOUBLEWORD4//双分界符#define DIVIDE5// /#define EQUAL6// =#define STAR7// *#define SPACE8//空白#define FILEOVER9//状态类型typedef unsigned int STATUS;#define NOSTATUS0// wrong input#define START1#define CASE_ID2#define END_ID3#define CASE_NUM4#define END_NUM5#define CASE_SINGLE6#define END_SINGLE7#define CASE_DOUBLE8#define CASE_DOUBLE29#define END_DOUBLE10#define CASE_DIVIDE11#define CASE_NOTE12#define END_NOTE13#define CASE_ERROR14#define END_ERROR15//状态转换表//: 到达终结状态的数据不保存在输出串中int reflect[STATUSNUM][DATANUM] ={//OTHER LETTER DIGIT SINGLEWORDDOUBLEWORD DIVIDE EQUAL STAR SPACE FILEOVER/*NOSTATUS*/{NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*START*/{CASE_ERROR,CASE_ID,CASE_NUM,CASE_SINGLE,CASE_DOUBLE,CASE_DIVIDE,CASE_DOUBLE,CASE_SINGLE,START, START},/*CADE_ID*/{END_ID,CASE_ID,CASE_ID,END_ID,END_ID,END_ID,END_ID,END_ID,END_ID,END_ID},/*END_ID*/{NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*CASE_NUM*/{END_NUM,END_NUM,CASE_NUM,END_NUM, END_NUM, END_NUM,END_NUM, END_NUM, END_NUM, END_NUM},/*END_NUM*/{NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS,NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*CASE_SINGLE*/ {END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE},/*END_SINGLE*/ {NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*CASE_DOUBLE*/ {END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, CASE_DOUBLE2,END_SINGLE,END_SINGLE, END_SINGLE},/*CASE_DOUBLE2*/{END_DOUBLE,END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE},/*END_DOUBLE*/ {NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*CASE_DIVIDE*/ {END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, CASE_NOTE, END_SINGLE, END_SINGLE},/*CASE_NOTE*/{END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE},/*END_NOTE*/{NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS},/*CASE_ERROR*/{END_ERROR, END_ERROR,END_ERROR, END_ERROR, END_ERROR, END_ERROR, END_ERROR, END_ERROR, END_ERROR, END_ERROR},/*END_ERROR*/ {NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS, NOSTATUS} };//若在 pString 中找到 word 则返回 true ,否则,返回 false boolSearchChar(char word,const char *pString){int n=strlen(pString);for(int i = 0; i < n; i++){if( word == pString[i])return true;}return false;}//得到 word 的数据流类型DATA GetDataByword(char word){if(word == EOF)return FILEOVER;if(isalpha(word))return LETTER;if(isdigit(word))return DIGIT;if(SearchChar(word,szSingleWord))return SINGLEWORD;if(SearchChar(word,szDoubleWord))return DOUBLEWORD;if(SearchChar(word,szDivide))return DIVIDE;if(SearchChar(word,szEqual))return EQUAL;if(SearchChar(word,szStar))return STAR;if(isspace(word))return SPACE;return OTHER;}//得到从 status 状态输入 word 后到达的状态STATUS GetNextStatus(STATUS status, DATA word){return reflect[status][word];}// 返回值表示错误个数。
Java 词法分析器实验报告--07111101--奥特曼一.词法分析器功能概述:1.使用DFA实现词法分析器的设计;2.实现对Java源程序中注释和空格(空行)的过滤;3.利用两对半缓冲区从文件中逐一读取单词;4.词法分析结果属性字流存放在独立文件(c:\words.txt)中;5.统计源程序所有单词数以、错误单词数、单词所在的行数;6.具有报告词法错误和出错位置(源程序行号)的功能;二.源程序设计实现://程序大部分参照网络,自己做了小部分改动#include<iostream>#include<fstream>#include<cstdio>#include<cstdlib>#include<cstring>#include"const.h"using namespace std;char rbuf[RBUFSIZE]; //读文件缓冲区int rp; //读文件缓冲区指针char ch; //当前扫描到的字符int type; //单词的类型char sbuf[SBUFSIZE]; //单词字符串缓冲区int sp; //单词字符串缓冲区指针ifstream inFile; //输入文件ofstream outFile; //输出文件void clear_rbuf()//清空读文件缓冲区{int i;for(i=0;i<RBUFSIZE;i++)rbuf[i]='\0';rp=0;}void clear_sbuf()//清空单词字符缓冲区{int i;for(i=0;i<SBUFSIZE;i++)sbuf[i]='\0';sp=0;}void get_ch()//从读文件缓冲区得到下一个字符{ch=rbuf[rp];rp++;}void put_ch(char ch)//向字符缓冲区追加一个字符{sbuf[sp]=ch;sp++;}void get_type(char * msg)//得到单词类型{int i;for(i=0;i<TABLE_LENGTH;i++){if (!strcmp(msg, ATTR_MAP[i].keyword)){type=ATTR_MAP[i].type;return;}}return;}int digit(int base)//判断字符是否属于base进制并转换{char c=ch;int result;if (c>='0'&&c<='7')result = (int)(c - '0');else if(c>='8'&&c<='9'){if (base > 8)result=(int)(c-'0');elseresult = -1;}else if(c>='a'&&c<= 'f'){if (base>10)result=(int)(c-'a'+10);elseresult=-1;}else if (c>='A'&&c<='F'){if (base>10)result=(int)(c-'A'+10);elseresult=-1;}elseresult=-1;return result;}void scan_fraction()//扫描指数{while(digit(10)>=0){put_ch(ch);get_ch();}if(ch=='e'||ch=='E'){put_ch(ch);get_ch();if(ch=='+'||ch=='-'){put_ch(ch);get_ch();}while(digit(10)>=0){put_ch(ch);get_ch();}return;}return;}void scan_suffix() //扫描浮点数后缀{scan_fraction();if(ch=='f'||ch=='F'||ch=='d'||ch=='D'){put_ch(ch);get_ch();}type=T_FLOAT;return;}bool is_spectial(char &ch)//判断字符是否是特殊字符{if(ch=='!'||ch=='%'||ch=='&'||ch=='*'||ch=='?'||ch=='+'||ch=='-'||ch==':'||ch=='<'| |ch=='='||ch=='>'||ch=='^'||ch=='|'||ch=='~')return true;elsereturn false;}void scan_operator()//扫描运算符{while (is_spectial(ch)){put_ch(ch);get_ch();}get_type(sbuf);if(type==0)type=T_ERROR;return;}void scan_number(int radix)//扫描8、10、16进制数值{while(digit(radix)>=0){put_ch(ch);get_ch();}if(radix!=10&&ch=='.'){put_ch(ch);get_ch();type=T_ERROR;}else if(radix==10&&ch=='.'){put_ch('.');get_ch();if(digit(10)>=0)scan_suffix();}else if(radix==10&&(ch=='e'||ch=='E'||ch=='f'||ch=='F'||ch=='d'||ch=='D')) scan_suffix();else if(ch == 'l' || ch == 'L'){put_ch(ch);get_ch();type=T_INT;}else type=T_INT;return;}void skip_comment()//跳过注释内容{while(ch!='\0'){switch(ch){case'*':get_ch();if (ch=='/'){get_ch();return;}break;default:get_ch();break;}}}bool is_idchar(char &ch)//判断字符是否标识符首字符{return((ch>='0'&&ch<='9')||(ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||ch=='$'||ch=='_');}void scan_ident()//搜索关键字、标识符{bool id_or_key = true;bool tem=true;//是否仍是标识符或关键字while(ch!=C_TAB&&ch!=C_FF&&ch!=C_CR&&ch!=C_LF&&ch!='\0') {if(is_idchar(ch)){put_ch(ch);get_ch();if(is_idchar(ch))continue;elseget_type(sbuf);if(type!=0)return;else{type=T_IDENTIFIER;return;}}}}void scan_char()//转义字符搜索字符{int oct = 0;int hex = 0;if(ch=='\\'){get_ch();if(ch=='\\')put_ch('\\');get_ch();if(ch=='\'')put_ch('\'');get_ch();if(ch=='\"')put_ch('\"');get_ch();if(ch=='b')put_ch('\b');get_ch();if(ch=='t')put_ch('\t');get_ch();if(ch=='n')put_ch('\n');get_ch();if(ch=='f')put_ch('\f');get_ch();if(ch=='r')put_ch('\r');get_ch();if('0'<=ch&&ch<='7'){oct=digit(8);get_ch();if('0'<=ch&&ch<='7'){oct=oct*8+digit(8);get_ch();if('0'<=ch&&ch<='7'){oct=oct*8+digit(8);get_ch();}}put_ch((char)oct);}if(ch=='u'){get_ch();if(('0'<=ch&&ch<='9')||('a'<=ch&&ch<='f')||('A'<=ch&&ch<='F')){hex=hex*16+digit(16);get_ch();if(('0'<=ch&&ch<='9')||('a'<=ch&&ch<='f')||('A'<=ch&&ch<='F')){hex=hex*16+digit(16);get_ch();if(('0'<=ch&&ch<='9')||('a'<=ch&&ch<='f')||('A'<=ch&&ch<='F')) {hex=hex*16+digit(16);get_ch();if(('0'<=ch&&ch<='9')||('a'<=ch&&ch<='f')||('A'<=ch&&ch<='F')){hex=hex*16+digit(16);get_ch();}}}}put_ch((char)hex);}}else{put_ch(ch);get_ch();}}void get_word()//获取下一个单词及属性{clear_sbuf();type=0;while (ch!='\0'){if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||ch=='$'||ch=='_')//关键字、标识符{scan_ident();return;}else if(ch=='\'')//字符{get_ch();if(ch=='\''){type=T_ERROR;strcpy(sbuf,"''");get_ch();}else{scan_char();if(ch=='\''){type=T_CHAR;get_ch();}else type=T_ERROR;}return;}else if(ch=='\"')//字符串{get_ch();{type=T_ERROR;strcpy(sbuf,"\"\"");get_ch();}else{do{scan_char();}while(ch!='\"'&&ch!=C_TAB&&ch!=C_FF&&ch!=C_CR&&ch!=C_LF);if(ch=='\"'){type=T_STRING;get_ch();}else type=T_ERROR;}return;}else if(ch=='.')//.开头数字{put_ch(ch);get_ch();if(digit(10)>=0)scan_suffix();else type=T_BOUND;return;}else if(ch=='0')//0开头数字{put_ch('0');get_ch();if(ch=='x'||ch=='X'){put_ch(ch);get_ch();if(digit(16)>=0&&ch!='0')scan_number(16);}else if(digit(8)>=0&&ch!='0')scan_number(8);{put_ch('.');get_ch();if(digit(10)>=0)scan_suffix();}else if(ch==' '){get_ch();type=T_INT;}else type=T_ERROR;return;}else if('1'<=ch&&ch<='9')//1-9开头数字{scan_number(10);return;}else if((ch=='(')||(ch==')')||(ch=='[')||(ch==']'))//9个界限符中的8个{put_ch(ch);get_ch();type = T_BOUND;return;}else if(ch==','){put_ch(ch);get_ch();type = T_COMMA;return;}else if((ch=='{')||(ch=='}')){put_ch(ch);get_ch();type = T_BRACKET;return;}else if(ch==';'){put_ch(ch);get_ch();type = T_SEMICOLON;return;}else if(ch=='/')//注释、'/'运算符、 '/='运算符 {get_ch();if(ch=='/'){while(ch!=C_CR&&ch!=C_LF&&ch!='\0') get_ch();break;}else if(ch=='*'){get_ch();skip_comment();}else if(ch=='='){strcpy(sbuf, "/=");type=T_ASSIGN;get_ch();}else{strcpy(sbuf, "/");type=T_MULDIV;}return;}else if(is_spectial(ch))//特殊字符{scan_operator();return;}else get_ch();//间隔符}}void readfile(char * fn_in)//将源文件读入缓冲区{rp = 0;inFile.open(fn_in);if (!inFile.is_open())return;while(inFile.get(rbuf[rp]))rp++;inFile.close();rp = 0;}void writefile()//向输出文件写字符{sp = 0;outFile << "(0x" << hex << type << ") ";outFile << "[";while(sbuf[sp]!='\0'){outFile << sbuf[sp];sp++;}outFile << "]";outFile << endl;sp = 0;}int main(int argc, char * argv[]){char fn_in[NAMESIZE];char fn_out[NAMESIZE];cout << "Input the name of Java source file: ";cin >> fn_in;readfile(fn_in);cout << "Input name of testing result file: ";cin >> fn_out;outFile.open(fn_out);get_ch();while(ch!='\0'){get_word();if(strlen(sbuf)!=0)writefile();}outFile.close();cout << "The analysis has been completed!" << endl;system("pause");return 0;}三.程序执行流程a.首先从Java文件中读取半个缓冲区的字符串读入预处理缓冲区中,将缓冲区中的注释、空行、空格全部处理,最后预处理缓冲区里面只剩下单词、一个空格、换行;b.将预处理缓冲区里面的的数据分两次读入两对半缓冲区ScanBuffer中,送入词法分析器wordScanner进行逐个单词分析,由wordScanner调用相应的转换函数进行单词属性的分析。
西安邮电学院编译原理实验报告——词法分析器系别:计算机系班级:计科0701姓名:王会银学号:04071026指导老师:王春梅实验时间:2010.4.5—2010.4.12一实验目的:1.巩固课本知识,学会利用状态转换图分析词法结构;2.深入了解词法分析的过程;3.做好词法分析,巩固并获得新的C语言编程的技巧。
二实验要求所输出的每一单词,均按形如(CLASS,VALUE)的二元式编码。
对于变量标识符和常数,CLASS字段为相应的类别码,VALUE字段则是该标识符、常数在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串,其最大长度为四个字符;常数表登记项中则存放该整数的二进制形式。
)。
对于保留字和分隔号,由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。
不过,为便于查看由词法分析程序所输出的单词串,也可以在CLASS字段上直接放置单词符号串本身。
三实验分析1.功能:输入源程序,输出单词符号。
单词符号是一个程序语言的基本语法符号。
2.单词的分类(五类):.关键字:由程序语言定义的具有固定意义的标识符。
. 标识符:用来表示程序中各种名字的字符串。
. 常数:常数的类型一般有整型、实型、布尔型、文字型。
. 运算符和界限符:如+、-、*、/ 等。
3.一个程序语言的关键字、运算符、界限符都是固定的,即数量有限及意义明确;而对于标识符和常数通常是不确定的。
词法分析器所输出的单词符号常常表示成如下的二元式:( <类别码,序号> 输入串/单词符号)单词种别通常用整数编码。
标识符一般统归为一种。
常数则宜按类型(整、实、布尔等)分种。
关键字可将其全体视为一种,也可以一字一种。
运算符和界符可采用一符一种的分法,但也可以把具有一定共性的运算符视为一种。
对于下述C代码段:FILE *f; //定义一个文件变量static int line = 1; //表示光标所在的行数int same(char *chr); //判断单词是否已经存在void Error(){error[K++] = line;}经词法分析器处理后,它将被转换为如下的单词符号序列:4.键字还是标识符的函数中判断,如果是数字,则判断是常数还是其他,在界符判断函数里面将所遇到的界符一一输出。
编译原理实验报告词法分析器实验目的1.熟练掌握词法分析程序的基本原理2.掌握词法分析程序的设计和实现实验内容1.针对一个简化的C语言子集完成对它的词法分析程序的设计与实现2.C语言子集的单词符号挤内码值程序代码:#include "stdio.h"#include "string.h"int i,j,k;char s;char a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int digit(){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(){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("输入源程序,结束用'#':\n");i=0;do{i++;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*20);j=0;get();while(s!='#'){if(s==' ')get();else{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++;get();}retract();k=lookup();if(k==0)printf("(%d,%s)\n",6,token); else printf("(%d,unll)\n",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)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n");break;case'*':printf("(*,null)\n");break;case'<':get();if(s=='=')printf("(relop,LE)\n");else {retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n");else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n");break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}运行结果:编译原理实验报告语法分析器实验目的1.熟练掌握语法分析程序的基本原理2.掌握用算符优先分析法来构造,设计优先函数3.掌握语法分析程序的设计与实现实验内容1.针对一个简单文法完成对它的语法分析程序的设计与实现2.通过语法分析程序来完成多输入的算数表达式进行计算并相应得到的对应四元式程序代码:#include <stdio.h>char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>='0')&&(s<='9'))return 1;elsereturn 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error!\n");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error!\n");}}void get(){i=i+1;s=a[i];}void main(){printf("请输入算数表达式,以'#'结束:\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j] != '#')||(s != '#')){if(operand(s)){opnd[k]=s-'0';k=k+1;get();}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else if(f(optr[j]) < g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j]) == g(s)){j=j-1;get();}elseprintf("error!");}}运行结果:。
《编译原理》课程实验报告课程实验题目:词法分析器学院:计算机科学与技术班级:软件1503学号:04153094姓名:刘欣指导教师姓名:陈燕完成时间:词法分析定义:词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。
单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常量等(1) 关键字是由程序语言定义的具有固定意义的标识符。
例如,Pascal 中的begin,end,if,while都是保留字。
这些字通常不用作一般标识符。
(2) 标识符用来表示各种名字,如变量名,数组名,过程名等等。
(3) 常数常数的类型一般有整型、实型、布尔型、文字型等。
(4) 运算符如+、-、*、/等等。
(5) 界符如逗号、分号、括号、等等。
输出:词法分析器所输出单词符号常常表示成如下的二元式:(单词种别,单词符号的属性值)单词种别通常用整数编码。
标识符一般统归为一种。
常数则宜按类型(整、实、布尔等)分种。
关键字可将其全体视为一种。
运算符可采用一符一种的方法。
界符一般用一符一种的方法。
对于每个单词符号,除了给出了种别编码之外,还应给出有关单词符号的属性信息。
单词符号的属性是指单词符号的特性或特征。
示例:比如如下的代码段:while(i>=j) i--经词法分析器处理后,它将被转为如下的单词符号序列:<while, _><(, _><id, 指向i的符号表项的指针><>=, _><id, 指向j的符号表项的指针><), _><id, 指向i的符号表项的指针><--, _><;, _>词法分析分析器作为一个独立子程序词法分析是编译过程中的一个阶段,在语法分析前进行。
词法分析作为一遍,可以简化设计,改进编译效率,增加编译系统的可移植性。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
词法分析器一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
二、实验要求如源程序为C语言。
输入如下一段:Array main(){int a,b;a = 10;b = a + 20;}#要求输出如右图。
要求:1、将单词分为五种识别关键字:main、if、int、for、while、do、return、break、continue;单词种别码为1。
标识符;单词种别码为2。
常数为无符号整形数;单词种别码为3。
运算符包括:+、-、*、/、=、>、<、>=、<=、!= ;单词种别码为4。
分隔符包括:,、;、{、}、(、);单词种别码为5。
2、使用一符一种的分法关键字、运算符和分界符可以每一个均为一种标识符和常数仍然一类一种三、实验内容1、功能描述改程序是一个实现词法分析的功能,能识别5种单词,其他单词报错。
2、程序结构描述int IsKey(char *Word)关键字匹配函数,查询是否为关键字,若是,返回值为1,否则为0。
int IsAlpha(char c) 查看是否为字母,若是,返回值为1,否则为0。
int IsNum(char c) 查看是否为数字,若是,返回值为1,否则为0。
void scanner(FILE *fp) 扫描函数,扫描程序中的字符串并调用上述三种函数检查是否是字母、数字,是否是关键字,并输出。
fseek(fp,-1,1)回退一个字符。
fgetc(fp)从数据流中区下一个字符。
fopen 文件打开函数,返回指向文件第一个字符的指针四、实验结果测试内容为main(){int a,b;a = 10;b = a + 20; }#结果测试代码为void main() {int a,b; if(a = 10;)b += 20; c=%;}#结果为测试代码main(){int a,b;if(a <= "10")b += 20;c=%@;return 0;}#结果五、实验过程记录1、因为用到回退函数fseek(),而以前没有用过这个函数,所以开始时很苦恼,不知道如何回退一个字符,后来问了同学,才明白原来有这么一个函数,顿时豁然开朗。
院系:计算机学院实验课程:编译原理实验项目:C++源代码单词扫描程序(词法分析)指导老师:陈寅开课时间:2014~2015年度第1学期专业:数据库班级:2班学生:雷楚楚学号:20122100158C++源代码单词扫描程序(词法分析)一、实验目的设计并实现一个词法分析器,深刻理解编译原理中词法分析器的原理。
二、实验内容1、C++源代码扫描程序识别C++记号。
C++语言包含了几种类型的记号:标识符,关键字,数(包括整数、浮点数),字符串,注释,特殊符号(分解符)和运算符号等。
2、打开一个C++源文件,打印出所有以上的记号。
3、选作部分:为了提高C++源程序的可读性,C++程序在书写过程中加入了空行、空格、缩进、注释等。
假设你想牺牲可读性,以节省磁盘空间,那么你可以存贮一个删除了所有不必要空格和注释的C++源程序的压缩文本。
因此,程序中还看可以有这样的压缩功能。
4、进一步实现减少源文件大小的压缩功能。
5、完善软件文档。
二、实验过程1、对C++文法中的各类单词分类(1)保留字:asm、do、if、return、typedef、auto、double、inline、short、typeid、bool、try、include、long、sizeof、union、case、enum、mutable、static、unsigned、long、sizeof、union、case、enum、mutable、static、unsigned、catch、explicit、namespace、using、char、export、int、signed、break、else、new、struct、virtual、class、extern、operator、switch、void、const、false、private、template、volatile、float、protected、this、continue、for、public、throw、while、default、friend、register、true、delete、goto、try、include、std、iomanip、setw、setprecision、endl、setiosflags、ios (2)数字:包括整数和浮点数(3)标识符:由字母打头的字母和数字的字符串,可包含下划线(4)运算符:"&="、"^="、"、="、"<<="、">>="、"*="、"/="、"%="、"+="、"-="、"="、"?:"、"、、"、"&&"、"、"、"^"、"&"、"=="、"!="、">"、">="、"<"、"<="、"<<"、">>"、"+"、"-"、"*"、"/"、"%"、".*"、"->*"、"&"、"+"、"-"、"++"、"--"、"->"、"::"(5)界符:"{"、"}"、"("、")"、"#"、","、":"、";"、"."、"\""(6)注释:包括//和/**/两种类型的注释(7)字符串:包含在“”里面的内容2、将各类单词对应到Flex中:(1)保留字:asm|do|if|return|typedef|auto|double|inline|short|typeid|bool|try|include|long|sizeof|union|case|enum|mutable|static|unsigned|long|sizeof|union|case|enum|mutable|static|unsigned|catch|explicit|namespace|using|char|export|int|signed|break|else|new|struct|virtual|class|extern|operator|switch|void|const|false|private|template|volatile|float|protected|this|continue|for|public|throw|while|default|friend|register|true|delete|goto|try|include|std|iomanip|setw|setprecision|endl|setiosflags|ios(2)数字:包括整数和浮点数(正负)[+-]?([0-9]*|0|([0-9]*\.[0-9]*))(3)标识符:由字母打头的字母和数字的字符串,包含下划线[A-Za-z]([A-Za-z]|[0-9]|_)*(4)运算符:"&="|"^="|"|="|"<<="|">>="|"*="|"/="|"%="|"+="|"-="|"="|"?:"|"||"|"&&"|"|"|"^"|"&"|"=="|"!="|">"|">="|"<"|"<="|"<<"|">>"|"+"|"-"|"*"|"/"|"%"|".*"|"->*"|"&"|"+"|"-"|"++"|"--"|"->"|"::"(5)界符:"{"|"}"|"("|")"|"#"|","|":"|";"|"."|"\""(6)注释:包括//和/**/两种类型的注释\/\*(\s|.)*?\*\/(/**/)\/\/[^\n]*(//)(7)字符串:包含在“”里面的内容'[^'\n]*'|\"[^\"]*\"(8)除其他情况之外判断为出错3、跳过空行和空格[\t]+{}/*空格*/ \n|.{}/*空行*/4、为lex制定一些规则5、写子程序让用户输入要进行词法扫描的文件,当lex读完输入文件之后就会调用函数yywrap。
编译原理课程设计:词法分析器词法分析器一、实验目的和要求:设计并实现一个PL/0语言(或其它语言,如C语言)的词法分析程序,加深对词法分析原理的理解。
二、实验原理:词法分析是从左向右扫描每行源程序的符号,拼成单词,换成统一的机内表示形式——TOKEN字,送给语法分析程序。
TOKEN字是一个二元式:(单词种别码,自身值)。
PL/0语言单词的种别码参见教材(或自行设定),单词自身值按如下规则给出:1 标识符的自身值是它在符号表的入口地址。
2常数的自身值是常数本身(或它的二进制数值)。
3关键字和界限符的自身值为本身。
三、实验步骤与要求1、设计的词法分析器符合软件工程的要求。
2、编制程序,此程序应具有如下功能:1)输入:字符串(待进行词法分析的源程序),输出:由(种别码,自身值)所组成的二元组序列。
2)功能:a.滤空格b.识别保留字c.识别标识符d.拼数e.拼复合单词: 例如:>=、 <=、 :=3)检查如下错误:a.程序语言的字符集以外的非法字符b.单词拼错,如9A88,而对于将begin拼写成begon的错误,只须把begon当成标识符即可3、请指导教师检查程序和运行结果,评定成绩。
4、撰写并上交实验报告。
四、试验设计和算法分析:实验原理:程序流程:置初值→调用扫描子程序→输出串结束→输出单词二元组→是→否→结束词法分析主程序示意图待分析的简单语言的词法(1) 关键字:begin if then while do end所有关键字都是小写。
(2)运算符和界符::= + - * / < > <= <> >= ; ( ) #(3):其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter | digit)*NUM=digit digit*(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。
词法分析报告编译原理实验报告实验一词法分析程序的设计与实现指导教师:姓名:学号:班级:一、实验目的基本掌握计算机语言的词法分析程序的开发方法。
二、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求1.根据以下的正规式,编制正规文法,画出状态图;标识符 (|)*十进制整数 0 | (1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)* 八进制整数 0(0|1|2|3|4|5|6|7) (0|1|2|3|4|5|6|7)*十六进制整数 0 (x|X) (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)* 运算符和分隔符 + - * / > < = ( ) ; 关键字if then else while do2.根据状态图,设计词法分析函数int scan( ),完成以下功能:(1)从输入流(键盘或文件)读入数据,分析出一个单词。
(2)返回单词种别(用整数表示),(3)返回单词属性(不同的属性可以放在不同的全局变量中)。
3.编写测试程序,循环调用函数scan( ),每次调用,获得一个单词的信息。
在测试程序中,打印输出单词种别、属性(注意:不要在词法分析函数scan 中打印输出!)。
四、实验环境微型计算机。
Windows 操作系统/Linux 操作系统。
编程语言:C/C++/Java/C#。
建议使用Visual C++/Netbeans/Eclipse 集成开发环境。
五、实验步骤1. 根据状态图,设计词法分析算法2. 设计函数scan( ),实现该算法3. 编制测试程序(在本试验中,可以是主函数main( ) )。
4. 调试程序:输入一组单词,检查输出结果。
六、状态图七. 测试数据: 0 92+data> 0x3f00 while八.测试结果九,思考题1. 词法分析能否采用空格来区分单词?答:不能,因为比如abc+bcd中没有空格,但这是三个单词。
C_minus语言词法分析器的设计一实验目的设计一个简单的词法分析器,从而进一步加深对词法分析器工作原理的理解.二实验内容编制一个能够分析整数、标识符、主要运算符和主要关键字的词法分析器。
三实验要求1、该个词法分析器要求至少能够识别以下几类单词:关键字:else if int return void while共6个,所有的关键字都是保留字,并且必须是小写;标识符:识别与C语言词法规定相一致的标识符,通过下列正则表达式定义:ID = letter (letter | digit)*;常数:NUM = digit digit*(.digit digit* |ε)(e(+ |— |ε) digit digit* |ε),letter = a|..|z|A|。
.|Z|,digit = 0|..|9,包括整数,如123等;小数,如123。
45等;科学计数法表示的常数,如1。
23e3,2.3e—9等;专用符号:+ — * / < <= > 〉= == != = ; ,()[ ] { } /* */;2、分析器的输入为由上述几类单词构成的程序,输出为该段程序的机内表示形式,即关键字、运算符、界限符变为其对应的机内符,常数使用二进制形式,标识符使用相应的标识符表指针表示.3、词法分析器应当能够指出源程序中的词法错误,如不可识别的符号、错误的词法等。
四实验环境PC微机;Windows操作系统;本次实验采用visual C++程序集成环境,采用C语言编写。
五实验步骤(一)构造单词的分类表单词的分类:构造上述语言中的各类单词符号及其分类码表如下:词法分析器实验报告(二)实验原理图(三)主要实验代码:1。
全局变量:char prog[80]={'\0’},//存放程序char token[8]; //存放构成单词符号的字符串char ch;//输入字符int syn,//存放单词字符的种别码sum, //存放整数型单词p, //p是缓冲区prog的指针n=-1;//记录标识符在符号表中的位置char *keyword[6]={"else”,"if",”int","while","void”,”return"};2.main函数2.1输入源程序:do{ch=getchar();prog[p++]=ch;}while(ch!='#');2.2循环调用子函数:do{scaner();switch(syn){case 11: break;case -1: printf("\n ERROR;\n”);break;case 10: printf(”(%d,%s的符号表入口地址%d)\n”,syn,token,n);break;default: printf("(%d,%s)\n",syn,token);}}while(syn!=0);3。
编译原理实验(一)——词法分析器一.实验描述运行环境: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置为空白字符。
void input();//向存放输入结果的字符数组输入一句语句。
void display();//输出一些程序结束字符显示样式int analyzerSubFun();//词法分析器子程序,为了实现词法分析的主要功能。
五.代码实现// cifa.cpp : 定义控制台应用程序的入口点。
//#include"stdafx.h"#include"stdio.h"#include"string.h"#include"iostream"using namespace std;char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量//int Words[500][10];char ch;//当前读入字符int sr,to=0;//数组str, strtaken 的指针int st=0,dcount=0;int id=0;static int line=1;int h,l;typedef struct Words /*放置二元组*/{int num;char letters[20];}DS;DS Words[500];typedef struct words{char word[20];int type;}WORDS;WORDS words[]={{"program",0},{"not",1},{"begin",2},{"end",3},{"if",4},{"then",5},{"var",6},{"else",7},{"int",8},{"while",9},{"and",10},{"do",11},{"or",12},{"+",15},{"-",16},{"(",17},{")",18},{",",19},{";",20},{"=",21},{"<",22},{">",23},{"*",24},{"**",25},{">=",26},{"<=",27},{"!=",28}};typedef struct keytable /*放置关键字*/ {char name[20];int kind;}KEYTABLE;KEYTABLE keyword[]={ /*设置关键字*/{"program",0},{"not",1},{"begin",2},{"end",3},{"if",4},{"then",5},{"var",6},{"else",7},{"int",8},{"while",9},{"and",10},{"do",11},{"or",12},};void openfile() /*打开文件*/{cout<<"____________________________________________________"<<endl;cout<<" 词法分析器 "<<endl;cout<<"____________________________________________________"<<endl;cout<<"请在本程序根目录下寻找以.txt”为结尾的文件作为词法分析对象,输入文件名"<<endl;FILE *fp;char a,filename[10];int n=0;gets(filename);if((fp=fopen(filename,"r"))==NULL){printf("cannot open file.\n");//exit(0);}elsewhile(!feof(fp)) /*文件不结束,则循环*/{a=getc(fp); /*getc函数带回一个字符,赋给a*/set[n]=a; /*文件的每一个字符都放入set[]数组中*/n++;}fclose(fp); /*关闭文件*/set[n-1]='\0';void reflesh() /*清空strtaken数组*/{to=0; /*全局变量to是strtaken的指示器*/strcpy(strtaken," ");}void pre1() /*预处理程序*/{int i,a,b,n=0;do{if(set[n]=='/' && set[n+1]=='*'){a=n; /*记录第一个注释符的位置*/while(!(set[n]=='*' && set[n+1]=='/')){if(set[n]=='\n')line++;n++;}b=n+1; /*记录第二个注释符的位置*/for(i=a;i<=b;i++) /**/set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ }else if(set[n]=='/' && set[n+1]=='/'){a=n; /*记录第一个注释符的位置*/while(!set[n]=='\n')n++;b=n+1; /*记录第二个注释符的位置*/for(i=a;i<=b;i++) /**/set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ }n++;}while(set[n]!='\0');}void pre2() /*预处理程序*/int j=0;sr=0; /*全局变量sr是str[]的指示器*/do{if(set[j]==' '|| set[j]=='\n'){while(set[j]==' ' || set[j]=='\n') /*扫描到有连续的空格或换行符*/{ if(set[j]=='\n') line++;j++;}str[sr]=' '; /*用一个空格代替扫描到的连续空格和换行符放入str[]*/ sr++;}else{str[sr]=set[j]; /*若当前字符不为空格或换行符就直接放入str[]*/sr++;j++;}}while(set[j]!='\0');str[sr]='\0';}char GetChar() /*把字符读入全局变量ch中,指示器sr前移*/{ch=str[sr];sr++;return(str[sr-1]);}void GetBC() /*开始读入符号,直至第一个不为空格*/{while(ch==' '){ch=GetChar();}}void Concat() /*把ch中的字符放入strtaken[]*/{strtaken[to]=ch;to++; /*全局变量to是strtaken的指示器*/strtaken[to]='\0';}int IsLetter() /*判断是否为字母*/{if((ch>='a' && ch<='z')||(ch>='A' && ch<='Z'))return(1);else return(0);}int IsDigit() /*判断是否为数字*/{if(ch>='0' && ch<='9')return(1);else return(0);}int Reserve() /*对strtaken中的字符串查找保留字表,若是则返回它的编码,否则返回-*/ {int i,k=0;for(i=0;i<=12;i++){if(stricmp(strtaken,keyword[i].name)==0){ k=1;Words[dcount].num=keyword[i].kind;strcpy(Words[dcount].letters,"-");dcount++;return(keyword[i].kind);}}if(k!=1)return(-1);}void Retract() /*指示器sr回调一个字符位置,把ch置为空*/{sr--;ch=' ';}int InsertId(){int i,k;for(i=0;i<id;i++){k=strcmp(strtaken,sign[i]);if(k==0)return(i);}strcpy(sign[id],strtaken); /*插入标识符*/Words[dcount].num=13;strcpy(Words[dcount].letters,strtaken);id++;dcount++;return(id-1);}int InsertConst(){int i,k;for(i=0;i<st;i++){k=strcmp(strtaken,constant[i]);if(k==0)return(i);}strcpy(constant[st],strtaken);/*插入常数*/Words[dcount].num=14;strcpy(Words[dcount].letters,strtaken);st++;dcount++;return(st-1);}void analysis(){int value;reflesh(); /*清空strtaken数组*/pre1(); /*预处理,使注释内容换成单个空格,放回set[]中*/pre2(); /*预处理,使set[]中连续的空格置换成单个空格,并把set[]的内容放到str[]中*/sr=0;GetChar(); /*把字符读入全局变量ch中,指示器sr前移*/GetBC(); /*读取第一个字符*/while(ch!='\0') /*当不等于结束符,继续执行*/{if(IsLetter())//标识符和关键字判定{while(IsLetter() || IsDigit()) /*若第一个是字符,继续读取,直到出现空格*/{Concat();GetChar(); /*把字符读入全局变量ch中,指示器sr前移*/}Retract(); /*指示器sr回调一个字符位置,把ch置为空*/value=Reserve(); /*对strtaken中的字符串查找保留字表,若是则返回它的编码,否则返回-*/if(value==-1) /*如果返回值是-,那就是标识符,把它输出*/{InsertId(); /*插入标识符*/}reflesh();}else if(IsDigit()){while(IsDigit()) /*否则,若第一个是数字,继续读取,直到出现空格*/{Concat(); /*把ch中的字符放入strtaken[]*/GetChar();}Retract(); /*指示器sr回调一个字符位置,把ch置为空*/InsertConst(); /*插入常数,返回类型为int*///printf(" %s",strtaken);//getchar();reflesh();}elseswitch(ch) /*否则,若是下面的符号*/{case'+':case'-':case'(':case')':case',':case';':case'=':case'<':case'>':Concat();for(int c0=15;c0<=23;c0++){if(stricmp(strtaken,words[c0].word)==0){Words[dcount].num=words[c0].type;dcount++;}}reflesh();break;default:if(ch=='*') /*如果是"*"符号,继续读取下一个*/{Concat(); /*判断是否为"**"的情况*/GetChar();if(ch==strtaken[0])Concat();elseRetract();for(int c1=24;c1<=25;c1++){if(stricmp(strtaken,words[c1].word)==0){Words[dcount].num=words[c1].type;dcount++;}}//printf(" %s",strtaken);//getchar();reflesh();break;}else if(ch=='<' || ch=='>' || ch=='!'){Concat(); /*判断是否为<=,>=,!=的情况*/GetChar();if(ch=='=')Concat();elseRetract();for(int c2=26;c2<=28;c2++){if(stricmp(strtaken,words[c2].word)==0){Words[dcount].num=words[c2].type;dcount++;}}reflesh();break;}else{ h=ch/line;l=ch%line;cout<<"Error in "<<h<<"行"<<l<<"列"<<endl;//getchar();break;}}GetChar();GetBC();}cout<<"输出二元组:"<<endl;for(int d_i=0;d_i<dcount;d_i++)cout<<Words[d_i].num<<" "<<Words[d_i].letters<<endl;cout<<endl;cout<<"输出标识符:"<<endl;for(int sign_i=0;sign_i<id;sign_i++)cout<<sign_i<<" "<<sign[sign_i]<<endl;cout<<endl;cout<<"输出常量:"<<endl;for(int const_i=0;const_i<st;const_i++)cout<<const_i<<" "<<constant[const_i]<<endl;cout<<endl;}int _tmain(int argc, _TCHAR* argv[]){openfile();analysis();printf("Analysis is finished!");getchar();return 0;}测试结果测试语句为:Program example ;var int j,m,n;Begin /*there is * a/ comment*/ i:=2;j:=6;m:=3; //there is a commentn:=j+m;If n>=3 and n<5then j:=j-1;end .结果截图:六.总结我在这次词法分析器的设计过程中学到了很多东西,其中最大的收获是对于编译原理中的词法分析这一过程理解的更加清楚明了。