《2007计软编译基础学习知识原理实验.doc》由会员分享,可在线阅读,更多相关《2007计软编译基础学习知识原理实验.doc(37页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、!-编译原理实验书 2010年11月 实验目录: 实验1:词法分析程序(3学时,第12周)2实验2:语法分析-递归子程序法(3学时,第13周)11实验3:语法分析-预测分析法(选做)27实验4:语义分析和代码生成(12学时,第1417周)37 适用专业及实验总学时:2007级计算机科学与技术专业(软件方向),18学时。 任课教师: 黄玲 E-mail: 恭喜你!你将进入非常重要的专业课程的实践。编译原理的知识影响到专业人员的素质,除编译程序外有大量专业工作与编译技术相关 。你现在需要通过脚踏实地的实践学习(很辛苦的!),把自己的专业水平提高一个层次。你需要在实验课前自己阅读程序代码,在实验课
2、中调试程序,实验课后完成实验报告(每一个实验上交一份实验报告),实验报告必须阐述清楚你的所做的工作,内容包含修改思路、关键修改代码、运行结果、对运行结果的评价、进一步改进的建议。最重要的是,通过实践你可以获得专业的能力和自信。加油!实验1:词法分析程序(3学时,第12周)一、实验目的和内容:1实验目的:通过词法分析程序,了解词法分析的过程。2实验内容:用C实现对Pascal的子集程序设计语言的词法识别。3实验要求:要求修改文法和程序,增加浮点数处理功能。4. 实验环境是Windows操作系统、Visual C+开发环境。二、未增加浮点数处理的原设计:1 程序设计语言的描述:.PROGRAM ;
3、CONST ,;标识符=无符号整数VAR ,;标识符,标识符:INTEGER|LONG;PROCEDURE 标识符;|PROCEDURE 标识符(标识符:);|标识符:=IF THEN WHILE DO 标识符|标识符()READ (标识符,标识符)WRITE (,)BEGIN ;END|ODD +|-标识符|无符号整数|()+|-*|/=|=其中: 用左右尖括号括起来的符号串表示非终结符 定义为 表示该语法成分可以重复0n次 表示方括号内为可选项,即0或1次2 程序设计语言单词的内部编码:(35个终结符) 内码单词内码单词内码单词内码单词1PROGRAM2CONST3VAR4INTEGER5
4、LONG6PROCEDURE7IF8THEN9WHILE10DO11READ12WRITE13BEGIN14END15ODD16+17-18*19/20=21222325=26.27,28;29:30:=31(32)33无符号整数34标识符35# 3下面是一个词法分析程序,该程序能够将源程序,也就是相应字符流转换成内码,并输出到文件。程序的执行需要提供两个参数,第一个参数是源程序文件名,第二个参数是存放分析结果的文件名,第二个参数可以省略,可由程序自动生成。Vc+6程序参数的设置方法:菜单project下子菜单settings中的debug选项卡下program arguments对话框中,输
5、入参数。如采用Visual Studio 2008开发环境,构建控制台应用程序,参数设置:项目属性-(活动debug模式)配置属性-调试-命令参数,同时工作目录为当前工程下debug 。 #include #include #include #include #define lenth1 15 /保留字表的长度#define lenth2 17 /运算符界符表长度struct char name21;int type;int addr;indent1000; /符号表struct stchar name21;int code;sym; /当前单词FILE *f1,*f2;int line=1,
6、row=1,val; /行号、列号、数字串的值char ch= ; /当前字符int lenth3=0; /符号表中实际的标识符个数void getsym();char getchr();void error(int);main(int argc,char *argv) char ft12,*fc; if (f1=fopen(argv1,r)=NULL) /打开源程序文件 printf(can not open file.n);exit(0); if (argc=2) /如果没有提供第二个参数 strcpy(ft,argv1);if (fc=strchr(ft,.)!=NULL) /如果第一个
7、参数即源文件名,有后缀 .xxxstrcpy(fc,.mid); /结果文件名:源文件名非后缀部分.midelsestrcat(ft,.mid); /结果文件名:源文件名.mid else strcpy(ft,argv2); if (f2=fopen(ft,w)=NULL) /打开结果文件 printf(cannot open file 2n); exit(0); while (!feof(f1) /只要没有遇到源文件的结尾,继续循环。 getsym(); /获取一个单词放到sym printf(%s %dn,sym.name,sym.code); /显示当前单词的名字及其内码 fprintf
8、(f2,%s %dn,sym.name,sym.code);/向输出文件写入:单词名字 单词内码 fclose(f1); fclose(f2);void getsym()static char alenth110=PROGRAM,CONST,VAR,INTEGER,LONG,PROCEDURE,IF,THEN,WHILE,DO,READ,WRITE,BEGIN,END,ODD;/保留字表static char dlenth23=+,-,*,/,=,=,.,;,:,:=,(,); /运算符界符表char str21;int i,n;while (isspace(ch) ch=getchr();i
9、f (isalpha(ch) /如果当前字符是字母,则后面几行代码就是识别标识符的自动机的实现n=0; while (isalpha(ch) | isalnum(ch) /当前字符是字母或者数字,继续循环 if (isalpha(ch) ch=tolower(ch); if (n20) strn+=ch; /构造字符串 ch=getchr(); /从文件中读取下一个字符 strn=0; for (i=0;ilenth1;i+) /检查当前符号串是否保留字 if (!strcmp(str,ai) break; /如果字符串已经登记在保留字表,中断循环 if (ilenth1) /如果该字符串是保
10、留字,将当前单词写入sym strcpy(sym.name,ai);sym.code=i+1; else /该单词不是保留字,而是标识符 for(i=0;ilenth3;i+) /在符号表里检查是否已经登记过该标识符 if (!strcmp(str,indenti.name) break; /如果登记过,中断循环 if (i=lenth3) strcpy(indenti.name,str);/如果没有登记过该标识符,登记它到符号表。lenth3+; strcpy(sym.name,indenti.name); /当前标识符写入sym sym.code=34; else if (isalnum(
11、ch) /如果当前字符是数字,则后面就是识别数字串的自动机的实现 val=0;n=0; while (isalnum(ch) val=val*10+ch-0; sym.namen+=ch; ch=getchr();sym.namen=0;sym.code=33; else /当前字符是运算符或者界符 if (ch=+ | ch=- | ch=* | ch=/ | ch= | ch=. | ch=, | ch=; | ch=( | ch=) str0=ch;str1=0;ch=getchr(); /从文件中读入一个字符 for (i=0;ilenth2;i+) /在运算符界符表查询,是否有此ch
12、字符if (!strcmp(str,di) strcpy(sym.name,str); /有, sym.code=i+16; else /处理符号 = : := n=0;if (ch= | ch=:) strn+=ch; if (ch=getchr()=) / =或:= strn+=ch; ch=getchr(); else if (ch=) / =或 strn+=ch; ch=getchr(); else if (ch=-1) strcpy(sym.name,); sym.code=35; /#/else error(1); strn=0; /str为一个完整的单词 for (i=0;ile
13、nth2;i+) /查运算符界符表,看是否有此符号串str if (!strcmp(str,di) strcpy(sym.name,str); sym.code=i+16; char getchr() char ch=fgetc(f1); if (ch=n) row=1; line+; else if (ch!= & ch!=t) row+; return (ch);void error(int n) printf(%d error happens.n,n); exit(0);4. 词法分析程序 getsym()流程图读入下一个字符到chch的符号是空格? Y Nch的符号是字母? 标识符或者
14、保留字 Y ch的符号是字母或数字? N N Ych的符号是字母? N Y将ch的字母变为小写字母将ch的符号加入到字符数组str尾读入下一个符号到ch在str尾增加0,构建一个字符串在保留字表a中查找str的位置ii或者:吗?构造str并读入符号到ch Y ch是=吗? N N 或: Y =或:=构造str并读入符号到ch ch是吗? N Y =或构造str并读入符号到ch登记#到sym,内码35 在str末尾加0,构建字符串在运算符界符表d查str位置i。查到?单词str?登记str到sym,内码i+16 Y N结束三、增加浮点数功能时,可以使用下面的源程序作为词法分析程序的输入(当然,你
15、也可以自己编写各种源程序,以便测试程序。)词法分析程序输出词法分析结果。PROGRAM mypascal;CONST UNIT=100;VAR x:INTEGER,y:FLOAT;PROCEDURE subproc(i:INTEGER); BEGIN x:=i; END; BEGIN subproc(20); x:=x+UNIT; y=y*x+23.45;END.实验2:语法分析-递归子程序法(3学时,第13周)一、实验的目的和内容:1目的:通过完成语法分析程序,了解语法分析的过程和作用。2实验内容:用递归子程序法实现对Pascal的子集程序设计语言的分析程序。分析程序对源程序的内码流进行分析
16、,如果为文法定义的句子,则输出“是”,否则输出“否”。3 实验要求:要求修改文法和程序,增加浮点数处理功能。二、未增加浮点数处理功能的原设计:1改写实验一的未增加浮点数处理的文法,使其是LL(1)文法。改变后文法如下:.PROGRAM ;CONST ;|标识符=无符号整数, |VAR |标识符:;, 标识符 | |INTEGER|LONG; |PROCEDURE 标识符;(标识符:) |; |标识符:=|()|IF THEN WHILE DO READ (标识符)WRITE (), |BEGIN END; |ODD +|-|标识符|无符号整数|()+|-*|/=|=2非终结符和函数名对照表:(
17、34个非终结符) 非终结符函数名非终结符函数名programprogheadblockconsexplconsdefivarexplconssuffvardefivarsuffprocdefitypilprocedhprocsuffassiprosentencesuffixifsentreadwhilsentidsuffwritecompsentexprsuffsentsuffconditiotermsuffexpresstermfactsuffargumentfactoraAddopermuloperrespoper3下面是一个递归子程序语法分析程序,程序的执行需要提供一个参数:源程序文件名
18、。该程序判断给定的源程序语法是否正确。#include #include #include #include #define PROGRAM 1 /从这里开始宏定义终结符内码,为的是增加程序的易读性#define CONST 2#define VAR 3 #define INTEGER 4#define LONG 5#define PROCEDURE 6#define IF 7#define THEN 8#define WHILE 9#define DO 10#define READ 11#define WRITE 12#define BEGIN 13#define END 14#define
19、 ODD 15#define ADD 16#define SUB 17#define MUL 18#define DIV 19#define EQU 20#define NEQ 21#define LES 22#define LEQ 23#define LAG 24#define GEQ 25#define DOT 26#define COM 27#define SEM 28#define COL 29#define ASS 30#define LBR 31#define RBR 32#define INT 33#define ID 34 /标识符内码#define EIN 35#define
20、 lenth1 15 /保留字表长度#define lenth2 17 /运算符界符长度struct char name21;int type;int addr;indent 1000; /符号表struct stchar name21;int code;sym; /当前单词int lenth=0;FILE* f1;int line=0,row=0,val;void getsym();char getchr();void error(int);void program();void proghead();void block();void consexpl();void consdefi();
21、void varexpl();void conssuff();void vardefi();void varsuff();void procdefi();void typeil();void procedh();void procsuff();void assipro();void sentence();void suffix();void ifsent();void read();void whilsent();void idsuff();void write();void compsent();void exprsuff();void sentsuff();void condition()
22、;void termsuff();void express();void term();void factsuff();void factor();void addoper();void muloper();void respoper();void argument();char ch= ; /当前字符int lenth3=0; /符号表中实际标识符个数void main(int argc,char* argv) if (f1=fopen(argv1,r)=NULL) /打开源程序文件 printf(cannot open filen); exit(0); getsym(); /获取第一个单词
23、 program(); /程序的语法分析 printf(the program is rightn);/源程序正确 fclose(f1);void program() /非终结符的分析程序:-. proghead(); /非终结符的分析程序 block(); /非终结符的分析程序 if (sym.code=DOT) /DOT为.的内码表示,见文件首的宏定义。如果当前单词是. getsym(); /读取下一个单词到sym else error(2);void proghead() /非终结符的分析程序:-PROGRAM 标识符;if(sym.code=PROGRAM) getsym(); if
24、(sym.code=ID) getsym(); if (sym.code=SEM) getsym(); else error(5); else error(4); elseerror(3);void block() /非终结符的分析程序 consexpl(); varexpl(); procdefi(); compsent();void consexpl() /非终结符CONST ;|if (sym.code=CONST) /如果当前单词不是CONST,则是分支,什么事情都不做。 / CONST ; getsym(); consdefi(); conssuff(); if (sym.code=
25、SEM) getsym(); else error(6);void consdefi() /非终结符if (sym.code=ID) getsym(); if (sym.code=EQU) getsym();if (sym.code=INT)getsym();elseerror(9); else error(8); elseerror(7);void conssuff() /非终结符,| if (sym.code=COM) getsym(); consdefi(); conssuff();/* if (sym.code=SEM) getsym(); else error(10); */void
26、 varexpl() /变量说明部分 if (sym.code=VAR) getsym();vardefi();varsuff(); void vardefi() /非终结符if (sym.code=ID) getsym(); idsuff(); if (sym.code=COL) getsym(); typeil(); if (sym.code=SEM) getsym(); else error(12); else error(11);void varsuff() /非终结符if (sym.code=ID) vardefi(); varsuff();void typeil() /非终结符if
27、 (sym.code=INTEGER|sym.code=LONG) getsym();else error(13);void procdefi() /非终结符if (sym.code=PROCEDURE) procedh(); block(); if (sym.code=SEM) getsym(); procsuff(); else error(14);void procedh() /非终结符if (sym.code=PROCEDURE) getsym(); if (sym.code=ID) getsym(); argument(); if (sym.code=SEM) getsym(); else error(16); else error(15);void argument() /非终结符参