C_minus语言词法分析器的设计
C语言词法分析器设计与实现
> C语言词法分析器设计与实现C语言词法分析器的设计与实现一.实验目的1.强化对系统软件综合工程实现能力、规划能力的训练;2.加强对词法分析原理、方法和基本实现技术的理解;二.实验内容用C语言(或 C++ )作为宿主语言完成:其中具体要求:1.使用DFA实现词法分析器的设计;2.实现对C源程序中注释的过滤;3.利用两对半缓冲区从文件中逐一读取单词;4.词法分析结果属性字流存放在独立文件中;5.统计源程序每行单词的个数和整个源文件单词个数;6.具有报告词法错误和出错位置(源程序行号和该行字符)的功能;7.屏幕输出属性字流,每次显示10行,按ESC可中途退出,每行有统计信息,最后有词法分析的全部信息,包括各种属性单词的个数。
三.实验验收与评分要求1.编写C语言词法分析器的源程序并调试通过;2.通过测试程序的验收 (测试程序名称:Test-Lexcial);3.提交简明扼要的书面实验报告。
内容包括:FA设计;源程序主要函数功能;主要数据结构设计。
四. 验收测试用例1. 测试用例一:统一验收测试用例;#include<stdio.h>#include<string.h>char buf[100],str[15];int countdef=0;FILE *fpmiddle;struct define{char with[30];char des[30];char filename[15];}def[30];char* getFileName(){int i=0,k=0;for(i=0;buf[i]!='<'&&i<30&&buf[i]!='\0';i++);i++;while(buf[i]!='>'&&i<30&&buf[i]!='\0')str[k++]=buf[i++];str[k]='\0';puts(str);return str;}long readline(FILE *fpt){if(fgets(buf,100,fpt)==NULL){puts(buf);printf("readline error or reach file end!\n");return 0;}puts(buf);return (long)(strlen(buf)+1);}void writeline(){fprintf(fpmiddle,"%s",buf);}void processDefine(char *filename){int i=8,j=0;while((def[countdef].des[i-8]=buf[i])!=' ') i++;def[countdef].des[i-8]='\0';while((def[countdef].with[j]=buf[i])!='\0'){i++;j++;}def[countdef].with[j-1]='\0';strcpy(def[countdef].filename,filename);countdef++;}long comment(FILE *fpt){char prechar=buf[0],ch='*';int i=0,j=0;for(i=0;buf[i]!='\0'&&!(buf[i]=='/'&&buf[i+1]=='*');i++) ;j=i;buf[i]='\0';if(i==strlen(buf)) return 0L;do{prechar=ch;if((ch=fgetc(fpt))==EOF){printf(" in comment, end");exit(0);}i++;}while(!(prechar=='*'&&ch=='/'));return (long)(i-j+1);}isin(char *p){int i=0,j=0,temp=0;while(temp!=strlen(buf)){while(buf[i]!='\0'&&buf[i]!=p[0])i++;temp=i;while(buf[i]==p[j]&&p[j]!='\0'&&buf[i]!='\0'){i++;j++;}if((i-temp)==strlen(p)) return temp;i=temp+1;j=0;}return -1;}void includeAndDefine(FILE *fpt){void add(char*);void replace(char*);while(readline(fpt)){if(isin("#include")>=0)add(getFileName());else if(isin("#define")>=0)processDefine(str);else{fseek(fpt,comment(fpt),1);replace(str);writeline();}}}void add(char *filename){void replace(char*);FILE *fpp;if((fpp=fopen(filename,"r"))==NULL){printf("file %s not found or open error!",filename);exit(0);}fseek(fpp,-readline(fpp),1);if(isin("#include")<0&&isin("#define")<0)while(readline(fpp)){fseek(fpp,comment(fpp),1);replace(filename);writeline();}elseincludeAndDefine(fpp);fclose(fpp);}void replace(char *filename){int i=0,start=0;for(i=0;i<countdef;i++)if(!strcmp(def[i].filename,filename))break;if(i>=countdef||(start=isin(def[i].des))==-1) return;else{int lenOfWith=strlen(def[i].with);int lenOfDes=strlen(def[i].des);if(lenOfDes>=lenOfWith){int k,j;for(k=start; k<start+lenOfWith; k++)buf[k]=def[i].with[k-start];for(j=(start+lenOfWith); j<start+lenOfDes; j++) buf[j]=' ';}else{int offset=lenOfWith-lenOfDes;int k,j;for(k=offset+strlen(buf);k>start;k--)buf[k]=buf[k-offset];for(j=start;j<start+lenOfWith;j++)buf[j]=def[i].with[j-start];}}}2. 自己编写的C语言词法分析器源码。
编译原理课程设计—词法分析器
编译原理课程设计(一)——词法分析器1、题目编写程序实现一个简易的词法分析器。
2、实验目的对一段程序代码进行词法分析,将程序段中的关键字、标识符、常数、运算符、界符按照一定的种别编码分析出来。
3、环境及工具操作系统:windows XP ;使用工具:Microsoft Visual C++ 6.0; 编程语言:C 语言;4、分析程序输入:从文件中读入程序段;程序输出:由单词种别和单词符号的属性值组成的二元式;单词种别通常使用整数编码,编码方式可以有多种,在设计词法分析器之前应确定一种程序处理起来较方便的编码方式。
当一个种别中含有多个单词符号时,在分析出其属于哪个种别的时候应同时给出其单词符号属性,本程序为方便起见,采用单词符号本身来作为其属性,以标识同种别种的不同单词符号。
标识符及关键字的识别:字母开头的字母和数字组成的串是多数编程语言的标识符,所以我们的简易词法分析器中,将标识符定义为这种字母数字串。
当第一个字母为字母且紧接着的字符为数字或字母时,应将其串接在一起为一个单词,直到紧跟着的不在是字母数字时。
由于关键字通常为一个单词,则这样得到的串可能是标识符也可能是关键字,又因为一种语言的关键字通常是有限个,则我们可以构造一个存放所有关键字的表,查询关键字表,可以判断得到的串是否为关键字。
界符和运算符的识别:它们多为当个字符,建立两个分别存放界符合运算符的表,读取字符后,进行查表便可以得出它们的类型。
为方便词法分析器的设计,可以使用状态转换图,根据一种特定的编程语言先设计出其状态转换图才能更好将其用代码实现。
典型状态转换图结构如下:(a)有不含回路含分支的状态节点:对应if …else if …else …语句;(b)有含回路的状态节点:对应while …if …语句。
(b )5、状态转换图6、程序框架描述程序中编写了以下函数,各个函数实现的作用如下:1. GetChar():将下一输入的字符读入到全局变量ch中,搜素指示器前移一个字符的位置。
编译原理课程设计_词法分析器设计
编译方法课程设计词法分析器设计学院:计算机与信息工程学院专业:软件工程学号:姓名:指导教师:职称:设计报告日期:二О一二年十二月目录1设计概述 (2)1.1设计题目 (2)1.2 设计目的 (3)1.3 设计任务内容: (3)1.4 设计时间 (3)2 设计环境与工具 (3)3设计要求 (3)4分析与概要设计 (4)5算法描述与框图 (4)6 源程序清单 (6)7 软件测试 (10)7.1 设计的测试题目 (10)7.2测试结果截图 (10)8 总结 (10)8 参考文献 (11)1设计概述1.1设计题目词法分析器的设计与实现。
1.2 设计目的词法分析是编译程序第一个阶段的工作,它的任务是对输入的字符串形式的源程序进行扫描,在扫描的同时,根据源语言的词法规则识别具有独立意义的单词。
本设计是C++高级程序语言,数据结构和变异原理中词法分析原理等知识的综合运用。
掌握生成词法分析器的方法,加深对词法分析原理的理解,掌握设计,编制并调试词法分析程序的思想和方法。
1.3 设计任务内容:1、格式输入:将C++语言的源代码从文本文档中读入。
处理:对输入框中的代码进行词法分析,分离出关键字、标示符、数值、运算符和界符。
输出:在文本文档中输出每个单词对应的编码和值。
2、编译对象声明和其他标记赋值语句分支结构语句循环语句1.4 设计时间2012年12月23日至2012年12月28日2 设计环境与工具Windows7环境下使用 C++语言。
3设计要求1、使用任何一种编程语言编制一个词法分析程序。
2、该程序能够识别的单词有5类:(1)关键字:"long", "float", "static", "char", "short", "switch", "int", "const", "if", "then", "else", "for", "while", "break"。
(完整版)词法分析器(c语言实现)
词法分析c实现一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(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)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();main(){p=0;printf("\n please input a string(end with '#'):/n");do{scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");getch();exit(0);default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);getch();}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')) { while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5-1所示:。
编译原理课程设计C编译器词法分析与语法分析的实现
编译原理课程设计报告课落款称: C-编译器词法分析与语法分析的实现提交文档学生姓名:黄臻旸提交文档学生学号: 1043041227 同组成员名单:无指导教师姓名:金军指导教师评阅成绩:指导教师评阅意见:..提交报告时刻:2021年 6 月 5 日编译原理课程设计报告 (1)一、课程设计目标 (3)二、分析与设计 (3)2.一、说明所用的方式: (3)2.二、系统总图: (3)2.2.一、scanner部份: (3)2.2.二、parse部份: (5)2.2.3、代码设计说明 (7)3、程序代码实现 (10)3.一、获取输入部份(在main.c中): (10)3.二、词法分析部份(在scan.c中): (10)3.3、语法分析部份(在parse.c中): (15)3.4、输出与结点的成立(在util.c中) (29)3.五、TokenType、treeNode与结点类型的声明(在globals.h中) (35)4、测试结果 (36)五、总结 (40)5.一、收成 (43)5.二、不足 (43)一、课程设计目标本次实验,本C- 编译器要紧设计而且实现了C- 编译器的词法分析功能与语法分析功能。
二、分析与设计2.一、说明所用的方式:各部份的实现方式(scanner:手工实现、Lex;parser:递归下降、LL(1)、LR(0)、SLR(1)、2.二、系统总图:2.2.一、scanner部份:2.2.1.一、实验原理:扫描程序的任务是从源代码中读取字符并形成由编译器的以后部份(一般是分析程序)处置的逻辑单元。
由扫描程序生成的逻辑单元称作记号(token),将字符组合成记号与在一个英语句子中将字母将字母组成单词并确信单次的含义很相像。
在此程序中,我将记号分成了以下类型:typedef enum {ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,PLUS,MINUS,TIMES,OVER,L T,LET,BT,BET,EQ,NEQ,// = + - * / < <= > >= == !=LPAREN_1,RP AREN_1,SEMI,COM,LPAREN_2,RP AREN_2,LPAREN_3,RP AREN_3,LIN,RIN// { } ; , [ ] ( ) /*} TokenType;其中,关键字有:else、if、int、return、void、while;专用符号有:+、-、*、/、<、<=、>、>=、==、~=、=、;、,、(、)、[、]、{、}、/*、*/其他标记是ID、NUM,通过以下正那么表达式概念:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9小写大写字母是有区别的。
编译原理词法分析器语法分析课程设计范本
《编译原理词法分析器语法分析课程设计-《编译原理》课程设计院系信息科学与技术学院专业软件工程年级级学号 2723姓名林苾湲西南交通大学信息科学与技术学院12月目录课程设计1 词法分析器 (2)设计题目 (2)设计内容 (2)设计目的 (2)设计环境 (2)需求分析 (2)概要设计 (2)详细设计 (4)编程调试 (5)测试 (11)结束语 (13)课程设计2 赋值语句的解释程序设计 (14)设计题目 (14)设计内容 (14)设计目的 (14)设计环境 (14)需求分析 (15)概要设计 (16)详细设计 (16)编程调试 (24)测试 (24)结束语 (25)课程设计一词法分析器设计一、设计题目手工设计c语言的词法分析器(能够是c语言的子集)。
二、设计内容处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。
三、设计目的了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
四、设计环境该课程设计包括的硬件和软件条件如下:.硬件(1)Intel Core Duo CPU P8700(2)内存4G.软件(1)Window 7 32位操作系统(2)Microsoft Visual Studio c#开发平台.编程语言C#语言五、需求分析.源程序的预处理:源程序中,存在许多编辑用的符号,她们对程序逻辑功能无任何影响。
例如:回车,换行,多余空白符,注释行等。
在词法分析之前,首先要先剔除掉这些符号,使得词法分析更为简单。
.单词符号的识别并判断单词的合法性:将每个单词符号进行不同类别的划分。
单词符号能够划分成5中。
(1)标识符:用户自己定义的名字,常量名,变量名和过程名。
(2)常数:各种类型的常数。
(3) 保留字(关键字):如if、else、while、int、float 等。
(4) 运算符:如+、-、*、<、>、=等。
词法分析程序的设计与实现
词法分析程序的设计与实现方法1:采用C作为实现语言,手工编制一.文法及状态转换图1.语言说明:C语言有以下记号及单词:(1)标识符:以字母开头的、后跟字母或数字组成的符号串。
(2)关键字:标识符集合的子集,该语言定义的关键字有32个,即auto,break,case,char,const,continue,default,do,double,else,enum, extern,float,for,goto,if,int,long,register,return,short,signed,static, sizeof,struct,switch,typedef ,union,unsigned ,void, volatile和while。
(3)无符号数:即常数。
(4)关系运算符:<,<=,==,>,>=,!=。
(5)逻辑运算符:&&、||、!。
(6)赋值号:=。
(7)标点符号:+、++、-、--、*、:、;、(、)、?、/、%、#、&、|、“”、,、.、{}、[]、_、^等(8)注释标记:以“/*”开始,以“*/”结束。
(9)单词符号间的分隔符:空格。
2.记号的正规文法:仅给出各种单词符号的文法产生式(1)标识符的文法id->letter ridrid->ε|letter rid|digit rid(2)无符号整数的文法digits->digit remainderremainder->ε|digit remainder(3)无符号数的文法num->digit num1num1->digit num1|. num2|E num4|εnum2->digit num3num3->digit num3|E num4|εnum4->+digits|-digits|digit num5digits->digit num5num5->digit num5|ε(4)关系运算符的文法relop-> <|<=|==|>|>=|!=(5)赋值号的文法assign_op->=(6)标点符号的文法special_symbol->+|-|*|%|#|^|(|)|{|}|[|]|:|;|”|?|/|,|.& (7)逻辑运算符的文法logic->&&| || | !(8)注释头符号的文法note->/starstar->*3.状态转换图其中,状态0是初始状态,若此时读入的符号是字母,则转换到状态1,进入标识符识别过程;如果读入的是数字,则转换到状态2,进入无符号数识别过程;……;若读入的符号是/,转换到状态11,再读入下一个符号,如果读入的符号是*,则转换到状态12,进入注释处理状态;如果在状态0读入的符号不是语言所定义的单词符号的开始字符,则转换到状态13,进入错误处理状态。
编译原理 设计c语言的词法分析器
编译原理课程设计报告题目:学院:教师::学号:班级:评分:签字:编译原理课程设计一:设计c语言的词法分析器一、实验目的了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程,加深对词法原理的理解。
二、实验要求了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
三、实验设计3.1.单词分类及表示3.1.1 C语言的子集分类(1)标识符:以字母开头的字母数字串(2)整数或浮点型。
(3)保留字:for,while,do,else,if,static,int,sizeof,break,continue(4)运算符:+,-,*,/,%,>,<,=,!=,==,<=,>=,!,&,&&,||;(5)界符:"(",")",",",":",";","{","}"3.1.2单词二元组(单词分类号、单词自身值)3.2 词法分析器的设计3.2.1算法设计3.2.1.1概要设计从文件中逐个读取字符,只要这五大类的状态序列则继续读取,否则回退字符,在对应类别进行查找,输出单元二次组至另一文件夹。
3.2.1.2状态图设计开始打开txt文件读取c语言代码扫描是否读取到相应字符常数?标识符保留字运算符记录标号结束界符?YY Y3.2.2输入输出设计输入:通过文件指针从文件中一个一个读取字符输出:输出单词二元组至文件。
格式为(种别码,值)3.2.3主要函数void Getchar(FILE *fp ) //读入一个字符void GetBC(FILE *fp)//读入一个非空字符void contacat()//连接字符int letter()//判断是否为字母int digit()//判断是否为字母void retract(FILE *fp,char *c)//回退int reserve (char **k)//处理保留字int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置void Tofile(int num, int val, identifier *id, constnumber *con, FILE *fw)//写到文件void WordAnalyze(char **k,char *c, char **CODE, identifier *id, constnumber *con, FILE *fp, FILE *fw)//词法分析函数四、结果测试文件输入int main(){int a=1,b=3;if(a>1)b=b-2;}输出结果:结论:程序输出结果与期望输出结果相符。
词法分析器实验报告
实验报告【实验过程记录(源程序、测试用例、测试结果及心得体会等)】1、程序源代码:#include "fstream.h"#include "iostream.h"#include "string.h"#include "ctype.h"char ch ; // 存放当前的输入字符int lineno = 1; // 记录当前的行号void main()//主函数{void Reserve(ifstream&);ifstream fin("input.txt",ios::nocreate); //用ifstream的对象fin打开input文件,文件不存在时,不创建if (fin.fail()) cout << "找不到文件" << endl;Reserve(fin);fin.close();//fout.close();// ferr.close();}int judge(char *string) // 判断是否为关键字{char *keywords[1000]={"if","int","else","for","while","do","return","break","continue"};//关键字表,按相应类型号排序for(int i = 0;i <= 8;i++) //遍历keywords数组{if (!strcmp(string,*(keywords+i))){return 1; //是关键字,返回对应的类型值}}return 0; //不是关键字,返回0}void Reserve(ifstream &fin) //词法分析程序,用引用传递参数{char temp[100]; // 临时存放已读入但无法判断类型的字符int j = 0;int value_judge ;//存放函数judge的返回值while (fin.get(ch)){if (ch == '\n') {lineno += 1; }else if (ch == '\t'||ch == ' ') {} //排除制表、空格字符else if (isalpha(ch)) //当前输入符为字母{while (isalpha(ch)||isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;if (value_judge = judge(temp)) // 判断是否为关键字{cout << "(1, "<< "\""<<temp<<"\")" << endl;}else cout << "(2, "<< "\""<<temp<<"\")" << endl;fin.seekg(-1,ios::cur); //回退1个字符}else if (isdigit(ch)){while (isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;cout << "(3, "<< "\""<<temp<<"\")" << endl;fin.seekg(-1,ios::cur); //回退一个字符}//+、-、*、/、=、>、<、>=、<=、<>else if (ch == '+') cout << "(4, "<< "\"+\")" << endl;else if (ch == '-') cout << "(4, "<< "\"-\")" << endl;else if (ch == '*') cout << "(4, "<< "\"*\")" << endl;else if (ch == '/') cout << "(4, "<< "\"/\")" << endl;else if (ch == '=') cout << "(4, "<< "\"=\")" << endl;else if (ch == '>') cout << "(4, "<< "\">\")" << endl;else if (ch == '<') cout << "(4, "<< "\"<\")" << endl;else if (ch == '>=') cout << "(4, "<< "\">=\")" << endl;else if (ch == '<=') cout << "(4, "<< "\"<=\")" << endl;else if (ch == '<>') cout << "(4, "<< "\"<>\")" << endl;//,、;、{、}、(、)else if (ch == ',') cout << "(5, "<< "\",\")" << endl;else if (ch == ';') cout << "(5, "<< "\";\")" << endl;else if (ch == '(') cout << "(5, "<< "\"(\")" << endl;else if (ch == ')') cout << "(5, "<< "\")\")" << endl;else if (ch == '{') cout << "(5, "<< "\"{\")" << endl;else if (ch == '}') cout << "(5, "<< "\"}\")" << endl;ch = '\0';}}2、程序设计截图3、程序运行结果截图。
利用VC++6.0编写C语言的词法分析
利用VC++6.0编写C语言的词法分析昆明学院《编译原理课程设计》教学大纲(适用计算机科学与技术专业)(学分:1.0 学时:1周)一、教学目的和任务词法分析器要实现的功能是依次扫视字符串形式源程序中的各个字符,逐个识别出其中的单词。
从左至右扫描源程序的字符串,按照词法规则识别出一个个正确的单词,并转换成该单词相应的二元式交给语法分析使用。
该分析器可以识别关键字,普通标识符,阿拉伯数字,单分界符,代表双分界符。
通过本次词法分析器课程设计进一步理解高级语言在计算机中的执行过程,提高编程能力,培养好的程序设计风格。
同时通过某种可视化编程语言的应用,更进一步加深对编译原理中重点算法和编译技术的理解。
二、课程设计基本内容1、设计题目利用 VC++6.0 编写 C 语言的词法分析1、设计内容对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状态转换图设计词法分析器的基本方法。
2、设计要求利用该词法分析器完成对源程序字符串的词法分析。
输出形式是源程序的单词符号二元式的代码,并保存到文件中。
(1) 假设该语言中的单词符号及种别编码如下表所示。
单词符号及种别编码单词符号种别编码单词符号种别编码main 1 [ 28int 2 ] 29char 3 { 30if 4 } 31else 5 , 32for 6 : 33while 7 ;34标识符ID 10 >35整型常数NUM 20 <36= 21 >=37+ 22 <=38- 23 ==39* 24 !=40/ 25 & 41( 26 && 42) 27 || 43(2) 关键字main int char if else for while都是小写并都是保留字。
算符和界符 = + - * / & <<=>>===!= && || , : ; { } [ ] ( ) ID和NUM的正规定义式为:ID→letter(letter | didit)*NUM→dig it digit*letter→a | … | z | A | … | Zdigit→ 0 | … | 9如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。
词法分析器的设计与实现
词法分析器的设计与实现
1.定义词法规则:根据编程语言的语法规范,定义不同的词法规则,
如关键字、标识符、操作符、常量等。
每个词法规则由一个正则表达式或
有限自动机来描述。
2.构建有限自动机:根据词法规则,构建一个有限自动机(DFA)来
识别词法单元。
有限自动机是一种形式化模型,用于在输入字符序列上进
行状态转换。
3.实现状态转换函数:根据有限自动机的定义,实现状态转换函数。
状态转换函数接受一个输入字符,并返回当前状态和输出的词法单元。
4.实现输入缓冲区:为了方便词法分析器的实现,通常需要实现一个
输入缓冲区,用于存储源代码,并提供一些读取字符的函数。
5. 实现词法分析器:将前面实现的状态转换函数和输入缓冲区结合
起来,实现一个完整的词法分析器。
词法分析器可以使用迭代器模式,每
次调用next(函数来获取下一个词法单元。
6.处理错误情况:在词法分析过程中,可能会遇到一些错误情况,如
未定义的词法单元、不符合语法规范的词法单元等。
词法分析器需要能够
检测并处理这些错误情况。
7.构建测试用例:为了验证词法分析器的正确性,需要构建测试用例,包括各种不同的源代码片段,并验证分析结果是否符合预期。
8.进行性能优化:词法分析是编译器中的一个耗时操作,因此可以进
行一些性能优化,如使用缓存机制、减少状态转换次数等。
以上是词法分析器的设计与实现的一般步骤,具体实现过程可能因编程语言和编译器的不同而有所差异。
pl0词法分析器(C语言版)
#include<stdio.h>#include<string.h>#include<stdlib.h>void init();void getsym();enum symbol {nul,ident,number,plus,minus,times,slash,oddsym,eql,neq, beginsym,endsym,ifsym,thensym,whilesym,writesym,readsym,dosym,callsym, constsym,varsym,procsym,programsym,};#define norw 14#define al 10#define nmax 10char word [norw][al];char ch;enum symbol sym;enum symbol wsym[norw];enum symbol ssym[256];FILE *fin,*fout;void main(){printf("please input outfile's name:\n");//词法分析之后的结果要输出到的文件}char outname[30],inname[30]; scanf("%s",outname);if((fout=fopen(outname,"w"))==NULL){printf("cannot open output file!");exit(0);}printf("please input infile's name:\n");//需要词法分析的源程序scanf("%s",inname);if((fin=fopen(inname,"r"))==NULL){printf("cannot open file!\n");exit(0);}ch=fgetc(fin);while(ch!=EOF){}getsym();//读取源文件void getsym(){long m;char id[al+1],a[al+1];int i,k;init();if(ch==' '||ch==10||ch==9){}else {if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'){k=0;ch=fgetc(fin);do {if(k<al){a[k]=ch;k++;}ch=fgetc(fin);}while((ch>='a'&&ch<='z'||ch>='0'&&ch<='9')||(ch>='A'&&ch<='Z'||ch>='0'&&ch<='9') );a[k]=0;strcpy(id,a);for(i=0;i<norw;i++){if(strcmp(id,word[i])==0){sym=wsym[i]; printf("%s %ssym\n",id,id);fprintf(fout,"%s %ssym\n",id,id);break;}else {if(i==(norw-1)){sym=ident;printf("%s ident\n",id);fprintf(fout,"%s ident\n",id);}}}}else {if(ch>='0'&&ch<='9'){k=0;m=0;sym=number;do}{m=10*m+ch-'0';k++;ch=getc(fin);}while(ch>='0'&&ch<='9');if(k>=nmax){printf("error!数值太大!\n");//exit(0);}printf("%d number\n",m);fprintf(fout,"%d number\n",m); else {if(ch==':'){ch=getc(fin);printf(":fprintf(fout,":ch=fgetc(fin);}else {}sym=nul; fprintf(fout,":nul\n");printf(":nul\n");else {if(ch=='<'){ch=fgetc(fin); if(ch=='='){sym=leq;printf("<=lep\n");fprintf(fout,"<=ch=fgetc(fin);}else {sym=lss; printf("<fprintf(fout,"<}}else {if(ch=='>'){ch=fgetc(fin); if(ch=='='){sym=geq;printf(">=fprintf(fout,">=ch=fgetc(fin);}else {sym=gtr;printf(">fprintf(fout,">}}else {sym=ssym[ch];if(ch=='+'){printf("+plus\n");ch=fgetc(fin);}else lep\n");lss\n");lss\n");geq\n");geq\n");gtr\n");gtr\n");plus\n");fprintf(fout,"+if(ch=='-'){printf("-minus\n");fprintf(fout,"-else if(ch=='*'){printf("*times\n");fprintf(fout,"*elseif(ch=='/'){printf("/slash\n");fprintf(fout,"/minus\n");ch=fgetc(fin);} times\n");ch=fgetc(fin);}slash\n");ch=fgetc(fin);}if(ch=='('){printf("(rparen\n");ch=fgetc(fin);}eql\n");ch=fgetc(fin);}neq\n");ch=fgetc(fin);}period\n");ch=fgetc(fin);}semicoln\n");ch=fgetc(fin);}nul\n",ch);ch=fgetc(fin);}}}}}}}}//对关键字等实现初始化void init(){int i;for(i=0;i<=255;i++){elselparen\n");fprintf(fout,"(elseif(ch==')'){printf(")elseif(ch=='='){printf("=elseif(ch==','){printf(",elseif(ch=='#'){printf("#elseif(ch=='.'){printf(".elseif(ch==';'){printf(";else{printf("%c lparen\n");ch=fgetc(fin);}rparen\n");fprintf(fout,")neq\n");fprintf(fout,"#period\n");fprintf(fout,".semicoln\n");fprintf(fout,"; nul\n",ch);fprintf(fout,"%c }ssym[i]=nul;}ssym['+']=plus;ssym['-']=minus;ssym['*']=times;ssym['/']=slash;ssym['(']=lparen;ssym[')']=rparen;ssym['=']=eql;ssym['.']=period;ssym['#']=neq;ssym[';']=semicolon;strcpy(&(word[0][0]),"begin");strcpy(&(word[1][0]),"call");strcpy(&(word[2][0]),"const");strcpy(&(word[3][0]),"do");strcpy(&(word[4][0]),"end");strcpy(&(word[5][0]),"if");strcpy(&(word[6][0]),"odd");strcpy(&(word[7][0]),"procedure");strcpy(&(word[8][0]),"read");strcpy(&(word[9][0]),"program"); strcpy(&(word[10][0]),"var"); strcpy(&(word[11][0]),"whlie"); strcpy(&(word[12][0]),"write"); strcpy(&(word[13][0]),"then"); wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;wsym[3]=dosym;wsym[4]=endsym;wsym[5]=ifsym;wsym[6]=oddsym;wsym[7]=procsym;wsym[8]=readsym;wsym[9]=programsym;wsym[10]=varsym;wsym[11]=whilesym;wsym[12]=writesym;wsym[13]=thensym;。
编译原理实验-词法分析器
编译原理实验-词法分析器⼀、实验⽬的设计、编制、调试⼀个词法分析程序,对单词进⾏识别和编码,加深对词法分析原理的理解。
⼆、实验内容1.选定语⾔,编辑任意的源程序保存在⽂件中;2.对⽂件中的代码预处理,删除制表符、回车符、换⾏符、注释、多余的空格并将预处理后的代码保存在⽂件中;3.扫描处理后的源程序,分离各个单词符号,显⽰分离的单词类型。
三、实验思路对于实验内容1,选择编写c语⾔的源程序存放在code.txt中,设计⼀个c语⾔的词法分析器,主要包含三部分,⼀部分是预处理函数,第⼆部分是扫描判断单词类型的函数,第三部分是主函数,调⽤其它函数;对于实验内容2,主要实现在预处理函数processor()中,使⽤⽂档操作函数打开源程序⽂件(code.txt),去除两种类型(“//”,“/*…*/”)的注释、多余的空格合并为⼀个、换⾏符、回车符等,然后将处理后的保存在另⼀个新的⽂件(afterdel.txt)中,最后关闭⽂档。
对于实验内容3,打开处理后的⽂件,然后调⽤扫描函数,从⽂件⾥读取⼀个单词调⽤判断单词类型的函数与之前建⽴的符号表进⾏对⽐判断,最后格式化输出。
四、编码设计代码参考了两篇博主的,做了部分改动,添加了预处理函数等1 #include<iostream>2 #include<fstream>3 #include<cstdio>4 #include<cstring>5 #include<string>6 #include<cstdlib>78using namespace std;910int aa;// fseek的时候⽤来接着的11string word="";12string reserved_word[20];//保留13char buffer;//每次读进来的⼀个字符14int num=0;//每个单词中当前字符的位置15int line=1; //⾏数16int row=1; //列数,就是每⾏的第⼏个17bool flag; //⽂件是否结束了18int flag2;//单词的类型192021//预处理函数22int processor(){//预处理函数23 FILE *p;24int falg = 0,len,i=0,j=0;25char str[1000],str1[1000],c;26if((p=fopen("code.txt","rt"))==NULL){27 printf("⽆法打开要编译的源程序");28return0;29 }30else{31//fgets(str,1000,p);32while((c=getc(p))!=EOF){33 str[i++] = c;34 }35 fclose(p);36 str[i] = '\0';37for(i=0;i<strlen(str);i++){38if(str[i]=='/'&&str[i+1]=='/'){39while(str[i++]!='\n'){}40 }//单⾏注释41else if(str[i]=='/'&&str[i+1]=='*'){42while(!(str[i]=='*'&&str[i+1]=='/')){i++;}43 i+=2;44 }//多⾏注释45else if(str[i]==''&&str[i+1]==''){46while(str[i]==''){i++;}47 i--;48if(str1[j-1]!='')49 str1[j++]='';50 }//多个空格,去除空格51else if(str[i]=='\n') {52if(str1[j-1]!='')53 str1[j++]='';54 }//换⾏处理,55else if(str[i]==9){56while(str[i]==9){57 i++;58 }59if(str1[j-1]!='')60 str1[j++]='';61 i--;62 }//tab键处理63else str1[j++] = str[i];//其他字符处理64 }65 str1[j] = '\0';66if((p = fopen("afterdel.txt","w"))==NULL){ 67 printf("can not find it!");68return0;69 }70else{71if(fputs(str1,p)!=0){72 printf("预处理失败!");73 }74else printf("预处理成功!");75 }76 fclose(p);77 }78return0;79 }8081//设置保留字82void set_reserve()83 {84 reserved_word[1]="return";85 reserved_word[2]="def";86 reserved_word[3]="if";87 reserved_word[4]="else";88 reserved_word[5]="while";89 reserved_word[6]="return";90 reserved_word[7]="char";91 reserved_word[8]="for";92 reserved_word[9]="and";93 reserved_word[10]="or";94 reserved_word[11]="int";95 reserved_word[12]="bool";96 }9798//看这个字是不是字母99bool judge_word(char x)100 {101if(x>='a' && x<='z' || x>='A' && x<='Z' ){ 102return true;103 }104else return false;105 }106107//看这个字是不是数字108bool judge_number(char x)109 {110if(x>='0' && x<='9'){111return true;112 }113else return false;114 }115116//看这个字符是不是界符117bool judge_jiefu(char x)118 {119if(x=='('||x==')'||x==','||x==';'||x=='{'||x=='}'){ 120return true;121 }122else return false;123 }124125126//加减乘127bool judge_yunsuanfu1(char x)128 {129if(x=='+'||x=='-'||x=='*')130 {131return true;132 }133else return false;134 }135136//等于赋值,⼤于⼩于⼤于等于,⼩于等于,⼤于⼩于137bool judge_yunsuannfu2(char x)138 {139if(x=='='|| x=='>'||x=='<'||x=='&'||x=='||'){140return true;141 }142else return false;143 }144145146//这个最⼤的函数的总体作⽤是从⽂件⾥读⼀个单词147int scan(FILE *fp)148 {149 buffer=fgetc(fp);//读取⼀个字符150if(feof(fp)){//检测结束符151 flag=0;return0;152 }153else if(buffer=='')154 {155 row++;156return0;157 }158else if(buffer=='\n')159 {160 row=1;161return0;162 }163//如果是字母开头或'_' 看关键字还是普通单词164else if(judge_word(buffer) || buffer=='_')165 {166 word+=buffer;167 row++;168while((buffer=fgetc(fp)) && (judge_word(buffer) || judge_number(buffer) || buffer=='_'))169 {170 word+=buffer;171 row++;172 }173if(feof(fp)){174 flag=0;175return1;176 }177for(int i=1;i<=12;i++){178if(word==reserved_word[i]){179 aa=fseek(fp,-1,SEEK_CUR);//如果执⾏成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。
编译原理课程设计报告——词法分析器
int begin=0,end=0;
vector<string> array;
do
{
begin=DeleteNull(fileline,begin);
string nowString;
nowString=GetWord(fileline,begin,end);
单词符号
种别编码
单词符号
种别编码
main
1
[
28
int
2
]
29
char
3
{
30
if
4
}
31
else
5
,
32
for
6
:
33
while
7
;
34
标识符ID
10
>
35
整型常数NUM
20
<
36
=
21
>=
37
+
22
<=
38
-
23
==
39
*
24
!=
40
/
25
&
41
(
26
&&
42)27||43(2)关键字main int char if elseforwhile都是小写并都是保留字。
int DeleteNull(string str,int i);
/*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/
bool IsBoundary(string str,int i);
/*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/
简单的C语言编译器--词法分析器
简单的C语⾔编译器--词法分析器1. 定义词法单元Tag ⾸先要将可能出现的词进⾏分类,可以有不同的分类⽅式。
如多符⼀类:将所有逗号、分号、括号等都归为⼀类,或者⼀符⼀类,将⼀个符号归为⼀类。
我这⾥采⽤的是⼀符⼀类的⽅式。
C代码如下:#ifndef TAG_H#define TAG_Hnamespace Tag {//保留字const intINT = 1, BOOL = 2, MAIN = 3, IF = 4,ELSE = 5, FOR = 6, WHILE = 7, FALSE = 8,BREAK = 9, RETURN = 10, TRUE = 11 ;//运算符const intNOT = 20, NE = 21, AUTOMINUS =22, MINUS = 23,AUTOADD = 24, ADD = 25, OR = 26,AND = 27, MUTIPLY = 28, DIVIDE = 29, MOD = 30,EQ = 31, ASSIN = 32, GE = 33, GT = 34,LE = 35, LS = 36;//分界符const intCOMMA = 40, SEMICOLON = 41, LLBRACKET = 42,RLBRACKET = 43, LMBRACKET = 44, RMBRACKET = 45,LGBRACKET = 46, RGBRACKET = 47;//整数常数const int NUM = 50;//标识符const int ID = 60;//错误const int ERROR = 404;//空const int EMPTY = 70;}#endif2. 具体步骤⼀个⼀个字符地扫描测试代码,忽略空⽩字符,遇到回车时,记录⾏数加1要进⾏区分标识符(即普通变量名字)和保留字因为将标识符和常数都guiwe各⾃归为⼀类,所以要有算法能够识别出⼀整个常数和完整的标识符加⼊适当的⾮法词检测3. 设计词法分析类 设计⼀个词法分析器,当然要包括如何存储⼀个词法单元,如何扫描(scan)测试代码等,直接上代码:myLexer.h#ifndef MYLEXER_H#define MYLEXER_H#include <fstream>#include <string>#include <unordered_map>#include "tag.h"/** 主要是定义基本的词法单元类,* 声明了词法分析类*///存储词法单元class Word {public:Word() = default;Word(std::string s, int t) : lexeme(s), tag(t) {};std::string getLexeme() { return lexeme; };int getTag() { return tag; }void setTag(int t) { tag = t; }void setLexeme(std::string s) { lexeme = s; }private:std::string lexeme;int tag;};//词法分析器类class Lexer {public:Lexer();void reserve(Word w);bool readnext(char c, std::ifstream &in);Word scan(std::ifstream &in);int getLine() { return line; }private:char peek;std::unordered_map<std::string, Word> words;int line;};#endifmyLexer.cpp#include <iostream>#include <cctype>#include <sstream>#include "myLexer.h"void Lexer::reserve(Word w) {words.insert({w.getLexeme(), w});}Lexer::Lexer() {//存⼊保留字,为了区分标识符reserve( Word("int", Tag::INT) );reserve( Word("bool", Tag::BOOL) );reserve( Word("main", Tag::MAIN) );reserve( Word("if", Tag::IF) );reserve( Word("else", Tag::ELSE) );reserve( Word("for", Tag::FOR) );reserve( Word("while", Tag::WHILE) );reserve( Word("break", Tag::BREAK) );reserve( Word("return", Tag::RETURN) );reserve( Word("true", Tag::TRUE) );reserve( Word("false", Tag::FALSE) );peek = ' ';line = 1;}//⽅便处理像>=,++等这些两个字符连在⼀起的运算符 bool Lexer::readnext(char c, std::ifstream &in) {in >> peek;if( peek != c)return false;peek = ' ';return true;}Word Lexer::scan(std::ifstream &in) {//跳过空⽩符while(!in.eof()) {if(peek == ' ' || peek == '\t') {in >> peek;continue;}else if(peek == '\n')++line;elsebreak;in >> peek;}//处理分界符、运算符等switch(peek) {case '!':if(readnext('=', in))return Word("!=", Tag::NE);elsereturn Word("!", Tag::NOT);case '-':if(readnext('-', in))return Word("--", Tag::AUTOMINUS);elsereturn Word("-", Tag::MINUS);case '+':if(readnext('+', in))return Word("++", Tag::AUTOADD);elsereturn Word("+", Tag::ADD);case '|':if(readnext('|', in))return Word("||", Tag::OR);elsereturn Word("error", Tag::ERROR);case '&':if(readnext('&', in))return Word("&&", Tag::AND);elsereturn Word("error", Tag::ERROR);case '*':in >> peek;return Word("*", Tag::MUTIPLY);case '/':in >> peek;return Word("/", Tag::DIVIDE);case '%':in >> peek;return Word("%", Tag::MOD);case '=':if(readnext('=', in))return Word("==", Tag::EQ);elsereturn Word("=", Tag::ASSIN);case '>':if(readnext('=', in))return Word(">=", Tag::GE);elsereturn Word(">", Tag::GT);case '<':if(readnext('=', in))return Word("<=", Tag::LE);elsereturn Word("<", Tag::LS);case ',':in >> peek;return Word(",", Tag::COMMA);case ';':in >> peek;return Word(";", Tag::SEMICOLON);case '(':in >> peek;return Word("(", Tag::LLBRACKET);case ')':in >> peek;return Word(")", Tag::RLBRACKET);case '[':in >> peek;return Word("[", Tag::LMBRACKET);case ']':in >> peek;return Word("]", Tag::RMBRACKET);case '{':in >> peek;return Word("{", Tag::LGBRACKET);case '}':in >> peek;return Word("}", Tag::RGBRACKET);}//处理常数if(isdigit(peek)) {int v = 0;do {v = 10*v + peek - 48;in >> peek;} while(isdigit(peek));if(peek != '.')return Word(std::to_string(v), Tag::NUM);}//处理标识符if(isalpha(peek)) {std::ostringstream b;do {b << peek;in >> peek;} while(isalnum(peek) || peek == '_');std::string tmp = b.str();//判断是否为保留字if(words.find(tmp) != words.end())return words[tmp];elsereturn Word(tmp, Tag::ID);}if(peek != ' ' && peek != '\t' && peek != '\n')return Word("error", Tag::ERROR);return Word("empty", Tag::EMPTY);} 设计完成后,⾃⼰写⼀个Main函数,在while循环中调⽤scan函数,每次打印出Word内容,就能够得到。
词法分析器实验报告
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。
《C-语言的词法分析器(基于Lex)》课程设计报告
《C-语⾔的词法分析器(基于Lex)》课程设计报告《编译原理与实践》课程报告课题名称: C-语⾔的词法分析器实现(基于Lex)课题负责⼈名(学号):李恒(0643111198)同组成员名单(⾓⾊):⽆指导教师:于中华评阅成绩:评阅意见:提交报告时间:2007 年12 ⽉31⽇1. ⽬的与意义词法分析是编译原理中⼀个重要的部分。
它可将源程序读作字符⽂件并将其分为若⼲个记号,每⼀个记号都是表⽰源程序中信息单元的字符序列。
词法分析器是翻译步骤的第⼀步,它对于编译器接下来要进⾏的⼯作起着开头的作⽤,因此要想实现对C-语⾔的编译器,词法分析器必不可少。
2. 基于Parser Generator的词法分析器构造⽅法利⽤Parser Generator构造词法分析器规则,⽣成对应的c语⾔及其头⽂件。
然后进⾏编译。
3. C-语⾔词法分析的设计重要数据类型:关键字枚举:typedef enum{ENDFILE, ERROR,/* reserved words */ELSE, IF, INT, RETURN, VOID, WHILE,/* multicharacter tokens */ID, NUM,/* special symbols */PLUS, MINUS, TIMES, OVER, LT, LE, GT, GE, EQU, NEQU,ASSIGN, SEMI, COMMA, LPAREN, RPAREN, LBRKT, RBRKT, LBRC, RBRC, LCOM, RCOM}TokenType;关键字声明:digit [0-9]number {digit}+letter [a-zA-Z]identifier {letter}+newline \nwhitespace [ \t]+c-语⾔的词法规则:"else" {return ELSE;} "if" {return IF;}"int" {return INT;} "return" {return RETURN;} "void" {return VOID;} "while" {return WHILE;} "+" {return PLUS;} "-" {return MINUS;} "*" {return TIMES;} "/" {return OVER;} "<" {return LT;}"<=" {return LE;} ">" {return GT;}">=" {return GE;}"==" {return EQU;}"!=" {return NEQU;} "=" {return ASSIGN;} ";" {return SEMI;} "," {return COMMA;} "(" {return LPAREN;} ")" {return RPAREN;} "[" {return LBRKT;} "]" {return RBRKT;} "{" {return LBRC;} "}" {return RBRC;} {number} {return NUM;} {identifier} {return ID;} {newline} {lineNo++} {whitespace} {/* skip */} "/*" { char c;do{ c = input();if (c == EOF ) break;if (c == '\n' ) lineNo++;} while ( c != '/*');}{return ERROR;}重要处理程序设计:⽂件util.c执⾏输出结果的打印:void printToken(TokenType token, const char* tokenString) { switch (token){case ELSE:case IF:case INT:case RETURN:case VOID:case WHILE:fprintf(listing, "reserved word: %s\n", tokenString);break;case PLUS:fprintf(listing, "+\n");break;case MINUS:fprintf(listing, "-\n");break;case TIMES:fprintf(listing, "*\n");break;case OVER:fprintf(listing, "/\n");break;case LT:fprintf(listing, "<\n");break;case LE:fprintf(listing, "<=\n");break;fprintf(listing, ">\n"); break;case GE:fprintf(listing, ">=\n"); break;case EQU:fprintf(listing, "==\n"); break;case NEQU:fprintf(listing, "!=\n"); break;case ASSIGN: fprintf(listing, "=\n"); break;case SEMI:fprintf(listing, ";\n"); break;case COMMA: fprintf(listing, ",\n"); break;case LPAREN: fprintf(listing, "(\n"); break;case RPAREN: fprintf(listing, ")\n"); break;case LBRKT: fprintf(listing, "[\n"); break;case RBRKT: fprintf(listing, "]\n"); break;case LBRC:fprintf(listing, "{\n");case RBRC:fprintf(listing, "}\n");break;case LCOM:fprintf(listing, "/*\n");break;case RCOM:fprintf(listing, "*/\n");break;case ENDFILE:fprintf(listing,"EOF\n");break;case NUM:fprintf(listing, "NUM,val=%s\n",tokenString); break;case ID:fprintf(listing, "ID, name=%s\n",tokenString); break;case ERROR:fprintf(listing, "ERROR: %s\n",tokenString); break;default:break;}}函数getToken获取下⼀个token:TokenType getToken(void){ static int firstTime = TRUE; TokenType currentToken;if (firstTime){ firstTime = FALSE;lineNo++;yyin = source;yyout = listing;}currentToken = yylex();strncpy(tokenString,yytext,MAXTOKENLEN);if (TraceScan) {fprintf(listing, "\t%d: ", lineNo);printToken(currentToken,tokenString);}return currentToken;}4. 运⾏结果及分析输⼊⽂件如果所⽰:输出结果如图:对于输⼊的每⼀⾏进⾏词法分析,表⽰出保留字,标识符,以及终结符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一:词法分析程序的设计与实现姓名:专业班级:学号:一、实验目的设计一个简单的词法分析器,从而进一步加深对词法分析器工作原理的理解。
二.、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求根据PL/0语言文法,编制词法分析程序GETSYM完成以下功能:1)从键盘读入数据,分析出一个单词。
2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。
四.、实验步骤1. 采用C语言,设计GETSYM ,实现该算法2. 编制测试程序(主函数main)。
3. 调试程序:输入一组单词,检查输出结果。
五.、实验设计分析1.词法的正规式描述S=aA|aA=(aA|dA)}(a|d)2.变换后的正规文法S→aAS→aA→aAA→dAA→aA→d3.词法分析程序的程序代码#include "stdafx.h"#include <iostream>#include<string>using namespace std;#define MAX 17char ch =' ';stringkey[17]={"const","long","float","double","void","main","if","else","then","break","int","char","in clude","for","while","printf","scanf"};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 IsLetter1(char c){ //判断是否为a~f字母if(((c<='f')&&(c>='a'))||((c<='F')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void scan(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF){arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)||ch=='_'){arr=arr+ch;ch=fgetc(fpin);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)){int flag=0;if(ch=='0'){arr=arr+ch;ch=fgetc(fpin);if(ch>='0'&&ch<='7'){while(ch>='0'&&ch<='7'){flag=1;arr=arr+ch;ch=fgetc(fpin);}}else if(ch=='x'||ch=='X'){flag=2;arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)||IsLetter1(ch)){arr=arr+ch;ch=fgetc(fpin);}}else if(ch==' '||ch==','||ch==';' ){cout<<arr<<"\t整数0"<<endl;}fseek(fpin,-1L,SEEK_CUR);if(flag==1) cout<<arr<<"\t八进制整数"<<endl;else if(flag==2) cout<<arr<<"\t十六进制整数"<<endl;}else{arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t十进制整数"<<endl;}}else switch(ch){case'+':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分析如下:\n"<<endl;scan(fpin);fclose(fpin);}七.实验测试:输入数据及运行结果:int a=3;double b=4;int c;if(a>b)c=a;elsec=b;。