(完整word版)编译原理词法分析器实验报告
- 格式:doc
- 大小:201.02 KB
- 文档页数:13
编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的: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)关键字:"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"(2)运算符:"+","-","*","/","="(3)界符:"{","}","[","]",";",",",".","(",")",":"(4)其他标记如字符串,表示以字母开头的标识符(5)空格、回车、换行符跳过(6)运行结果在屏幕上以如下格式显示:1 $无符号整数begin $关键字if $关键字+ $运算符;$界符a $普通标识符//“$“为美元符号,不是大写字母S测试功能时,可以多次设置包含不同字符,关键字的待解析文件,但要保证输入文件和后缀名时准确无误,仔细察看运行结果,检测该分析器的分析结果是否正确四、源代码:#include <iostream>#include<string>using namespace std;#define MAX 22char ch =' ';string key[15]={"begin","end","if","then","else","while","write","read","do", "call","const","char","until","procedure","repeat"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++) {if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void analyse(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF) {arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)) {if((ch<='Z')&&(ch>='A')) ch=ch+32;arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}else cout<<arr<<"\t$普通标识符"<<endl;}else if(IsDigit(ch)){while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t$无符号实数"<<endl;}else switch(ch){case'+':case'-' :case'*' :case'=' :case'/' :cout<<ch<<"\t$运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t$界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t$运算符"<<endl;else {cout<<"="<<"\t$运算符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t$运算符"<<endl;if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;else {cout<<">"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;else{cout<<"<"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t$无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n********************分析如下*********************"<<endl;analyse(fpin);fclose(fpin);cout<<endl;cout<<"按任意键结束"<<endl;int a;cin>>a;}运行结果截图:输入:输出:生成的单词表目标文件:。
词法分析器实验报告一、实验目的选择一种编程语言实现简单的词法分析程序,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn 用来存放单词符号的种别码。
编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。
本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。
二、实验环境本次实验使用的编程语言为_____,开发工具为_____。
三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。
单词符号通常包括关键字、标识符、常量、运算符和界符等。
词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。
在本次实验中,我们采用了状态转换图法。
状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。
通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。
四、实验步骤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.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
词法分析器的实验报告词法分析器的实验报告引言:词法分析器是编译原理中的重要组成部分,它负责将源代码中的字符序列转换为有意义的词法单元,为后续的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,并对其进行测试和评估。
实验设计:1. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。
例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。
2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。
有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。
3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。
代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。
实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。
- 运算符:包括+、-、*、/等。
- 分隔符:包括括号()和逗号,。
- 标识符:以字母开头,由字母和数字组成的字符串。
2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。
该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。
- 数字状态:用于识别和输出数字。
- 运算符状态:用于识别和输出运算符。
- 分隔符状态:用于识别和输出分隔符。
- 标识符状态:用于识别和输出标识符。
3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。
代码主要包括以下功能:- 读取源代码文件。
- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。
- 识别和输出词法单元。
实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。
编译原理实验(一)——词法分析器一.实验描述运行环境: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置为空白字符。
(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。
编译原理实验报告一、实验目的本次实验的目的是了解编译原理的基本知识,并运用所学知识实现一个简单的词法分析器。
二、实验内容1.设计一个词法分析器,能够识别并输出源程序中的关键字、标识符、常数和运算符等。
2.设计并实现一个词法分析器的算法。
3.对编写的词法分析器进行测试。
三、实验过程1.设计词法分析器的算法在设计词法分析器的时候,需要先了解源程序的基本构成,了解关键字、标识符、常数和运算符等的特点,以及它们在源程序中的表示形式。
然后,根据这些特点,设计一个适合的算法来进行词法分析。
2.实现词法分析器根据设计好的算法,在编程语言中实现词法分析器。
在实现过程中,需要根据不同的词法单元,设计相应的正则表达式来进行匹配和识别。
3.测试词法分析器编写几个简单的测试用例,对词法分析器进行测试。
检查输出结果是否正确,并根据实际情况对词法分析器进行调试和优化。
四、实验结果经过测试,词法分析器能够正确识别并输出源程序中的关键字、标识符、常数和运算符等。
测试用例的输出结果与预期结果一致。
五、实验总结通过本次实验,我学习了编译原理的基本知识,掌握了词法分析器的设计和实现方法。
在实验过程中,我遇到了一些困难和问题,但通过仔细思考和查阅文献资料,最终成功地完成了实验任务。
这次实验不仅帮助我巩固了所学知识,还提高了我的编程能力和解决问题的能力。
通过实践,我深刻体会到了编译原理在软件开发中的重要性和作用,并对将来的学习和工作有了更好的规划和方向。
通过本次实验,我对编译原理的相关知识有了更深入的理解和掌握,对词法分析器的设计和实现方法有了更加清晰的认识。
同时,我还学会了如何进行实验报告的撰写,提高了我的文档写作能力。
通过本次实验,我不仅实现了实验的目标,还提高了自己的综合素质和能力。
《编译原理》课程实验报告题目词法分析专业计算机指导教师签名华东理工大学信息学院计算机系2013年4月10日一.实验序号:《编译原理》第一次实验二.实验题目:词法分析三.实验日期:2013.3.27-2013.4.10四.实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五.实验要求●修改词法:1)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字母或小写字母或数字或下划线”。
把while ((isalpha(buffer))||(isdigit(buffer)))改成while ((isalpha(buffer))||(isdigit(buffer))||buffer==’_’)2)将<条件>中的表示相等关系的单词“=”改为“= =”char *relation[6]={"<","<=","=",">",">=","<>"};把其中的=改成==即可3)将原来无小数的数改为可以有小数的数把while (isdigit(buffer))改成while (isdigit(buffer)||buffer==’.’)●用C语言开发词法分析程序。
读入用PL/0语言编写的测试用例源程序,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
六.实验步骤1)根据修改词法后的PL/0语言编写测试用例源程序。
2)用C语言编写词法分析程序。
读入PL/0语言的测试用例源程序,进行词法分析,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
3)设立断点,单步运行词法分析程序,依次单个输出单词。
分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
七.实验结果(测试用例源程序,运行结果部分截图,词法分析函数主要部分源程序PL0程序:const a=6,b=81;var x,y;procEdure p;procedure q;x:=2;beginx:=1;write(x);end;begincall p;end.C程序:#include <stdio.h>#include <ctype.h>#include <malloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char*key[19]={"auto","break","case","char","const","continue","default","do"," double","else","enum","extern","float","for","goto","if","int","long","register"};char *border[6]={",",";","{","}","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[11]={"0","1","2","3","4","5","6","7","8","9","."};char *label[20];int labelnum=0;int search(char searchchar[],int wordtype){ int i=0;switch (wordtype) {case 1:for (i=0;i<=18;i++){ if (strcmp(key[i],searchchar)==0){return(1);}}return(0);break;case 2:{for (i=0;i<=5;i++){ if (strcmp(border[i],searchchar)==0)return(i+1);} return(0);}break;case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){ return(1);}}return(0);}break;case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){ return(1);}}return(0);}break;case 5:{for (i=0;i<=10;i++){ if (strcmp(consts[i],searchchar)==0){return;}}return(0);}break;}}char alphaprocess(char buffer){ int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer;buffer=fgetc(fp);}alphatp[i+1]='\0';atype=search(alphatp,1);if(atype==1){printf("%s \t 保留字\n",alphatp);}//结束if(atype==0){printf("%s \t 标示符\n",alphatp);}return(buffer);}char digitprocess(char buffer){ int i=-1;char digittp[20];int dtype;while (isdigit(buffer)){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);if(dtype==1)printf("%s \t 数字\t %s\n",digittp,digittp);return(buffer);}char otherprocess(char buffer){ int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';otype=search(othertp,3);if (otype==1){ printf("%s \t 运算符\n",othertp);buffer=fgetc(fp);goto out;}otype=search(othertp,4);if (otype==1){ buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';otypetp=search(othertp,4);if (otypetp==1){ printf("%s \t 运算符\n",othertp);goto out;}elseothertp[1]='\0';printf("%s \t 运算符\n",othertp);goto out;}if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= \t 运算符\n");buffer=fgetc(fp);goto out;}else{ if (otype=search(othertp,2)){ printf("%s \t 界符\n",othertp);buffer=fgetc(fp);goto out;}}if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer);buffer=fgetc(fp);out: return(buffer);}void main(){if ((fp=fopen("example.txt","r"))==NULL)printf("error");else{cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);elsecbuffer=otherprocess(cbuffer);}printf("over\n");getchar();}}八.实验体会(词法分析程序修改的地方,解决问题的方法、心得体会等)通过本次试验,了解了词法分析的主要步骤,就是把标识符,保留字区分,并且能识别出空格,并把数据能从文件中读出来,主要识别标识符和保留字,主要通过比较参照一个事先建好的数组,里面包含了所有的保留字,不在其中的便是标识符。
北华航天工业学院《编译原理》课程实验报告课程实验题目:词法分析器实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:B08512作者学号:18作者姓名:李桂丁指导教师姓名:李建义完成时间:2010年3月26日一、实验目的了解词法分析程序的两种设计方法:1.根据状态转换图直接编程的方式;2.利用DFA 编写通用的词法分析程序。
二、实验内容及要求1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。
在此,词法分析程序作为单独的一遍,如下图所示。
具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。
将错误信息输出到屏幕上。
(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。
标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。
常量表结构:常量名,常量值2.能对任何S语言源程序进行分析在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。
3.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。
4. 本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。
2:源程序文件结束而注释未结束。
注释格式为:/* …… */三、实验程序设计说明1.实验方案设计2.程序源代码#include<stdio.h>#include<stdlib.h>#include<string>#include<iostream>using namespace std;stringkeywords[20]={"include","void","main","int","char","float","double","if","else","then","break","c ontinue","for","do","while","printf","scanf","begin","end","return"};char aa[99999]=" ";string id[10000];int pp=0;string nu[10000];int qq=0;void initscanner() //程序初始化:输入并打开源程序文件和目标程序文件,初始化保留字表{int i=0;FILE *fp;if((fp=fopen("a.txt","r"))==NULL){printf("Open error!");exit(0);}char ch=fgetc(fp);while(ch!=EOF){aa[i]=ch;i++;ch=fgetc(fp);}fclose(fp);}int decide1(char a) //判断是否是字母{if((a>='a'&&a<='z')||(a>='A'&&a<='Z'))return 1;else return 0;}int decide2(char a) //判断是否是数字{if(a>='0'&&a<='9')return 1;else return 0;}int isalpha(int st) //识别保留字和标识符{char wordbuf[20]=" ";int n=0;for( ; ; ){wordbuf[n]=aa[st];st++;n++;if((decide2(aa[st])==1)||(decide1(aa[st])==1)||(aa[st]=='_')) wordbuf[n]=aa[st];else break;}int flag=0;for(int k=0;k<20;k++){if(strcmp(keywords[k].c_str(),wordbuf)==0) flag=1;}if(flag==0){int flagg=-1;for(int t=0;t<pp;t++){if(strcmp(id[t].c_str(),wordbuf)==0){flagg=t;}}if(flagg!=-1) printf(" (id,%d) ",flagg);else{id[pp]=wordbuf;printf(" (id,%d) ",pp);pp++;}}else{printf(" (");for(int i=0;i<n;i++){printf("%c",wordbuf[i]);}printf(",-) ");}return st;}int isnumber(int st) //识别整数,如有精力,可加入识别实数部分工功能{char numbuf[20]=" ";int n=0;int k=0;int flag=0;for( ; ; ){numbuf[n]=aa[st];st++;n++;if(decide2(aa[st])==1){numbuf[n]=aa[st];}else if((k==0)&&(aa[st]=='.'))numbuf[n]=aa[st];k++;}else if(decide1(aa[st])==1){numbuf[n]=aa[st];flag=1;continue;}else break;}if(flag==0){int flagg=-1;for(int t=0;t<qq;t++)if(strcmp(nu[t].c_str(),numbuf)==0)flagg=t;if(flagg!=-1) printf(" (nu,%d) ",flagg);else{nu[qq]=numbuf;printf(" (nu,%d) ",qq);qq++;}}else{printf(" (");for(int i=0;i<n;i++) printf("%c",numbuf[i]);printf(",error digital!) ");}return st;}int isanotation(int st) //处理除号/和注释{char tabuf[9999]=" ";int n=0;st++;if(aa[st]=='/'){printf(" (//,-) ");st++;while(aa[st]!=10)tabuf[n]=aa[st];st++;n++;}printf(" (");for(int i=0;i<n;i++)printf("%c",tabuf[i]);printf(",unuseful things!) ");}else if(aa[st]=='*'){printf(" (/*,-) ");st++;int stt=st+1;while(1){if(aa[st]=='*'&&aa[st+1]=='/') break;tabuf[n]=aa[st];st++;n++;if(aa[st+1]==NULL){printf("(/* error!!\n)");return st+1;}} printf(" (");for(int i=0;i<n;i++)printf("%c",tabuf[i]);printf(",unuseful things!) ");printf(" (*/,-) ");st=st+2;}else if(aa[st]=='='){st++;printf(" (/*,-) ");}else printf(" (/,-) ");return st;}int isother(int st) //函数识别其他特殊字符{switch(aa[st]){case '=': st++;if(aa[st]=='='){st++;printf(" (rlop,==) ");}else printf(" (rlop,=) ");break;case '+': st++;if(aa[st]=='='){st++;printf(" (+=,-) ");}else if(aa[st]=='+'){st++;printf(" (++,-) ");}else printf(" (+,-) ");break;case '-': st++;if(aa[st]=='='){st++;printf(" (-=,-) ");}else if(aa[st]=='-'){st++;printf(" (--,-) ");}else printf(" (-,-) ");break;case '*': st++;if(aa[st]=='='){st++;printf(" (*=,-) ");}else printf(" (*,-) ");break;case '>': st++;if(aa[st]=='='){st++;printf(" (rlop,>=) ");}else printf(" (rlop,>) ");break;case '<': st++;if(aa[st]=='='){st++;printf(" (rlop,<=) ");}else printf(" (rlop,<) ");break;case '%': st++;if(aa[st]=='='){st++;printf(" (\%=,-) ");}else printf(" (\%,-) ");break;case '!': st++;if(aa[st]=='='){st++;printf(" (!=,-) ");}else printf(" (!,wrong thing!) ");break;case '&': st++;if(aa[st]=='&'){st++;printf(" (&&,-) ");}else printf(" (&,worng word!) ");break;case '|': st++;if(aa[st]=='|'){st++;printf(" (||,-) ");}else printf(" (|,worng word!) ");break;case '{': st++;printf(" ({,-) ");break;case '}': st++;printf(" (},-) ");break;case '(': st++;printf(" ((,-) ");break;case ')': st++;printf(" (),-) ");break;case '[': st++;printf(" ([,-) ");break;case ']': st++;printf(" (],-) ");break;case ':': st++;printf(" (:,-) ");break;case '#': st++;printf(" (#,-) ");break;case ';': st++;printf(" (;,-) ");break;case '.': st++;printf(" (.,-) ");break;case ',': st++;printf(" (,,-) ");break;case ' ': st++;break;case ' ': st++;break;case 10: st++;printf("\n");break;case 34: st++;printf(" (\",-) ");break;case 39: st++;printf(" (',-) ");break;default: printf(" (%c,worng thing) ",aa[st]);st++;}return st;}int lexscan(int st) //根据读入的单词的第一个字符确定调用不同的单词识别函数{if(decide1(aa[st])==1)st=isalpha(st);else if(decide2(aa[st])==1)st=isnumber(st);else if(aa[st]=='/')st=isanotation(st);else st=isother(st);return st;}void scanner() //若文件未结束,反复调用lexscan函数识别单词{int i=0;while(aa[i]!=NULL)i=lexscan(i);}void print(){cout<<endl<<" This is id card!! "<<endl;for(int i=0;i<pp;i++)cout<<i<<" "<<id[i]<<endl;cout<<" This is nu card!! "<<endl;for(int j=0;j<qq;j++)cout<<j<<" "<<nu[j]<<endl;}void main(){initscanner();scanner();print();}3.程序的执行结果图 1 程序输入文件内容图 2 输出结果4.实验程序的优点和特色本程序特色:出错处理能力强,任何非法字符输入,将会报错。