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

编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的:1.熟悉编译原理中词法分析的基本概念和原理;2.掌握正则表达式的使用方法;3.实现一个简单的词法分析器。
二、实验内容:1.设计一个简单的编程语言,包含如下几种类型的词法单元:关键字、标识符、常量、运算符和界符。
2.使用正则表达式定义每种词法单元的模式。
3.设计一个词法分析器,将源代码中的每个词法单元识别出来并输出。
三、实验步骤:1. 确定编程语言的词法单元类型和正则表达式模式,定义相应的单词类型(如 TokenType)和模式(如 regex)。
2. 实现一个词法分析器的类 Lexer,包含以下方法:(1)一个构造方法,用于初始化词法分析器的输入源代码。
(2) 一个getNextToken方法,用于获取源代码中的下一个词法单元。
3. 在getNextToken方法中,使用正则表达式逐个识别源代码中的词法单元,并返回相应的Token对象。
4. 设计一个Token类,包含以下属性:词法单元类型、词法单元的值和位置信息等。
5.在主程序中使用词法分析器,将源代码中的每个词法单元识别出来并输出。
四、实验结果:1.设计一个简单的编程语言,包含如下词法单元类型(示例):(1) 关键字:if、else、while、for等;(2)标识符:变量名等;(3)常量:整数、浮点数、字符串等;(4)运算符:+、-、*、/、=等;(5)界符:(、)、{、}、;等。
2. 实现一个词法分析器,识别出源代码中的每个词法单元,并输出相应的Token对象。
五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。
我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。
这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。
词法分析程序实验报告

词法分析程序实验报告篇一:词法分析器_实验报告词法分析器实验报告实验目的:设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。
实验要求:该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分界符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(一)实验内容(1)功能描述:对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。
而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。
(2)程序结构描述:函数调用格式:参数含义:String string;存放读入的字符串 String str; 存放暂时读入的字符串 char ch; 存放读入的字符 int rs 判断读入的文件是否为空 char []data 存放文件中的数据 int m;通过switch用来判断字符类型,函数之间的调用关系图:函数功能:Judgement()判断输入的字符并输出单词符号,返回值为空; getChar() 读取文件的,返回值为空;isLetter(char c) 判断读入的字符是否为字母的,返回值为Boolean类型; switch (m) 判断跳转输出返回值为空;isOperator(char c)判断是否为运算符的,返回值为Boolean类型; isKey(String string)判断是否为关键字的,返回值为Boolean类型; isDigit(char c) 判断读入的字符是否为数字的,返回值为Boolean类型。
(二)实验过程记录:本次实验出错3次,第一次无法输出双运算符,于是采用双重if条件句进行判断,此方法失败,出现了重复输出,继续修改if语句,仍没有成功。
然后就采用了直接方法调用解决此问题。
对于变量的判断,开始忘了考虑字母和数字组成的变量,结果让字母和数字分家了,不过改变if语句的条件,解决了此问题。
词法分析实验总结【词法分析实验报告】

