实验1-3-《编译原理》词法分析程序设计方案

合集下载

编译原理词法分析程序实现实验报告

编译原理词法分析程序实现实验报告

编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。

输入:由无符号数和+,,,*,/, ( , ) 构成的算术表达式,如1.5E+2,100。

输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。

二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:输入字符p指向第一个字符符号识别*p=+||-||*||/YYNN*p=0~9*p=E*p=0~9||"."N无效符号Y*p=“.”GOTO 2GOTO 1GOTO 1:NY无符号数GOTO 1*p=0~9*p='/0'YNP++NNP++*p=E*p='+'||'-'YYP++P++continueYY*p=0~9*p=0~9NN无符号数无符号数P++P++continuecontinueGOTO 2:GOTO 2*p=EcontinueY无符号数P++continue三、源程序代码部分#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~9 int 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=='.') return 1;else return 0;}void DistinguishSign(char *p) { int Class;char ch=*p;switch(ch){case '+':Output(PLUS,p,p);Type[count++]=PLUS;break;case '-':Output(SUBTRACT,p,p);Type[count++]=SUBTRACT;break; case '*':Output(MULTIPLY,p,p);Type[count++]=MULTIPLY;break; case '/':Output(DIVIDE,p,p);Type[count++]=DIVIDE;break; case '(':Output(LEFTBRACKET,p,p);Type[count++]=LEFTBRACKET;break; case ')':Output(RIGHTBRACKET,p,p);Type[count++]=RIGHTBRACKET;break; default:break;}}void TypyDistinguish(){printf("词法开始,分析结果如下:\n");char *p;p=&Store[0];while(*p!='\0'){if(Sign(p)){DistinguishSign(p++);continue;}else if(UnsignedNum(p)||*p=='.'){char *p1=p;if(UnsignedNum(p)){while(UnsignedNum(p))p++;if(*p=='\0'){Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='E'){p++;if(UnsignedNum(p)){while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='+'||*p=='-'){p++;while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p);Type[count++]=UNSIGNEDNUMBER;p++;continue;}else{Output(INEFFICACIOUSLABEL,p1,--p);printf("输入的这个符号是不合法的~"); break; Type[count++]=INEFFICACIOUSLABEL;p++;continue;}}else if(*p=='.'){p++;while(UnsignedNum(p))p++;if(*p=='\0'){Output(UNSIGNEDNUMBER,p1,--p);Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='E'){p++;if(UnsignedNum(p)){while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='+'||*p=='-'){p++;if(UnsignedNum(p)){while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p);Type[count++]=UNSIGNEDNUMBER;p++;continue;}else{Output(INEFFICACIOUSLABEL,p1,--p);printf("输入的这个符号是不合法的~ /n");break;Type[count++]=INEFFICACIOUSLABEL;p++;continue;}}else{Output(INEFFICACIOUSLABEL,p1,--p);printf("输入的这个符号是不合法的~因为他的后面既不是0~9也不是“+”或者“-…");break;//1.5E*2这样的字符串不是无符号数Type[count++]=INEFFICACIOUSLABEL;p++;continue;}}else{Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}}else{Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}}if(*p=='.'){p++;if(UnsignedNum(p)){p++;while(UnsignedNum(p))p++;if(*p=='\0'){Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='E'){p++;if(UnsignedNum(p)){while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;continue;}else if(*p=='+'||*p=='-'){p++;while(UnsignedNum(p))p++;Output(UNSIGNEDNUMBER,p1,--p);Type[count++]=UNSIGNEDNUMBER;p++;continue;}}else{Output(UNSIGNEDNUMBER,p1,--p);Type[count++]=UNSIGNEDNUMBER;p++;continue;}}else{Output(INEFFICACIOUSLABEL,p1,--p);printf("输入的这个符号是不合法的~"); break; Type[count++]=INEFFICACIOUSLABEL;p++;continue;}}}else if(*p=='E'){Output(INEFFICACIOUSLABEL,p,p); break;Type[count++]=INEFFICACIOUSLABEL;printf("输入的这个符号是不合法的~");p++;continue;}}printf("\n\n词法分析完毕~");}void ShowType()//将类别码存储在Type[100]中,为语法分析做准备{printf("\n用类别码表示输入的字符如下:\n");int i;printf("\n");for(i=0;Type[i]!=FINISH;i++){printf("%d",Type[i]);}printf("\n\n");}void main(){//词法分析部分StoreStr();ShowStore();TypyDistinguish();Type[count]=FINISH;ShowType();}四、实验结果正确的结果:错误的结果:输入的字符串中有1.5E*2因为实验是以文件的形式进行读取的所以,在读取不合法的过程中只是将存在project 中的a.txt 中的内容改变改为1.5E*2+100*555实验结果如下:结果分析:对于正确的结果,我以二元式的形式输出,包括他的值和他的类别码,其中将类别码存放在另外的一个数组中,为了在实验二中的语法识别打下基础。

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

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

