1、编译原理实验报告组员: 韦廷廷(112455)、熊敏(112456) 、马昊(113042)任课老师:吴 清一、 任务概述本次实验我们要完成的任务主要是实现一个简单语言集的词法、语法和语义分析程序,验证实际编译系统的实现方法。我们组的分工并不是词法分析、语法分析、语义分析每人负责一个,而是先确定每种分析按照哪一种方法实现,然后每个人写出自己的想法,按照自己的想法实验,最后总结到一起,有问题大家一起讨论,共同商量解决的办法。二、系统设计实验采用的实现方法和依据:语言中的各类单词符号及其分类码表单词符号 类别编码 类别码的助记符 单词值begin 1 BEGINend 2 ENDif 3 IFth
2、en 4 THENelse 5 ELSE标识符 6 ID 字母打头的字母数字串无符号常数 7 UCON 机内二进制表示11 NE 12 GT= 13 GE:= 14 IS+ 15 PL- 16 MI* 17 MU/ 18 DI实验采用的实现方法和依据:文法:E T | E+T | E-T T F | T*F | T/F F i | (E)SLR(1)分析表ACTION GOTO状态 ( ) + - * / i # E T F0 S4 S5 1 2 31 S6 S7 Acc2 R3 R3 R3 S8 S9 R33 R6 R6 R6 R6 R6 R64 S4 S5 10 2 35 R8 R8 R8
3、 R8 R8 R86 S4 S5 11 37 S4 S5 12 38 S4 S5 139 S4 S5 1410 S15 S6 S711 R1 R1 R1 S8 S9 R112 R2 R2 R2 S8 S9 R213 R4 R4 R4 R4 R4 R414 R5 R5 R5 R5 R5 R515 R7 R7 R7 R7 R7 R7三、系统实现(包括必要的框图,各.h 和.c 文件说明,所有函数功能的说明,数据结构、各种表格、变量等的说明,以及函数调用关系图等)(1 )各.h 和.c 文件说明Cifa.cpp 的功能:字符串扫描识别。Table.cpp 的功能:存放 SLR 分析法需要用到的 AC
4、TION 和 GOTO 表。Yufa.cpp 的功能:引用 Cifa.cpp、Table.cpp 两个文件进行语法、语义的分析。(2 )函数功能说明词法分析部分函数说明:int lookup (char *token) /比较是否是关键字int GetChar(char ch) /每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量 ch,然后把扫描指示器前推一个字符位置。int HandleError (void)/报错函数int EXCUTE (int state, int symbol)/状态转换int lookup (char *token) /比较是否是关键字void out
5、(int a,char *token)/输出函数void scanner_example (FILE *fp)/词法分析语法、语义部分函数功能说明:void REPORT_ERROR()/报错函数void Accept()/语法成功接受int INDEX(char a)/获取当前字符串对应的索引void yuyi(int n)/语义子程序void INPUT(int a)/语法分析程序(2) 数据结构、各种表格、变量等的说明Cifa.cpp 中:char *KeyWordTableMAX_KEY_NUMBER=“begin“,“end“, “if“, “then“, “else“, KEY_W
6、ORD_END;/数组指针关键字int w,n,p,e,d;/w 尾数累加器, n 小数位数计数器,p 指数累加器,e 指数符号标记,int Class;/标识单词类型Table.cpp#define MAXROW 16 /行数#define MAXCOL 11 /列数int TableMAXROWMAXCOLYufa.cpp 中#define NUMBER 9/表达式的个数int StateMAXState;/状态栈int CURRENTSTATE=0;/标识当前状态int LENGTHNUMBER=1,3,3,1,3,3,1,3,1;/表达式右边的长度int Yes=0;/判断是否结束in
7、t tag=0;/判断是否需要调用词法程序四、系统工作过程及运行说明(使用操作指南)程序使用:在工程里创建一个 b.txt 文件以识别算数运算表达式五、源程序清单(要求有详细注释)和实例程序运行结果源程序清单:Cifa.cpp#include#include#include#include#include#define DIGIT 1#define POINT 2#define OTHER 3#define POWER 4# define ID 6# define UCON 7# define LT 8# define LE 9# define EQ 10# define NE 11# def
8、ine GT 12# define GE 13# define IS 14# define PL 15 /+# define MI 16 /-# define MU 17# define DI 18#define zuokuohao 19#define youkuohao 20#define jin 21#define ClassOther 200#define EndState -1#define MAX_KEY_NUMBER 20 /*关键字的数量*/#define KEY_WORD_END “END“ /*关键字结束标记*/char *KeyWordTableMAX_KEY_NUMBER
9、=“begin“,“end“, “if“, “then“, “else“, KEY_WORD_END;/数组指针char TOKEN20;char ch;int w,n,p,e,d;/w 尾数累加器,n 小数位数计数器,p 指数累加器,e 指数符号标记,int Class;/标识单词类型int ICON;double FCON;static int CurrentState=0;int result;int start=0;/指示程序的开始int end=0;/指示程序的结束int GetChar (void);int EXCUTE (int,int);int HandleOtherWord
10、(void)return ClassOther;int HandleError (void)printf (“Error!n“); return 0;int lookup (char *token) /比较是否是关键字int n=0;while (strcmp(KeyWordTablen, KEY_WORD_END) /*strcmp 比较两串是否相同,若相同返回 0*/if (!strcmp(KeyWordTablen, token) /*比较token 所指向的关键字和保留字表中哪个关键字相符*/return n+1; /*根据单词分类码表 I,设置正确的关键字类别码,并返回此类别码的值*
11、/break;n+;return 0; /*单词不是关键字,而是标识符 */int GetChar (char a)char c=a;if(isdigit(c)d=c-0; /字符 c 与字符 0 的 ascii 码差值,返回类型为一个整数return DIGIT;if (c=.) return POINT;if (c=E|c=e) return POWER;if (c=+) return PL;if (c=-) return MU;return OTHER;void report_error( )printf(“错误n“);void out1(int a,char *token)/输出函数s
12、witch (a)case 1:printf(“(BEGIN, )n“);break;case 2:printf(“(END, )n“);break;case 3:printf(“(IF, )n“);break;case 4:printf(“(THEN, )n“);break;case 5:printf(“(ELSE, )n“);break;case 6: printf(“(ID,%s)n“,token);break;case 8:printf(“(LT,%s)n“,token);break;case 9:printf(“(LE,%s)n“,token);break;case 10:print
13、f(“(EQ,%s)n“,token);break;case 11:printf(“(NE,%s)n“,token);break;case 12:printf(“(GT,%s)n“,token);break;case 13:printf(“(GE,%s)n“,token);break;case 14:printf(“(IS,%s)n“,token);break;case 15:printf(“(PL,%s)n“,token);break;case 16:printf(“(MI,%s)n“,token);break;case 17:printf(“(MU,%s)n“,token);break;c
14、ase 18:printf(“(DI,%s)n“,token);break;case 19:printf(“(, )n“);break;case 20:printf(“(), )n“);break;default: report_error( );break;int out(int a)switch(a)case 7:return 6;break;/常量case 15:return 2;break;/+case 16:return 3;break;case 17:return 4;break;case 18:return 5;break;case 19:return 0;break;case
15、20:return 1;break;case 21:return 7;break;case 22:return 100;break;/判断是否是空格或换行case 26: return 26;break;/标识符default:return 001;report_error();break;void scanner_example (FILE *fp)/文件扫描器int i, c;ch=fgetc(fp);if(ch= |ch=n) scanner_example (fp);else if (isalpha (ch) /判断是否是英文字母TOKEN0=ch; ch=fgetc(fp);i=1;
16、while (isalnum (ch)TOKENi=ch; i+;ch=fgetc (fp);TOKENi=0;fseek(fp,-1,1); /* retract*/c=lookup (TOKEN);if (c=0) /printf(“算术表达式不需要 n“);result=out(26); /标识符else if(c=1)start=1;out1 (c,“ “);if (c=2)end=1;out1(c,“ “);else if (isdigit(ch)|ch=.) /判断是否是数字或“.”i=0;/TOKENi=ch;if(isdigit(ch)d=ch-0; /字符 c 与字符 0 的
17、 ascii 码差值,返回类型为一个整数EXCUTE(CurrentState,DIGIT);if (ch=.) EXCUTE(CurrentState,POINT);if (ch=E|ch=e) EXCUTE(CurrentState,POWER);if (ch=+)EXCUTE(CurrentState,PL) ;if (ch=-) EXCUTE(CurrentState,MU);while(CurrentState!=EndState)TOKENi=ch; i+;ch=fgetc(fp);int c=GetChar(ch);EXCUTE(CurrentState,c);TOKENi=0;
18、fseek(fp,-1,1);/ printf(“(UCON,%g)n“,FCON);result=out(UCON);else switch(ch) /关系运算符case ) out1 (NE,“ “);elsefseek (fp,-1,1);printf(“算术表达式不需要n“);/ out (UCON);break;case =: printf(“算术表达式不需要n“);/out(EQ, “ “); break;case : ch=fgetc(fp);if(ch=) printf(“算术表达式不需要n“);/out(GE,“ “);elsefseek(fp,-1,1);printf(“算
19、术表达式不需要n“);/out(GT,“ “);break;case :ch=fgetc(fp);if(ch=) printf(“算术表达式不需要 n“);/out(IS,“ “);break;case +:result=out(PL);break;case -:result=out(MI);break;case *:result=out(MU);break;case /:result=out(DI);break;case (:result=out(zuokuohao);break;case ):result=out(youkuohao);break;case ;:result=out(jin
20、);break;case EOF:break;default:report_error();break;return;int EXCUTE (int state, int symbol)switch (state)case 0:switch (symbol)case DIGIT: n=0;p=0;e=1;w=d;CurrentState=1;Class=UCON;break;case POINT: w=0;n=0;p=0;e=1;CurrentState=3;Class=UCON;break;default: HandleOtherWord( );Class=ClassOther;Curren
21、tState=EndState;break;case 1:switch (symbol)case DIGIT: w=w*10+d;break; /CurrentState=1case POINT: CurrentState=2;break;case POWER: CurrentState=4;break;default: FCON=w;CurrentState=EndState;break;case 2:switch (symbol)case DIGIT: n+;w=w*10+d;break;case POWER: CurrentState=4;break;default: FCON=w*po
22、w(10,e*p-n);CurrentState=EndState;break;case 3:switch (symbol)case DIGIT: n+;w=w*10+d;CurrentState=2;break;default: HandleError( );CurrentState=EndState;break;case 4:switch (symbol)case DIGIT: p=p*10+d;CurrentState=6;break;case MU: e=-1;CurrentState=5;break;case PL: e=1;CurrentState=5;break;default:
23、 HandleError( );CurrentState=EndState;break;case 5:switch (symbol)case DIGIT: p=p*10+d;CurrentState=6;break;default: HandleError( );CurrentState=EndState;break;case 6:switch (symbol)case DIGIT: p=p*10+d;break;default: FCON=w*pow(10,e*p-n);CurrentState=EndState;break;return CurrentState;int cifa(FILE
24、 *fp)CurrentState=0;/初始 0 状态scanner_example (fp) ;return(result);Table.cpp#include#include#include#include#include#define MAXROW 16 /行数#define MAXCOL 11 /列数#define S1 1#define S2 2#define S3 3#define S4 4#define S5 5#define S6 6#define S7 7#define S8 8#define S9 9#define S10 10#define S11 11#define
25、S12 12#define S13 13#define S14 14#define S15 15#define R1 21#define R2 22#define R3 23#define R4 24#define R5 25#define R6 26#define R7 27#define R8 28#define acc 100/SLR(1)分析表, 2130 表示规约,120 表示移近,0 报错int TableMAXROWMAXCOL=S4,0,0,0,0,0,S5,0,S1,S2,S3,0,0,S6,S7,0,0,0,acc,0,0,0,0,23,23,23,8,9,0,23,0,0
26、,0,0,26,26,26,26,26,0,26,0,0,0,4,0,0,0,0,0,5,0,10,2,3,0,28,28,28,28,28,0,28,0,0,0,4,0,0,0,0,0,5,0,0,11,3,4,0,0,0,0,0,5,0,0,12,3,4,0,0,0,0,0,5,0,0,0,13,4,0,0,0,0,0,5,0,0,0,14,0,15,6,7,0,0,0,0,0,0,0,0,21,21,21,8,9,0,21,0,0,0,0,22,22,22,8,9,0,22,0,0,0,0,24,24,24,24,24,0,24,0,0,0,0,25,25,25,25,25,0,25,0
27、,0,0,0,27,27,27,27,27,0,27,0,0,0;Yufa.cpp#include#include#include#include#include#include“cifa.cpp“#include“table.cpp“# define PL 15 /+# define MI 16 /-# define MU 17# define DI 18#define acc 100#define MAXState 20#define NUMBER 9/表达式的个数#define MAXTEMP 10/最多临时变量的个数int StateMAXState;/状态栈int i=0;int C
28、URRENTSTATE=0;/标识当前状态int LENGTHNUMBER=1,3,3,1,3,3,1,3,1;/表达式右边的长度int length;int index;/索引int Yes=0;/判断是否结束int tag=0;/判断是否需要调用词法程序/extern char * cifa();double e1,t4,f7;/整形char e1220,t4220,f7220;/字符型int TEMPMAXTEMP;int temp=0;int biaoshifu=0;FILE * fp;void REPORT_ERROR()Yes=1;long f1=ftell(fp);char ch
29、=fgetc(fp);fseek(fp,-1,1);printf(“语法错误,第%d 个字符%C处n“,f1,ch);void Accept()Yes=1;/printf(“语法分析成功n“);int INDEX(char a)/获取当前字符串对应的索引int i;switch (a)case E:i=8;return(i);break;case T:i=9;return(i);break;case F:i=10;return(i);break;default: REPORT_ERROR();return(0);break;void Gen(int a,double i1,double i2,
30、int t)/输出四元式switch(a)case PL:printf(“(+,%g,%g,%d)n“,i1,i2,t);break;case MI:printf(“(-,%g,%g,%d)n“,i1,i2,t);break;case MU:printf(“(*,%g,%g,%d)n“,i1,i2,t);break;case DI:printf(“(/,%g,%g,%d)n“,i1,i2,t);break;default:break;void yuyi(int n)/语义子程序switch(n)case 1: temp+;/产生临时变量,Gen(PL,e1,t4,temp);e1=temp;b
31、reak;case 2:temp+;/产生临时变量,TEMPtempGen(MI,e1,t4,temp);e1=temp;break;case 3:e1=t4;break;case 4:temp+;Gen(MU,t4,f7,temp);t4=temp;break;case 5:temp+;Gen(DI,t4,f7,temp);t4=temp;break;case 6:t4=f7;break;case 7:f7=e1;break;case 8:f7=FCON;break;default :printf(“errorn“);break;void Gen2(int a,char *i1,char *
32、i2,int t)/输出四元式switch(a)case PL:printf(“(+,%s,%s,%d)n“,break;case MI:printf(“(-,%s,%s,%d)n“,break;case MU:printf(“(*,%s,%s,%d)n“,break;case DI:printf(“(/,%s,%s,%d)n“,break;default:break;void fuzhi(char *a,char *b)/将数组 b 赋值给数组avoid yuyi2(int n)/语义子程序switch(n)case 1: temp+;/产生临时变量Gen2(PL,e12,t42,temp)
33、;e120=temp;break;case 2:temp+;/产生临时变量,TEMPtempGen2(MI,e12,t42,temp);e120=temp;break;case 3:/e12=t42;strcpy(e12,t42);break;case 4:temp+;Gen2(MU,t42,f72,temp);t420=temp;break;case 5:temp+;Gen2(DI,t42,f72,temp);t420=temp;break;case 6:/t42=f72;strcpy(t42,f72);break;case 7:/f72=e12;strcpy(f72,e12);break;
34、case 8:/f72=TOKEN0;strcpy(f72,TOKEN);break;default :printf(“errorn“);break;void INPUT(int a)index=a;int index2=0;if(TableCURRENTSTATEindex!=acc)if (TableCURRENTSTATEindex=0)/报错REPORT_ERROR();else if (TableCURRENTSTATEindex=3e2+100 then x:=y 测试二:begin 2.9+3.0e-3 end词法、语法、语义成语整合实例程序运行结果截图:正确识别后的程序显示:错误的程序显示:(括号不匹配问题)6、 体会和讨论经过本次的实验,我们对编译原理中的词法分析、语法分析和语义分析有了基本的认识。虽然只有简短的三个小程序,但是,只有在理解的基础上才能写出好的程序来。所以,我们觉得本次的实验重点在于理解编译的过程。由于采用的是小组作业的形式,通过组内同学的互帮互助,理解起来也轻松了很多。实验由于有了大家的辛苦和努力,才有了最后的结果。最后的遗憾是我们组的实验没有将字符和数字同时输入进行语义分析出来,如果有时间,我们会继续努力完善的。