词法分析实验总结词法分析实验报告】
4 试验体会 10 试验目的 1、学会针对 DF 转换图实现相应的高级语言源程序。
文档 《词法分析》 试验报告
2、深刻领会状态转换图的含义,逐步理解有限自动机。 3、把握手工生成词法分析器的方法,了解词法分析器的内部工作原理。 试验内容 TINY 计算机语言描述
}
{
int C::InsertID(chr *strToken)
if(c=c=z||c=c=Z) return true;
{
else return flse;
int i=0;
}
while (im) //设 m 为符号表中已有的标识符的个数
第1页共1页
本文格式为 Word 版,下载可任意编辑,页眉双击删除即可。
if(strcmp([mid],b)==0) return mid;
{
else if(strcmp([mid],b)0) left=mid+1;
if(c=9c=0) return true;
else right=mid-1;
else return flse;
}
ห้องสมุดไป่ตู้
}
return -1;
bool C::isLetter(chr c)
//关键字 bi 编码 1 2 3 4 5 6 7 8
while(left=right)
chr K[18][10]={else,end,if,red,repet,then,until,write,
{
%,*,+,-,/,:,;,,=,};
mid=(left+right)/2;
词法分析实验报告

词法分析实验报告词法分析实验报告引言词法分析是自然语言处理中的一个重要环节,它负责将输入的文本分割成一个个的词语,并确定每个词语的词性。
本次实验旨在通过实现一个简单的词法分析器,来探索词法分析的原理和实践。
实验内容本次实验中,我们使用Python编程语言来实现词法分析器。
我们选取了一段简单的英文文本作为输入,以便更好地理解和演示词法分析的过程。
1. 文本预处理在进行词法分析之前,我们首先需要对输入文本进行预处理。
预处理的目的是去除文本中的标点符号、空格和其他无关的字符,以便更好地进行后续的分词操作。
2. 分词分词是词法分析的核心步骤之一。
在这个步骤中,我们将文本分割成一个个的词语。
常见的分词方法包括基于规则的分词和基于统计的分词。
在本次实验中,我们选择了基于规则的分词方法。
基于规则的分词方法通过事先定义一系列的分词规则来进行分词。
这些规则可以是基于语法的,也可以是基于词典的。
在实验中,我们使用了一个简单的基于词典的分词规则,即根据英文单词的常见前缀和后缀来进行分词。
3. 词性标注词性标注是词法分析的另一个重要步骤。
在这个步骤中,我们为每个词语确定其词性。
词性标注可以通过事先定义的规则和模型来进行。
在本次实验中,我们使用了一个简单的基于规则的词性标注方法。
基于规则的词性标注方法通过定义一系列的词性标注规则来进行词性标注。
这些规则可以是基于词法的,也可以是基于语法的。
在实验中,我们使用了一个简单的基于词法的词性标注规则,即根据英文单词的后缀来确定其词性。
实验结果经过实验,我们得到了输入文本的分词结果和词性标注结果。
分词结果如下:- I- love- natural- language- processing词性标注结果如下:- I (代词)- love (动词)- natural (形容词)- language (名词)- processing (名词)讨论与总结通过本次实验,我们深入了解了词法分析的原理和实践。
编译原理实验词法分析实验报告

编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。
本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。
二、实验环境本次实验使用的编程语言为_____,开发工具为_____。
三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。
单词符号通常包括关键字、标识符、常量、运算符和界符等。
词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。
在本次实验中,我们采用了状态转换图法。
状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。
通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。
四、实验步骤1、定义单词符号的类别和编码首先,确定实验中要识别的单词符号种类,如关键字(if、else、while 等)、标识符、整数常量、浮点数常量、运算符(+、、、/等)和界符(括号、逗号等)。
为每个单词符号类别分配一个唯一的编码,以便后续处理。
2、设计状态转换图根据单词符号的词法规则,绘制状态转换图。
例如,对于标识符的识别,起始状态为“起始状态”,当输入为字母时进入“标识符中间状态”,在“标识符中间状态”中,若输入为字母或数字则继续保持该状态,直到遇到非字母数字字符时结束识别,确定为一个标识符。
3、编写词法分析程序根据状态转换图,使用所选编程语言实现词法分析器。
在程序中,通过不断读取输入字符,根据当前状态进行转移,并在适当的时候输出识别到的单词符号。
4、测试词法分析程序准备一组包含各种单词符号的测试用例。
将测试用例输入到词法分析程序中,检查输出的单词符号是否正确。
五、实验代码以下是本次实验中实现词法分析器的核心代码部分:```include <stdioh>include <ctypeh>//单词符号类别定义typedef enum {KEYWORD,IDENTIFIER,INTEGER_CONSTANT,FLOAT_CONSTANT,OPERATOR,DELIMITER} TokenType;//关键字列表char keywords ={"if","else","while","for","int","float","void"};//状态定义typedef enum {START,IN_IDENTIFIER,IN_INTEGER,IN_FLOAT,IN_OPERATOR} State;//词法分析函数TokenType getToken(char token, int tokenLength) {State state = START;int i = 0;while (1) {char c = getchar();switch (state) {case START:if (isalpha(c)){state = IN_IDENTIFIER;tokeni++= c;} else if (isdigit(c)){state = IN_INTEGER;tokeni++= c;} else if (c =='+'|| c ==''|| c ==''|| c =='/'|| c =='('|| c ==')'|| c ==';'|| c ==','){state = IN_OPERATOR;tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else if (c == EOF) {tokeni ='\0';tokenLength = i;return -1;} else {tokeni ='\0';tokenLength = i;return -2;}break;case IN_IDENTIFIER:if (isalpha(c) || isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;//检查是否为关键字for (int j = 0; j < sizeof(keywords) / sizeof(keywords0); j++){if (strcmp(token, keywordsj) == 0) {return KEYWORD;}}return IDENTIFIER;}break;case IN_INTEGER:if (isdigit(c)){tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return INTEGER_CONSTANT;}break;case IN_FLOAT:if (isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return FLOAT_CONSTANT;}break;case IN_OPERATOR: tokeni ='\0';tokenLength = i;return OPERATOR; break;}}}int main(){char token100;int tokenLength;TokenType tokenType;while ((tokenType = getToken(token, &tokenLength))!=-1) {switch (tokenType) {case KEYWORD:printf("Keyword: %s\n", token);break;case IDENTIFIER:printf("Identifier: %s\n", token);break;case INTEGER_CONSTANT:printf("Integer Constant: %s\n", token);break;case FLOAT_CONSTANT:printf("Float Constant: %s\n", token);break;case OPERATOR:printf("Operator: %s\n", token);break;case DELIMITER:printf("Delimiter: %s\n", token);break;}}return 0;}```六、实验结果对准备的测试用例进行输入,得到的词法分析结果如下:测试用例 1:```int main(){int num = 10;float pi = 314;if (num > 5) {printf("Hello, World!\n");}}```词法分析结果:```Keyword: int Identifier: main Delimiter: (Delimiter: ){Identifier: num Operator: =Integer Constant: 10;Identifier: float Identifier: pi Operator: =Float Constant: 314;Keyword: ifDelimiter: (Identifier: numOperator: >Integer Constant: 5){Identifier: printfDelimiter: (String: "Hello, World!\n" Delimiter: );}```测试用例 2:```for (int i = 0; i < 10; i++){double result = i 25;```词法分析结果:```Keyword: for Delimiter: (Keyword: int Identifier: i Operator: =Integer Constant: 0;Identifier: i Operator: <Integer Constant: 10;Identifier: i Operator: ++)Identifier: doubleIdentifier: resultOperator: =Identifier: iOperator:Float Constant: 25;}```通过对多个测试用例的分析,词法分析器能够正确识别出各种单词符号,实验结果符合预期。
实验一词法分析实验报告1

实验一词法分析一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码与单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验要求使用一符一种的分法关键字、运算符和分界符可以每一个均为一种标识符和常数仍然一类一种三、实验内容功能描述:1、待分析的简单语言的词法(1)关键字:begin if then while do end(2)运算符和界符:(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)*NUM=digit digit *(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的种别码图 1程序结构描述:符号界符等符号四、实验结果输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图3所示:图3输入private x:=9;if x>0 then x:=2*x+1/3; end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图4所示:图4显然,private是关键字,却被识别成了标示符,这是因为图1中没有定义private关键字的种别码,所以把private当成了标示符。
输入private x:=9;if x>0 then x:=2*x+1/3; @ end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5所示图5显然,@没有在图一中定义种别,所以输出了“Error in row 1!”的报错信息。
词法分析实验报告

词法分析实验报告一、实验目的和背景词法分析是编译原理中的重要部分之一,其主要作用是将源程序中的字符序列转化为有意义的单词序列,以便于后续的处理和分析。
为了更好地理解词法分析的实现原理以及掌握相关算法和工具,本次词法分析实验旨在通过手动编写正则表达式、确定有限自动机的状态转移函数和实现词法分析程序来实现词法分析。
二、实验内容在本次实验中,我们需要完成以下任务:1.手动编写正则表达式;2.确定有限自动机的状态转移函数;3.实现词法分析程序。
三、实验过程1.手动编写正则表达式对于给定的源程序,我们首先需要根据其语法规则手动编写正则表达式。
例如,对于一个简单的算术表达式,其正则表达式可以如下所示:i. 数字(0-9):[0-9]+ii. 加号(+):\+iii. 减号(-):-iv. 乘号(*):\*v. 除号(/):/vi. 左括号(():\(vii. 右括号()):\)2.确定有限自动机的状态转移函数根据正则表达式,我们可以确定有限自动机的状态转移函数。
例如,对于上述算术表达式的正则表达式,其有限自动机的状态转移函数如下所示:i. 初始状态(S):判断下一个字符,如果是数字则进入数字状态,如果是左括号则进入左括号状态;ii. 数字状态(D):继续判断下一个字符,如果是数字则保持在数字状态,如果是运算符则输出数字记号,返回初始状态,如果是右括号则输出数字记号,返回初始状态;iii. 左括号状态(L):输出左括号记号,返回初始状态;iv. 右括号状态(R):输出右括号记号,返回初始状态。
3.实现词法分析程序根据以上的正则表达式和有限自动机的状态转移函数,我们可以编写一个简单的词法分析程序。
该程序的主要流程如下所示:i. 读取源程序的字符序列;ii. 根据有限自动机的状态转移函数,逐个字符进行状态转移;iii. 如果当前状态为接受状态,则输出相应的记号;iv. 继续进行状态转移,直至读取完整个源程序。
四、实验结果通过以上步骤,我们成功完成了对给定源程序的词法分析。
词法分析器实验报告_4

实验一词法分析1.实验要求(1)从源程序文件中读取有效字符和并将其转换成二元组内部表示形式输出。
(2)掌握词法分析的实现方法。
(3)实验时间4学时。
(4)实验完成后,要上交实验报告(包括源程序清单)。
2.实验内容2.1主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。
主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。
2.2词法分析过程考虑该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。
对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将常数存入数组中ci 中,并记录其在表中的位置。
注:所有识别出的单词都用二元组表示。
第一个表示单词的种别编码。
例如:关键字的t=1;标识符的t=2;常数t=3;运算符t=4;界符t=5。
第二个为该单词在各自表中的指针或内部码值(常数表和标识符表是在编译过程中建立起来的。
其i 值是根据它们在源程序中出现的顺序确定的)。
将词法分析程序设计成独立一遍扫描源程序的结构。
其主流程图如下:图1 词法分析程序流程图程序源代码:#include<stdio.h>#include<stdlib.h>#include<string.h>char *keychar[14]={"int","char","float","void","const","if", "else","do","while","scanf","printf","return","main","read"};//关键字表,全局变量(种别编码为1)char *operatchar[18]={"+","-","*","/","%","=","==",">","<","!=",">=","<=","&&","||","!","<>","++","--"};//运算符表,全局变量(种别编码为2)char *boundschar[8]={"(",")","{","}",";",",","\"","'"};//保留字表,全局变量(种别编码为3)char *markchar[40];//标示符数组(种别编码为4)int markc=0;//记录已经记录的标示符的个数char *conster[40];//常数数组(种别编码为5)int markn=0;//记录已经记录的常数的个数char tempchar[40];//临时用来存放读入的字符int already=0;//全局变量,记录从文件中读出字符的个数char Read()//从文件中读出一个字符{FILE * fcode;char temp;if((fcode=fopen("code.txt","r"))==NULL){printf("无法打开此文件!\n");exit(0);}fseek(fcode,already*sizeof(char),0);//将文件位置移动到标记位置while(!feof(fcode)){already++;temp=fgetc(fcode);if(feof(fcode)){fclose(fcode);exit(0);}fclose(fcode);return temp;}}void ShowCode()//显示文件中的代码{printf("文件中的代码为:\n\n");FILE * fcode;if((fcode=fopen("code.txt","r"))==NULL){printf("无法打开此文件!\n");exit(0);}rewind(fcode);while(!feof(fcode)){putchar(fgetc(fcode));}putchar('\n');fclose(fcode);}void FirstLetter()//处理当程序的首字符为字母时的情况{void Judge();int i=1;char tempch;tempch=Read();while (((tempch>='A'&&tempch<='Z')||(tempch>='a'&&tempch<='z')) ||tempch>='0'&&tempch<='9'){tempchar[i]=tempch;tempch=Read();i++;}if (tempch!=' '){already--;//读出的文件的位置退1}printf("读出的字符为:%s\n",tempchar);int flag=0;for (int j=0;j<14;j++){if (!(strcmp(keychar[j],tempchar)))//若该字符串为关键字{printf("该字符为关键字,二元组为:");printf("<%s,->\n\n",tempchar);flag=1;break;}}if (flag==0)//若字符串为标示符{int flag1=0;char *p;for (int k=0;k<markc;k++)//查找标示符表,是否已存在该标示符{if (!(strcmp(markchar[k],tempchar))){p=markchar[k];flag1=1;break;}if (flag1==0){markchar[markc]=(char*)malloc(strlen(tempchar));strcpy(markchar[markc],tempchar);p=markchar[markc];markc++;}printf("该字符为标示符,二元组为:");printf("<2,%d>\n\n",p);}int l0=strlen(tempchar);for (int l=0;l<l0;l++)//将临时字符数组清零{tempchar[l]='\0';}Judge();}void FirstNum()//处理当程序的首字符为数字时的情况{void Judge();char *p;int i=1;char tempch;tempch=Read();while ((tempch>='0'&&tempch<='9')||tempch=='.'){tempchar[i]=tempch;tempch=Read();i++;}if (tempch!=' '){already--;//读出的文件的位置退1}int flag=0;printf("读出的字符为:%s\n",tempchar);for (int j=0;j<markn;j++){if (!strcmp(conster[j],tempchar)){p=conster[j];flag=1;break;}if (flag==0){conster[markn]=(char*)malloc(strlen(tempchar));strcpy(conster[markn],tempchar);p=conster[markn];markn++;}printf("该字符为常数,二元组为:");printf("<3,%d>\n\n",p);int l0=strlen(tempchar);for (int l=0;l<l0;l++)//将临时字符数组清零{tempchar[l]='\0';}Judge();}void FirstBound()//处理处理当程序的首字符为界符时的情况{void Judge();int i=0;printf("读出的字符为:%s\n",tempchar);printf("该字符为界符,二元组为:");printf("<%s,->\n\n",tempchar);if(tempchar[0]=='"'){do{i++;tempchar[i]=Read();} while (tempchar[i]!='"');if (tempchar[i-1]!='\\'){char*temp1=(char*)malloc(i*sizeof(char));int n=0;for (int j=0;j<i-1;++j){*(temp1+j)=tempchar[j+1];n++;}temp1[i-1]='\0';printf("读出的字符为:%s\n",temp1);conster[markn]=(char*)malloc((i-1)*sizeof(char));strcpy(conster[markn],temp1);char*p=conster[markn];markn++;printf("该字符为常量,二元组为:<3,%d>\n\n",p);free(temp1);}printf("读出的字符为:%c\n",tempchar[i]);printf("该字符为界符,二元组为:<%c,->\n\n",tempchar[i]);}for (int j=0;j<=i;j++){tempchar[j]='\0';}Judge();}void Firstoperat()//处理处理当程序的首字符为界符时的情况{void Judge();tempchar[1]=Read();int flag=0;for (int i=0;i<18;i++){if(!strcmp(tempchar,operatchar[i])){printf("读出的字符为:%s\n",operatchar[i]);printf("该字符为运算符,二元组为:<%s,->\n\n",operatchar[i]);tempchar[1]='\0';flag=1;break;}}if (flag==0){already--;tempchar[1]='\0';for (int i=0;i<18;i++){if (!strcmp(tempchar,operatchar[i])){printf("读出的字符为:%s\n",operatchar[i]);printf("该字符为运算符,二元组为:<%s,->\n\n",operatchar[i]);flag=2;break;}if (flag==0){printf("读出的字符为:%s\n",tempchar);printf("警告!该字符无法识别!\n\n");}}tempchar[0]='\0';Judge();}void Judge() //用来判断第一个读入的字符是数字,字母或者其他字符{do{tempchar[0]=Read();}while ((tempchar[0]==' ')||(tempchar[0]=='\n'));//判断字符类型,并作出处理if ((tempchar[0]>='A'&&tempchar[0]<='Z')||(tempchar[0]>='a'&&tempchar[0]<='z')){FirstLetter();}else if (tempchar[0]>='0'&&tempchar[0]<='9'){FirstNum();}elseif(tempchar[0]=='('||tempchar[0]==')'||tempchar[0]=='{'||tempchar[0]=='}'||tempchar[0]==';'||tempchar[0]==',' ||tempchar[0]=='"'||tempchar[0]=='\''){FirstBound();}else{Firstoperat();}}void main(){ShowCode();Judge();}实验心得:通过此次上机实验,是我掌握了词法分析器的实现过程,以前只是在课堂上学习词法分析器的理论,通过实践,也真正了解到了它的原理,为以后的语法分析打下基础,同时也熟悉了C语言,夯实了C语言的功底!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《词法分析》实验报告
目录
目录错误!未定义书签。
1 实验目的错误!未定义书签。
2 实验内容错误!未定义书签。
TINY计算机语言描述错误!未定义书签。
实验要求错误!未定义书签。
3 此法分析器的程序实现错误!未定义书签。
状态转换图错误!未定义书签。
程序源码错误!未定义书签。
实验运行效果截图错误!未定义书签。
4 实验体会错误!未定义书签。
实验目的
1、学会针对DFA转换图实现相应的高级语言源程序。
2、深刻领会状态转换图的含义,逐步理解有限自动机。
3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。
实验内容
TINY计算机语言描述
TINY计算机语言的编译程序的词法分析部分实现。
从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。
为了简化程序的编写,有具体的要求如下:
1、数仅仅是整数。
2、空白符仅仅是空格、回车符、制表符。
3、代码是自由格式。
4、注释应放在花括号之内,并且不允许嵌套
TINY语言的单词
要求实现编译器的以下功能
1、按规则拼单词,并转换成二元式形式
2、删除注释行
3、删除空白符(空格、回车符、制表符)
4、列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式
5、发现并定位错误
词法分析进行具体的要求
1、记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。
2、词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。
这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。
3、标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。
此法分析器的程序实现
状态转换图
图1 TINY语言的确定有限自动机(DFA)
程序源码
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
#include<iomanip>
class CA
{
public:
void getToken(); .:/.../...格式
cout<<"请输入源程序代码.cpp 文件的绝对路径:"<<endl;
cin>>filename;
ifstream infile(filename,ios::in);
if(!infile)
{
cerr<<"open error!"<<endl;
abort();
}
char ch;
int count1=1;count2=0;
cout<<"第"<<count1<<" 行";
while(ch))
{
preDo(ch);
cout<<ch; //逐行打印出源程序
if(ch=='\n')
{
count1++;
cout<<"第"<<count1<<" 行";
}
}
buffer1[count2+1]='\0';
cout<<endl;
//对buffer1中的字符进行扫描
getToken();
();
cout<<endl;
cout<<"符号表:";
for (int i=0;i<m;i++)
cout<<ID[i]<<" ";
cout<<endl;
cout<<"数字表:";
for (int j=0;j<n;j++)
cout<<Cons[j]<<" ";
cout<<endl;
}
void CA::preDo(char c)
{
char *p=buffer1;
buffer1[0]='#'; //赋#给扫描缓冲区的第一个元素
count2++;
*(p+count2)=c;
if(buffer1[count2-1]=='{') //删除注释
{
if(c=='{') cout<<"注释不允许嵌套! "; //注释不允许嵌套
if(c!='}') count2--;
else count2=count2-2;
}
else if(buffer1[count2-1]==' '&&c==' ') count2--; //若干相继的空白符结合成一个if(c=='\r') count2--;
if(c=='\t') count2--;
}
void CA::getToken()
{
int n=1;
cout<<"第1行: ";
for(int i=1;i<strlen(buffer1);i++)
{
if(buffer1[i]=='\n'){n++;cout<<"\n第"<<n<<"行:" ;}
else if(isLetter(buffer1[i]))
{
string tok = "";
tok +=buffer1[i];
while(isLetter(buffer1[++i]))
tok +=buffer1[i];
int r=Search(K,(),8);
i--;
if(r!=-1)cout<<"(关键字"<<r+1<<","<<tok<<") "; //关键字编码
else
{
cout<<"(标识符,"<<tok<<") "; //标识符编码
r = InsertID((char *)());
}
}
else if(isDigit(buffer1[i]))
{
string tok = "";
tok +=buffer1[i];
while(isDigit(buffer1[++i]))
{
tok +=buffer1[i];
}
int y = InsertConst((char *)());
cout<<"(数字,"<<tok<<") ";
i--; //数字编码
}
else if (buffer1[i]==' ') {}
else
{
string tok = "";
tok +=buffer1[i];
int q=Search(K,(),18);
if(q!=-1){ cout<<"(特殊符号,"<<tok<<") "; }
else
cout<<"非法符号! ";
}
}
}
/***********************main函数*******************************/ int main()
{
CA ca;
();
cout<<endl;
return 0;
}
实验运行效果截图
实验体会
本次实验是《编译技术》的第一次实验,按理说也应该是最简单的一次实验验,但是在具体的实现过程中还是遇到了这样或那样的问题,比如对原输入串进行分析的预处理是在注释的嵌套判断上出现了问题,调试了几次才发现是出现注释时计数值本来应该减2结果减了1。
类似的错误还有,但好在最后都解决了。
除了提升了自己的动手能力外本次实验最大的收获应该是对词法分析器的运行机制有了更深入的理解了,再画状态转换的过程中也激发了我的一些关于那些复杂的语言(如c++)的词法分析器是怎样书写的联想,希望在今后的学习实践中能有更深入的学习。
最后感谢老师的悉心指导,谢谢老师!。