编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的: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对象。

五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。

我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。

这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。

编译原理综合性实验:词法分析的设计

编译原理综合性实验:词法分析的设计
编译过程中编译程序需要不断汇集和反复查证出现在源程序中各种名字的属性和特征 等有关信息。这些信息通常记录在符号表中。符号表中的每一项一般包含两部分:名字,与 此名字有关的信息,如类型,种属,值等。符号表主要在词法或语法分析阶段生成,可能用 于语义检查、产生中间代码以及最终生成目标代码等不同阶段。
对数字常数的处理如下:先查符号表 VAL 栏,若发现相同的常数则直接输出其二元式。 若表内无相同的常数,则将数字常数填入符号表内,在 TYPE 栏内填入整型或实型,然后输 出其二元式。二元式中包含该常数在符号表中的入口。
1.3 词法分析程序的详细设计
图 1-3 的数据流图属于输入-变换-输出形式的变换型数据流图,但加工 1.3—1.9 构成了典型的事务处理型数据流图。根据数据流图,可以得到词法分析 程序的总体框架,如图 1-4。
图 1-3 词法分析程序的详细数据流图 在上面的数据流图中,各个加工处理完成的功能如下: 加工 1.1(读一行并打印):收到读下一行命令后,从源程序读入一行,装入缓冲区,行计 数,并打印。在这里需要注意的是,回车换行在源程序(文本文件)中用两个字符 0D0AH 来表示,而用高级语言(C 语言)读入内存后,就用一个字符 0AH 来表示,这是在用高级
查找函数可以使用顺序查找,也可以使用折半查找。 例如:使用顺序查找方法查找给定单词 key 是否是关键字的函数原型和算法描述如下:
int iskeyword (char * str)/*设 keyword 为所有关键字列表*/ /*该函数返回 0 表示 str 不是关键字,不为 0 表示 str 是关键字*/
词不能跨行书写; (4) 关键字都是保留字。
1.2 词法分析程序的总体设计
图 1-2 词法分析程序的顶层数据流图 图 1-2 是词法分析程序的顶层数据流图,即是词法分析程序的输入输出界面图,由此可 以看出词法分析程序的功能就是从源程序中读入一个个字符,依据一定的构词规则,识别出 各类有用的单词。其中源程序清单和错误信息从屏幕、打印机或文件输出,其余文件均以顺 序文件的形式输出到外存储器上,以供下一阶段使用。由此可以得到更详细的数据流图,如 图 1-3。

编译原理实习设计——词法分析程序

编译原理实习设计——词法分析程序

