资源描述
.编译原理实验报告组员: 韦廷廷、熊敏、马昊任课老师:吴 清一、 任务概述 本次实验我们要完成的任务主要是实现一个简单语言集的词法、语法和语义分析程序,验证实际编译系统的实现方法。我们组的分工并不是词法分析、语法分析、语义分析每人负责一个,而是先确定每种分析按照哪一种方法实现,然后每个人写出自己的想法,按照自己的想法实验,最后总结到一起,有问题大家一起讨论,共同商量解决的办法。二、系统设计实验采用的实现方法和依据: 语言中的各类单词符号及其分类码表单词符号类别编码类别码的助记符单词值begin1BEGINend2ENDif3IFthen4THENelse5ELSE标识符6ID字母打头的字母数字串无符号常数7UCON机内二进制表示8LT=9LE=10EQ11NE12GT=13GE:=14IS+15PL-16MI*17MU/18DI实验采用的实现方法和依据:文法:E T | E+T | E-T T F | T*F | T/F F i | SLR分析表状态ACTIONGOTO+-*/i#ETF0S4S51231S6S7Acc2R3R3R3S8S9R33R6R6R6R6R6R64S4S510235R8R8R8R8R8R86S4S51137S4S51238S4S5139S4S51410S15S6S711R1R1R1S8S9R112R2R2R2S8S9R213R4R4R4R4R4R414R5R5R5R5R5R515R7R7R7R7R7R7三、系统实现包括必要的框图,各.h和.c文件说明,所有函数功能的说明,数据结构、各种表格、变量等的说明,以及函数调用关系图等1各.h和.c文件说明Cifa.cpp的功能:字符串扫描识别。Table.cpp的功能:存放SLR分析法需要用到的ACTION和GOTO表。Yufa.cpp的功能:引用Cifa.cpp、Table.cpp两个文件进行语法、语义的分析。2函数功能说明词法分析部分函数说明:int lookup /比较是否是关键字 int GetChar /每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch,然后把扫描指示器前推一个字符位置。 int HandleError /报错函数 int EXCUTE /状态转换 int lookup /比较是否是关键字void out/输出函数 void scanner_example /词法分析语法、语义部分函数功能说明:void REPORT_ERROR/报错函数void Accept/语法成功接受int INDEX/获取当前字符串对应的索引void yuyi/语义子程序void INPUT/语法分析程序 数据结构、各种表格、变量等的说明Cifa.cpp中:char *KeyWordTableMAX_KEY_NUMBER=begin,end, if, then, else, KEY_WORD_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;/判断是否结束int tag=0;/判断是否需要调用词法程序四、系统工作过程及运行说明使用操作指南程序使用:在工程里创建一个b.txt文件以识别算数运算表达式五、源程序清单要求有详细注释和实例程序运行结果源程序清单:Cifa.cpp13 / 13.#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# define 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=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 ;int EXCUTE ;int HandleOtherWord return ClassOther; int HandleError printf ; return 0;int lookup /比较是否是关键字 int n=0; while strcmp /*strcmp比较两串是否相同,若相同返回0*/ if !strcmp /*比较token所指向的关键字和保留字表中哪个关键字相符*/ return n+1; /*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/ break; n+; return 0; /*单词不是关键字,而是标识符*/int GetChar char c=a; ifisdigit d=c-0; /字符c与字符0的ascii码差值,返回类型为一个整数 return DIGIT; if return POINT; if return POWER; if return PL; if return MU; return OTHER;void report_error printf;void out1/输出函数 switch case 1:printfn;break; case 2:printfn;break; case 3:printfn;break; case 4:printfn;break; case 5:printfn;break; case 6: printfn,token;break; case 8:printfn,token;break; case 9:printfn,token;break; case 10:printfn,token;break; case 11:printfn,token;break; case 12:printfn,token;break; case 13:printfn,token;break; case 14:printfn,token;break; case 15:printfn,token;break; case 16:printfn,token;break; case 17:printfn,token;break; case 18:printfn,token;break; case 19:printfn;break; case 20:printf, n;break; default: report_error;break; int outswitchcase 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 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 /文件扫描器 int i, c; ch=fgetc;if scanner_example ; else if isalpha /判断是否是英文字母 TOKEN0=ch; ch=fgetc; i=1; while isalnum TOKENi=ch; i+; ch=fgetc ; TOKENi=0; fseek; /* retract*/ c=lookup ; if /printf; result=out; /标识符 else if start=1; out1 ; if end=1;out1; else if isdigit|ch=. /判断是否是数字或. i=0; /TOKENi=ch; ifisdigit d=ch-0; /字符c与字符0的ascii码差值,返回类型为一个整数 EXCUTE; if EXCUTE; if EXCUTE; if EXCUTE ; if EXCUTE; while TOKENi=ch; i+;ch=fgetc;int c=GetChar; EXCUTE; TOKENi=0; fseek; / printfn,FCON; result=out;else switch /关系运算符 case : ch=fgetc; ifout1; else if out1 ; else fseek ; printf; / out ; break; case =: printf; /out; break; case : ch=fgetc; if printf; /out; else fseek; printf; /out; break;case :ch=fgetc; if printf; /out; break;case +:result=out;break;case -:result=out;break;case *:result=out;break;case /:result=out;break;case :result=out;break;case :result=out;break;case ;:result=out;break;case EOF:break;default:report_error;break;return;int EXCUTE switch case 0:switch 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; CurrentState=EndState; break; case 1:switch case DIGIT: w=w*10+d;break; /CurrentState=1 case POINT: CurrentState=2;break; case POWER: CurrentState=4;break; default: FCON=w;CurrentState=EndState; break; case 2:switch case DIGIT: n+;w=w*10+d;break; case POWER: CurrentState=4;break; default: FCON=w*pow;CurrentState=EndState; break; case 3:switch case DIGIT: n+;w=w*10+d;CurrentState=2;break; default: HandleError;CurrentState=EndState; break; case 4:switch case DIGIT: p=p*10+d;CurrentState=6;break; case MU: e=-1;CurrentState=5;break; case PL: e=1;CurrentState=5;break; default: HandleError;CurrentState=EndState; break; case 5:switch case DIGIT: p=p*10+d;CurrentState=6;break; default: HandleError;CurrentState=EndState; break; case 6:switch case DIGIT: p=p*10+d;break; default: FCON=w*pow;CurrentState=EndState; break; return CurrentState; int cifa CurrentState=0;/初始0状态 scanner_example ; return;.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 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分析表,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,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,0,0,0,27,27,27,27,27,0,27,0,0,0;Yufa.cpp.#include#include#include#include#include#includecifa.cpp#includetable.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 CURRENTSTATE=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_ERRORYes=1;long f1=ftell;char ch=fgetc;fseek;printf;void AcceptYes=1;/printf;int INDEX/获取当前字符串对应的索引int i;switch case E:i=8;return;break;case T:i=9;return;break;case F:i=10;return;break;default: REPORT_ERROR;return; break;void Gen/输出四元式switchcase PL:printfn,i1,i2,t;break;case MI:printfn,i1,i2,t;break;case MU:printfn,i1,i2,t;break;case DI:printfn,i1,i2,t;break;default:break;void yuyi/语义子程序switchcase 1: temp+;/产生临时变量,Gen;e1=temp;break;case 2:temp+;/产生临时变量,TEMPtempGen;e1=temp;break;case 3:e1=t4;break;case 4:temp+;Gen;t4=temp;break;case 5:temp+;Gen;t4=temp;break;case 6:t4=f7;break;case 7:f7=e1;break;case 8:f7=FCON;break;default :printf;break;void Gen2/输出四元式switchcase PL:printfn,&i1,&i2,t;break;case MI:printfn,&i1,&i2,t;break;case MU:printfn,&i1,&i2,t;break;case DI:printfn,&i1,&i2,t;break;default:break;void fuzhi/将数组b赋值给数组avoid yuyi2/语义子程序switchcase 1: temp+;/产生临时变量Gen2;e120=temp;break;case 2:temp+;/产生临时变量,TEMPtempGen2;e120=temp;break;case 3:/e12=t42;strcpy;break;case 4:temp+;Gen2;t420=temp;break;case 5:temp+;Gen2;t420=temp;break;case 6:/t42=f72;strcpy;break;case 7:/f72=e12;strcpy;break;case 8:/f72=TOKEN0;strcpy;break;default :printf;break;void INPUTindex=a;int index2=0;ifif /报错REPORT_ERROR;else if TableCURRENTSTATEindex/移近 i+; Statei=TableCURRENTSTATEindex; CURRENTSTATE=Statei; else /规约tag=1;length=LENGTHTableCURRENTSTATEindex-20; i=i-length;/指针回退 switchcase 1: case 2:case 3:index2=8;break;case 4:case 5:case 6:index2=9;break;case 7:case 8:index2=10;break;default :REPORT_ERROR;break;if /不是标识符yuyi;/规约调用语义子程序elseyuyi2;/规约调用语义子程序CURRENTSTATE=Statei;i+; Statei=TableCURRENTSTATEindex2;CURRENTSTATE=Statei;else Accept;CURRENTSTATE=0;void main int res; State0=0; iffp=fopen=NULL printf; exit; else res=cifa; if/文件以begin开始 do res=cifa;if fseek;/文件指针回退一个*/ do if res=cifa; tag=0; if biaoshifu=1;res=res-20; INPUT; while;/一个语法句子翻译完成 Yes=0;/归零 i=0; cifa;ifend=1;printf; fseek;while; cifa; if printf; /文件结束 else printf; .单独词法识别测试用例及结果截图:测试一:if myid=3e2+100 then x:=y测试二:begin 2.9+3.0e-3end词法、语法、语义成语整合实例程序运行结果截图:正确识别后的程序显示:错误的程序显示:括号不匹配问题六、 体会和讨论 经过本次的实验,我们对编译原理中的词法分析、语法分析和语义分析有了基本的认识。虽然只有简短的三个小程序,但是,只有在理解的基础上才能写出好的程序来。所以,我们觉得本次的实验重点在于理解编译的过程。由于采用的是小组作业的形式,通过组内同学的互帮互助,理解起来也轻松了很多。实验由于有了大家的辛苦和努力,才有了最后的结果。最后的遗憾是我们组的实验没有将字符和数字同时输入进行语义分析出来,如果有时间,我们会继续努力完善的。
展开阅读全文