图三:实数的识别
} 27 { * 26 * 25 ] * 24 [ * 23 ( * 22 ) * 21 ; *
20 , * * | 19 18 非| 17 | * * 16 & 15 非& 14 & * = 13 * 12 非= 11 = * 10 # * 9 = * 8 非= 7 %
* 6 ^ * 5 = * 4 非= 3 ! * 2
if(c=='>' || c=='"') { Output("$ID", string); for(int p=0; p<k; p++) { string[p]=NULL; } break; } else if( c=='.' || IsLetter(c) IsDigit(c) ) { string[k++]=c; } } break; } j++; } c=Get_ch(++j); } if(IsLetter(c) || c=='_') { k=0; string[k++]=c; j++; while(1) { c=Get_ch(j); if(IsLetter(c) || c=='_' || IsDigit(c)) { string[k++]=c; } else { if(IsKeyword(string) ) { Output("$keyword", string); }
!= ^ % %= = == && & | || , ; ( ) [ ] { } + ++ += - ―― -= * *= / /=

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

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

编译原理词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求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.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)……三、词法分析程序的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();void scanner_example (FILE *fp);main(){FILE *fp;fp=fopen("D:\\1.txt","r");//打开文件scanner_example (fp);scaner();}void scanner_example (FILE *fp){do{ch=fgetc (fp);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");default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);}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;case '-':token[m++]=ch;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;token[m++]=ch;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)……如图所示:五、总结:词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

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

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

编译原理词法分析实验报告实验一词法分析一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

二、实验内容(1)功能描述:该程序是实现一个词法分析器,词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

本实验中,采用的是将单词分为五种的方法。

识别关键字:main、if、int、for、while、do、return、break、continue;单词种别码为1。

标识符:单词种别码为2。

常数:为无符号整形数;单词种别码为3。

运算符:包括:+、-、*、/、=、>、<、>=、<=、!= ;单词种别码为4。

分隔符:包括:,、;、{、}、(、);单词种别码为5。

(2)程序结构描述:输入:从控制台输入一段源程序代码,对输入的代码进行词法分析,处理:分离出关键字、标识符、数值、运算符和界符。

输出:在词法分析结果表中输出每个单词所在行号、类型以及它所对应的编码。

其中,编码是自定义的,一种类型对应一个编码。

词法分析结果显示在控制台上。

(3)程序设计思路1、定义编码表,用ArrayList集合存放单词,如:关键字、运算符、分界符。

这三种单词是固定的,标示符和数字这两种单词不存放在集合中。

编码表是固定的,只需要初始化一次就够了,所以将集合定义为static类型,使其在类加载时,进行一次初始化。

2、static char allstr[] = new char[100000];该数组用于存储用户从控制台输入的所有字符。

3、//从键盘获取一个一个的字符public char Getchar() {try {ch = (char) System.in.read();} catch (Exception e) {e.printStackTrace();}return ch;}4、用while循环遍历allstr数组中存放的字符,判断分离出关键字、标示符、数字、运算符、标示符。

编译原理实验-词法分析器的设计

编译原理实验-词法分析器的设计

集美大学计算机工程学院实验报告课程名称:编译原理班级:指导教师:姓名:实验项目编号:实验一学号:实验项目名称:词法分析器的设计实验成绩:一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

二、实验内容编写一个词法分析器,从输入的源程序(编写的语言为C语言的一个子集)中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验要求1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

单词示例单词种别码要求保留字if、else、int、while、do 每个保留字的单词种别都单独为一种标识符以字母开头且包含字母和数字的字符串标识符作为一种常数(只识别无符号整数)123、343 无符号整数作为一种运算符+、-、*、/、=、= = 、!=、> 、<、>=、<= 每符一种,也可以每一类符号一种分隔符,、;、{、}、(、) 每符一种2、上述要求仅为基本要求,可以在此基础上扩充,例如删除注释,增加识别单词的类型,将标识符和常量分别插入到相应的符号表中,增加错误处理等。

3、编程语言不限。

四、实验设计方案1、数据字典本实验用到的数据字典如下表所示:单词示例标识ID1 保留字void、if、else、for、while、do、return、break、main、int、float、char、double、String标识符以字母开头且包含字母和数字的字符串 2无符号整数和小数 3 常数(只识别无符号整数)运算符+、-、*、/、=、> 、<、 4分隔符,、;、{、}、(、) 5 本实验所使用的开发语言是C语言,在Test2类中定义了以下几个函数:2.程序流程图:YNY NNY YN Y N Y YN NN Y YN N N Y Y开始读入文件,把内容存入string 中,m=0,check=ture ,error=false从string 中读出一个字符放入ch 中输出str ,标识为无法识别的串check=ture ,error=falsech 是运算符?error=ture ? check=false ? 输出str ,标识为标示符check=ture 输出str ,标识为运算符输出str ,标识为无法识别的串check=ture ,error=falseerror=ture ? check=false ? 输出str ,标识为标示符check=ture 输出str ,标识为分隔符ch 是分隔符?ch 是数字?check=ture ?清空str ,ch 加到str 中,check=false ch 加到str 中Ch 是字母?check=ture ?清空str ,ch 加到str 中,check=falsech 加到str 中打印出错ch 是最后一个字符? 结束YN Y N3、实验程序#include<stdio.h> #include<string.h> #include<ctype.h> #include<windows.h>//判断读入的字符是否为字母 bool isLetter(char c){if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){ return true; } else return false; }//判断读入的字符是否为数字 bool isDigit(char c){if(c >='0' && c <= '9'){ return true; } else return false; }//判断是否为关键字 bool isKey(char *string) { if(!strcmp(string,"void")|| !strcmp(string,"if")|| !strcmp(string,"for")|| !strcmp(string,"while")|| !strcmp(string,"do")|| !strcmp(string,"return")|| !strcmp(string,"break")|| !strcmp(string,"main")|| !strcmp(string,"int")|| !strcmp(string,"float")|| !st rcmp(string,"char") || !strcmp(string,"double")|| !strcmp(string,"String")) { return true;ch 是数字?ch 加到str 中,error=true ch 是关键字? 输出str ,标识为关键字,check=true}else return false;}bool isError(char ch){if(ch == '@' || ch == '$' || ch == '&' || ch == '#' || ch == '~' || ch == '^'){return true;}elsereturn false;}void main(){char string[500]="";//存放文件中读出来的字符串char str[10]="";//存放需要对比的字符串char ch,c;//ch存放文件中的单个字符(翻译时用),c存放文件中的单个字符(从文件中提取信息时用)char filename[20];//文件名int j=0;printf("请输入文件名进行词法翻译:");scanf("%s",filename);FILE *cfPtr;if((cfPtr=fopen(filename,"r"))==NULL)printf("文件未找到!");else{while(!feof(cfPtr)){if(isspace(c=fgetc(cfPtr))){//判断是否是字符串;}else{string[j]=c;//从文件中一一提取字符j++;}}}int m = 0,k=0;//m翻译时用,k是str数组的下标string[j]=' ';j++;bool check=true,error=false;//用于判断标识for(int i = 0;i < j;i++){//实现语法翻译器switch (m){ch = string[i];if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '='|| ch == '>' || ch == '<'){if(error){printf("%s,此字符无法是识别!\n",str);error=false;check=true;}else if(!check){printf("(2,%s)标示符\n",str);check=true;}m = 4;}else if(ch == ',' || ch == ';' || ch == '{' || ch == '}' || ch == '(' || ch == ')'){if(error){printf("%s此字符无法识别\n",str);error=false;check=true;}else if(!check){printf("(2,%s)标示符\n",str);check=true;}m = 5;}else if ( isDigit((ch =string[i]) ) ){if(check){memset(str, 0, strlen(str));//清空k=0;str[k]=ch;k++;m = 3;check=false;} else{str[k]=ch;k++;}}else if ( isLetter(ch = string[i]) )if(check){check=false;memset(str, 0, strlen(str));k=0;str[k]=ch;k++;}else{str[k]=ch;k++;if(isKey(str)){printf("(1,%s)关键字\n",str);check=true;}}}else if(isError(ch = string[i])){if(check){memset(str, 0, strlen(str));//清空k=0;str[k]=ch;k++;check=false;error=true;}else{str[k]=ch;k++;error=true;}}else{}break;case 3:if(isLetter(ch =string[i])){printf("程序有错误!!!\n");str[k] = ch;k++;error=true;m = 0;break;}if(isError(ch = string[i])){printf("程序有错误!!!\n");str[k] = ch;k++;error=true;m = 0;break;}if (isDigit((ch =string[i] ) )){str[k] = ch;k++;}else if(ch=='.'){str[k]=ch;k++;}else{printf("( 3,%s) 数字\n",str);i --;m = 0;check=true;}break;case 4:i--;printf("( 4 ,%c) 运算符\n",ch);m = 0;break;case 5:i --;printf("( 5 ,%c) 分隔符\n",ch);m = 0;break;}}return;}五、实验结果六、实验小结本次实验中,运用C语言进行实验,实验刚开始的时候,能够对输入的字符进行判断,但是却不能排错以及只能识别全是字母的标识符,后来经过修改程序代码和编程的逻辑最终实现了,既能排错又能分析句子;通过实验掌握了词法分析,能实现对普通程序的语法分析翻译。

编译原理实验 词法分析&语法分析程序

编译原理实验 词法分析&语法分析程序

编译原理实验词法分析程序实验一:词法分析程序1、实验目的从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。

2、实验内容表C语言子集的单词符号及内码值单词符号种别编码助记符内码值while 1 while --if 2 if --else 3 else --switch 4 switch --case 5 case --标识符 6 id id在符号表中的位置常数7 num num在常数表中的位置+ 8 + --- 9 - --* 10 * --<= 11 relop LE< 11 relop LT== 11 relop LQ= 12 = --; 13 ; --输入源程序如下if a==1 a=a+1;else a=a+2;输出对应的单词符号形式的中间程序3、实验过程实验上机程序如下:#include "stdio.h"#include "string.h"int i,j,k;char s ,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("please input you source program,end('#'):\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*10);j=0;get();while(s!='#'){if(s==' '||s==10||s==13)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(Digit()||letter()){token[j]=s;j=j+1;get();}retract();k=lookup();if(k==0)printf("(6,%s)\n",token); elseprintf("(%d,null)\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()){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();}}}4、实验结果实验结果分析:if是关键字,对应种别编码为2,输出(2,null)a是标识符,对应种别编码为6,值为a,输出(6,a)==的助记符是relop,内码值为LE,输出(relop,LE)1是常数,对应种别编码为7,值为1,输出(7,1)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)1是常数,对应种别编码为7,值为1,输出(7,1);是语句结束符号,直接输出(;,null)else是关键字,对应种别编码为3,输出(3,null)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)2是常数,对应种别编码为7,值为2,输出(7,2);是语句结束符号,直接输出(;,null)#是输入结束标志编译原理实验语法分析程序实验二:语法分析程序1、实验目的:将单词组成各类语法单位,讨论给类语法的形成规则,判断源程序是否符合语法规则3、实验内容:给定文法:G[E]:E→E+E|E-E|E*E|E/E|(E)E→0|1|2|3|4|5|6|7|8|9首先把G[E]构造为算符优先文法,即:G’[E]:E→E+T|TT→T-F|FF→F*G|GG→G/H|HH→(E)|i得到优先关系表如下:+ - * / i ( ) # + ·><·<·<·<·<··>·> - ·>·><·<·<·<··>·> * ·>·>·><·<·<··>·> / ·>·>·>·><·<··>·>i ·>·>·>·>·>·>( <·<·<·<·<·<·=) ·>·>·>·>·>·> # <·<·<·<·<·<·=构造出优先函数+ - * / i ( ) #f 6 8 10 12 12 2 12 2g 5 7 9 11 13 13 2 2要求输入算术表达式:(1+2)*3+2*(1+2)-4/2输出其对应的语法分析结果4、实验过程:上机程序如下:#include "stdio.h"#include "string.h"char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>=48)&&(s<=57))return 1;else return 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");}}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");}}void get(){s=a[i];i=i+1;}void main(){printf("请输入算数表达式,并以‘#’结束:\n");i=0;do{scanf("%c",&a[i]);i++;}while(a[i-1]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j]!='#')||(s!='#')){if(operand(s)){opnd[k]=s-48;k=k+1;get();}else if(f(optr[j])<g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j])==g(s)){if(optr[j]=='('&&s==')'){j=j-1;get();}else if(optr[j]=='('&&s=='#'){printf("error\n");break;}else if(optr[j]=='#'&&s==')'){printf("error\n");break;}}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{printf("error\n");break;}}if(j!=0||k!=1)printf("error\n");}5、实验结果:实验结果分析:(1+2)*3+2*(1+2)-4/2#因为‘)’优先级大于‘*’,先计算1+2=3,并输出(+,1,2,3)原式变为:3*3+2*(1+2)-4/2#因为‘*’优先级大于‘+’,先计算3*3=9,并输出(*,3,3,9)原式变为:9+2*(1+2)-4/2#因为‘)’优先级大于‘-’,先计算1+2=3,并输出(+,1,2,3)原式变为:9+2*3-4/2#因为‘*’优先级大于‘-’,先计算2*3=6,并输出(*,2,3,6)原式变为:9+6-4/2#因为‘/’优先级大于‘#’,先计算4/2=2,并输出(/,4,2,2)原式变为:9+6-2#因为‘-’优先级大于‘#’,先计算6-2=4,并输出(-,6,2,4)原式变为:9+4#因为‘+’优先级大于‘#’,计算9+4=13,并输出(+,9,4,13)原式变为13#优先级等于#,跳出while循环,运算结束!。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验1-3-《编译原理》词法分析程序设计方案实验1-3 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式;二、实验内容1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。

在此,词法分析程序作为单独的一遍,如下图所示。

源程序词法分析程序二元式文件具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。

将错误信息输出到屏幕上。

(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。

常量表结构:常量名,常量值三、实验要求1.能对任何S语言源程序进行分析在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。

2.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。

本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。

2:源程序文件结束而注释未结束。

注释格式为:/* …… */四、保留字和特殊符号表单词代码1 2 3 4 5 6 7 8 9单词int char floatvoidconstforif else then单词助记符int charfloatvoidconstforif else then内码值- - - - - - - - -单词代码10 11 12 13 14 15 16 17 18单词while switchbreakbeginend 标识符数字(包括整数和实数)单词助记符whileswitchbreakbeginend id num内码值- - - - - 在符号表中的位置在常数表中的位置单词代码19 20 21 22 23 24 25 26 27 单词+ - * / % ( ) [ ] 单词助记符+ - * / % ( ) [ ]内码值- - - - - - - - -单词代码28 28 29 30 单词!= < > <= >= == ;{ }单词助记符rlop ;{ }内码值!= < > <= >= == - -单词代码37 38 39 40 41 42 43 44 45单词/= += -= *= %= || &&! =单词助记符/= += -= *= %= or andnot =内码值- - - - - - - - -单词的构词规则:字母=[A-Za-z]数字=[0-9]标识符=(字母|_)(字母|数字)*数字=数字(数字)*(.数字+| )四、S语言表达式和语句说明1.算术表达式:+、-、*、/、%2.关系运算符:>、>=、<、<=、==、!= 3.赋值运算符:=,+=、-=、*=、/=、%= 4.变量说明:类型标识符变量名表;5.类型标识符:int char float6.If语句:if 表达式then 语句[else 语句]7.For语句:for(表达式1;表达式2;表达式3)语句8.While语句:while 表达式do 语句9.S语言程序:由函数构成,函数不能嵌套定义。

函数格式为:返回值函数名(参数){数据说明语句}五、程序参考结构说明Scanner closeIsalpha Isnumber Isanotation Output IsotherError主函数Initscanner Lexscan1.Initscanner 函数:程序初始化:输入并打开源程序文件和目标程序文件,初始化保留字表 2.Scanner 函数:若文件未结束,反复调用lexscan 函数识别单词。

3.Lexscan 函数:根据读入的单词的第一个字符确定调用不同的单词识别函数 4.Isalpha 函数:识别保留字和标识符 5.Isnumber 函数:识别整数,如有精力,可加入识别实数部分工功能6.Isanotation 函数:处理除号/和注释 7.Isother 函数识别其他特殊字符8.Output 函数:输出单词的二元式到目标文件,输出格式(单词助记符,单词内码值),如(int,-)(rlop,>)……9.Error函数:输出错误信息到屏幕10.除此之外,还可以设置查符号表,填写符号表等函数,学生可自行设计。

实验中,可以将某些类型的单词识别过程利用DFA算法实现,DFA算法参考如下:DFA(S=S0,MOVE[][],F[],ALPHABET[],ALLS[])/*S为状态,初值为DFA的初态,MOVE[][]为状态转换矩阵,F[] 为终态集,ALPHABET[] 为字母表,其中的字母顺序与MOVE[][] 中列标题的字母顺序一致。

ALLS[]为状态集*/{Char Wordbuffer[10]=“”//单词缓冲区置空Nextchar=getchar();//读字符i=0;while(nextchar!=NULL)//NULL代表此类单词{ if (nextcha r!∈ALPHABET[]){ERROR (“非法字符”),return(“非法字符”);}S=MOVE[S][nextchar] //下一状态if(S=NULL)return(“不接受”);//下一状态为空,不能识别,单词错误wordbuffer[i]=nextchar ;//保存单词符号i++;nextchar=getchar();}Wordbuffer[i]=‘\0’;If(S∈F)return(wordbuffer);//接受Else return(“不接受”);}六、实验过程说明1.每人单独完成。

2.完成后,由老师验收,并给出成绩。

3.实验完成后,写出实验报告(要求交打印稿)。

报告内容要求如下:完成人:班级、学号、姓名一、实验名称:简化S语言词法分析器二、实验目的:通过手工编写简化C语言词法分析器,熟悉并深入理解编译程序词法分析器2.设计词法分析器模块调用结构图和各模块流程图。

3.程序源代码。

七、测试源程序示例://aa.cvoid aa( ){float rate,circle;rate=3;circle=3.14*rate*rate;}输出结果:(1)输出结果文件:(void,-)(id, 0) ((,-) (),-) ({,- ) ( float,-) (id,1)……(2)标识符的符号表:Name type address0 aa1 rate2 circle345(3)常数表:Namevalue0 31 3.1423实验地点:教10五楼计算机学院软一机房实验时间:第4周周二3单元、周四1单元、第五周周二3单元八、实验代码#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<string.h>#define MAX 10//保留字符号长度#define MAXSIZE 45//保留字和特殊符号表长#define NUM 30//标识符和常数的个数FILE *in,*out;// 指向文件的指针char infile[MAX];//文件名字char token[MAX];char Word[NUM][MAX];//标识符char consts[NUM][MAX];//常数charlownum[NUM][MAX]={"0","1","2","3","4"," 5","6","7","8","9","10","11","12","13","14","15","16","17"," 18","19""20","21","22","23","24","25","26","27"," 28","29"}; //自定义表int n=1;//行号int num=0; //错误统计数typedef struct Key_word//保留字和特殊符号表结构//int keyNum;char keyWord[MAX];char keySign[MAX];char keyValue[MAX];}Key_word;//初始化保留字表Key_wordKey[MAXSIZE]={{"int","int","-"},{"char","c har","-"},{"float","float","-"},{"void","void","-"},{"const","const","-"},{" for","for","-"},{"if","if","-"},{"else","else","-"},{"then","t hen","-"},{"while","while","-"},{"switch","switch","-"},{"break","break","-"},{"begin","begin","-"},{"end","end","-"},{""{"","",""},{"","id",""},{"","num",""},{"+","+","-"},{"-","-","-"},{"*","*","-"}, {"/","/","-"},{"%","%","-"},{"(","(","-"}, {")",")","-"},{"[","[","-"},{"]","]","-"},{"","",""},{"<","rlop","<"},{">","rlop","> "},{"<=","rlop","<="},{">=","rlop",">="},{"= ","rlop","="},{"!=","rlop","!="},{";",";","-"},{"","",""},{"/=","/=","-"},{"+=","+=","-"},{"-=","-=", "-"},{"*=","*=","-"},{"%=","%=","-"},{"||","or{"&&","and","-"},{"!","not","-"},{"=","=", "-"}};//打开关闭文件int Initscanner(){printf("请输入要输入的文件:\n");scanf("%s",infile);if((in=fopen(infile,"r"))==NULL){printf("cannot open infile!\n");return 0;}if((out=fopen("word.txt","a+"))==NULL) {printf("cannot open outfile!\n");return 0;}return 0;}//写入文件void Output(int n,int m){fputs("(",out);fputs(Key[n].keySign,out);fputs(",",out);if(m==-1)fputs(Key[n].keyValue,out);elsefputs(lownum[m],out);//下标fputs(")",out);}//Isalpha函数:识别保留字和标识符int Isalpha(){int i;for(i=0;i<16;i++)//关键字{if(strcmp(token,Key[i].keyWord)==0){Output(i,-1);return 0;}}//标识符Word[NUM][MAX]for(i=0;i<NUM;i++){if((Word[i][0]!=NULL)&&strcmp(token,Wor d[i])==0){Output(16,i);return 0;}if(Word[i][0]==NULL){strcpy(Word[i],token);Output(16,i);return 0;}}return 0;}int Isnumber()//Isnumber函数:consts[NUM][MAX]{int i;for(i=0;i<NUM;i++){if((consts[i][0]!=NULL)&&strcmp(token,cons ts[i])==0){Output(17,i);return 0;}if(consts[i][0]==NULL){strcpy(consts[i],token);Output(17,i);return 0;}}return 0;}void remove() //扫描指针回退一个字符{fseek(in,-1,SEEK_CUR);}//Isanotation函数:处理除号/和注释void Isanotation() //提示第一个字符已经存为/了{char ch,pre;ch=getc(in);if(ch=='=')// "/="Output(36,-1);else if(ch=='*')// "/*"{ch=getc(in);do{if(feof(in)){num++;printf("\n第(%d)行: 注释错误: /*后面的字符全部当做注释,缺少结束注释*/\n",n);break;}pre=ch;ch=getc(in);}while(pre!='*'||ch!='/');}else// "/"{remove(); //指针回退一个字符Output(21,-1);}}//Isother函数识别其他特殊字符void Isother(){ int i=1;int j=0;char ch;if(token[0]=='<'||token[0]=='>'||token[0]=='!'|| token[0]=='%'){ch=getc(in);if(ch=='=')token[i++]=ch;elseremove(); }else i f(token[0]=='|') {ch=getc(in);if(ch=='|')token[i++]=ch;elseremove();}else if(token[0]=='&') {c h=getc(in);if(ch=='&')token[i++]=ch;elseremove();}token[i]='\0';for(i=18;i<45;i++){if(strcmp(token,Key[i].keyWord)==0){Output(i,-1);break;}}if(i==45){num++;printf("\n第(%d)行: 字符错误: %s字符非法\n",n,token);}}void Scanner(){char ch;int i;ch=getc(in);while(!feof(in)){while(ch==' '||ch=='\t'||ch=='\n') //先统计行数{if(ch=='\n')++n;ch=getc(in);}if(((ch>='a')&&(ch<='z'))||(ch=='_'))//标识符isalpha(ch)单词{i=1;token[0]=ch;ch=getc(in);while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(c h<='9')))//word number{token[i++]=ch;ch=getc(in);}token[i]='\0';Isalpha();}else if((ch>='0')&&(ch<='9'))//整数{i=1;token[0]=ch;ch=getc(in);while(isdigit(ch)){token[i++]=ch;ch=getc(in);}token[i]='\0';Isnumber();}else if(ch=='/')//区分"/" , "/=" , "/*" {token[0]=ch;Isanotation();ch=getc(in);}else //特殊字符{token[0]=ch;Isother();ch=getc(in);}}}void show(){int i;char ch;printf("\n二元式:\n");rewind(out);while(!feof(out)){printf("%c",getc(out));}printf("\n标志符表\n");for(i=0;i<NUM;i++){if(Word[i][0]!=NULL)printf("%d,%s\n",i,Word[i]);}printf("\n常数表\n");for(i=0;i<NUM;i++){if(consts[i][0]!=NULL)printf("%d,%s\n",i,consts[i]);}}void main(){Initscanner();Scanner();printf("\n共有%d个错误\n",num); show();fclose(in);fclose(out);}九、实验结果输入文件void aa( ) begin float rate,circle; rate=3;circle=3.14*rate;/******/end 输出文件(void,-) (id,0) ((,-) (),-) (begin,-) (float,-) (id,1) (id,2) (;,-) (id,1) (rlop,=) (num,0) (;,-) (id,2) (rlop,=) (num,0) (num,1) (*,-) (id,1) (;,-) (end,-)实验1-3 词法分析器实验十、实验总结经过此次实验,了解了程序的词法构词规则和词法分析过程。

相关文档
最新文档