您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页PL0编译原理课程设计(3109006080何路生)

PL0编译原理课程设计(3109006080何路生)

来源:意榕旅游网


课 程 设 计

课程名称___ 编译原理______ __ 题目名称__编译原理课程设计__ _ 学生学院__ 计算机学院_________ 专业班级_ 09级计科5班 _ 学 号 3109006080 学生姓名____ 何路生___________ 指导教师_______张巍____________

2011 年 12 月29 日

一.课程设计目的

在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达到进一步了解程序编译过程的基本原理和基本实现方法的目的。

二.课程设计要求 课内实验:

对PL/0作以下修改扩充:

(1)增加单词:保留字 ELSE,FOR,STEP,UNTIL,RETURN 运算符 +=,-=,++,--,∧,∨,┓ (2)修改单词:不等号# 改为 <>

(3)增加条件语句的ELSE子句,要求:写出相关文法,语法图,语义规则。

课程设计:

基本内容(成绩范围:“中”、“及格”或“不及格”)

(1)扩充赋值运算:+= 和 -= (2)扩充语句(Pascal的FOR语句):

FOR <变量>:=<表达式> STEP <表达式>UNTIL <表达式> DO <语句> (3)增加运算:++ 和 --。

选做内容(成绩评定范围扩大到:“优”和“良”)

(1)增加类型:① 字符类型; ② 实数类型。 (2)扩充函数:① 有返回值和返回语句;② 有参数函数。 (3)增加一维数组类型(可增加指令)。 (4)其他典型语言设施。

三.课程设计环境与工具

(1)计算机及操作系统:PC机,Windows7 (2)实现工具:C++Builder6 (3)教学型编译程序:PL/0

四.结构设计说明

a) PL/0编译程序的结构图

Pl0 源 程 序 表格管理程序词法分析程序 语法分析程序 代码生产程序 出错处理程序b) PL/0编译程序的过程或函数的功能表

1、 void Error(int n) :错误处理,打印出错位置和错误编码 2、 void GetCh():漏掉空格,读取一个字符 3、 void GetSym():词法分析,读取一个单词

4、 void GEN(FCT X, int Y, int Z):生成目标代码,并送入目标程序区 5、 void TEST(SYMSET S1, SYMSET S2, int N):测试当前单词符号是否合法 6、 void ENTER(OBJECTS K, int LEV, int &TX, int &DX):登录名字表 7、 int POSITION(ALFA ID, int TX):查找标识符在名字表中的位置 8、void ConstDeclaration(int LEV,int &TX,int &DX):常量说明处理 9、 void VarDeclaration(int LEV,int &TX,int &DX):变量说明处理 10、void CharDeclaration(int LEV,int &TX,int &DX):字符说明处理 11、void RealDeclaration(int LEV,int &TX,int &DX):实数说明处理 12、void ListCode(int CX0):列出目标代码清单

13、void FACTOR(SYMSET FSYS, int LEV, int &TX) :因子处理 14、void TERM(SYMSET FSYS, int LEV, int &TX) :项处理

15、void EXPRESSION(SYMSET FSYS, int LEV, int &TX):表达式处理 16、void CONDITION(SYMSET FSYS,int LEV,int &TX) :条件处理 17、void STATEMENT(SYMSET FSYS,int LEV,int &TX) :语句部分处理 18、void Block(int LEV, int TX, SYMSET FSYS) :分程序分析处理过程 19、int BASE(int L,int B,int S[]):通过静态链求出数据区的基地址 20、void Interpret() :对目标代码的解释执行程序

目 标 程 序 21、void __fastcall TForm1::ButtonRunClick(TObject *Sender):进行编译,RUN

c) PL/0编译程序的总体流程图

启动 置初值 调用getsym取单词 调用block过程 N 是否为源程序结束符 出错 Y 源程序是否有错误 Y 打印错误 N 调用解释过程interpret解释执行目标执行目标程序 结束 d) 词法分析

词法分析是编译的第一个阶段,它的主要任务是从左向右逐个字符地对源程序进行扫描,产生一个个单词序列用于语法分析。PL/0词法分析程序GETSYM的功能是为语法分析提供单词用的,是语法分析的基础,把输入的字符串形式的源程序分割成一个个单词符号。经过词法分析程序分析出来的单词,对语言固有的单词只给出类别存放在全程变量SYM中,而对用户定义的单词(标识符或常数)既给出类别又给值,其类别放在SYM中,值放在全程变量ID或全程变量NUM中,全部单词种类由编译程序定义的纯量类型SYMBOL给出,称为语法词汇表。

词法分析程序GETSYM将完成下列任务:

(1)滤空格 (2)识别保留字 (3)识别标识符 (4)拼数 (5)拼复合词 (6)输出源程序 e) 语法分析

PL/0编译程序的语法分析采用了自顶向下的递归的子程序法。语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。语法分析主要由分程序分析过程(BLOCK)、常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。这些过程在结构上构成一个嵌套的层次结构。 f) 语义分析

PL/0 的语义分析主要进行以下检查:

(1) 是否存在标识符先引用未声明的情况; (2) 是否存在己声明的标识符的错误引用; (3) 是否存在一般标识符的多重声明。 g) 中间代码生成

h) 语法错误处理

PL/0编译程序对语法错误的处理采用两种办法:

(1)对于一些易于校正的错误,如丢了逗号、分号等,指出出错的位置,加以校正,继续进行分析。 (2)对于难于校正的错误,给出错误的位置与性质,跳过后面一些单词,直到下一个可以进行正常语法分析的语法单位。 错误类型如下

0 过程开始部分说明不正确 1 常数说明中\"=\"写成\":=\"

2 常数说明中\"=\"后应为整数或实数或字符

3 常数说明中的标识符后应是\"=\"

4 const, var, procedure后应为标识符 5 漏掉了\或\";\"

6 过程说明后的符号不正确(应该是语句开始符,或过程定义符) 7 应是语句开始符

8 程序体内语句部分的后跟符不正确 9 程序结尾丢了句号\".\" 10 语句间漏了\";\" 11 标识符未说明

12 赋值语句中,赋值号左部标识符属性应是变量 13 变量后不能是此符号 14 call后应为标识符

15 call后标识符属性应为过程 16 条件语句中丢了\"then\" 17 丢了\"end\"或\";\"

18 while型循环语句丢了\"do\" 19 语句后的符号不正确 20 应为关系运算符

21 表达式内标识符属性不能是过程 22 表达式中漏掉右括号\"(\" 23 因子后的非法符号

24 表达式的开始符不能是此符号 31 数越界

五.设计过程

(一) 课内实验内容

(1)增加单词:保留字 ELSE(ELSESYM),FOR(FORSYM),STEP(STEPSYM),UNTIL(UNTILSYM),RETURN(SYM)

运算符 +=(ADDEQUALSYM),-=(MINUSEQUALSYM),++(INCSYM),--(DECSYM),∧(ANDSYM),∨(ORSYM),┓(NOTSYM)

typedef enum { NUL, IDENT, NUMBER, PLUS, MINUS, TIMES, SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ, LPAREN, RPAREN, COMMA, SEMICOLON, PERIOD, BECOMES, BEGINSYM, ENDSYM, IFSYM, THENSYM, WHILESYM, WRITESYM, READSYM, DOSYM, CALLSYM, CONSTSYM, VARSYM, PROCSYM, PROGSYM ,

ELSESYM , FORSYM,STEPSYM,UNTILSYM,RETURNSYM , ANDSYM,ORSYM,NOTSYM,LESSTHAN,MORETHAN,

ADDEQUALSYM,MINUSEQUALSYM,INCSYM,DECSYM,CHARSYM,INTSYM,REALSYM,OFSYM

} SYMBOL; //51

char *SYMOUT[] = {\"NUL\ \"SLASH\

\"LPAREN\ \"BECOMES\ \"WHILESYM\ \"CONSTSYM\ ,

\"ELSESYM\

\"ANDSYM\ \"ADDEQUAL\OFSYM\"};

其中黑斜体为新加入的SYMBOL。

再将上述黑斜体关键字加到KWORD和将相应的SYM加到WSYM,按字母顺序排列 void __fastcall TForm1::ButtonRunClick(TObject *Sender) { for (CH=' '; CH<='^'; CH++) SSYM[CH]=NUL;

strcpy(KWORD[ 1],\"ADDEQUAL\");strcpy(KWORD[ 2],\"BEGIN\"); strcpy(KWORD[ 3],\"CALL\");strcpy(KWORD[4],\"CHAR\"); strcpy(KWORD[5],\"CONST\");strcpy(KWORD[6],\"DEC\"); strcpy(KWORD[ 7],\"DO\"); strcpy(KWORD[ 8],\"ELSE\"); strcpy(KWORD[ 9],\"END\");strcpy(KWORD[ 10],\"FOR\"); strcpy(KWORD[ 11],\"IF\");strcpy(KWORD[ 12],\"INC\");

strcpy(KWORD[13],\"INT\");strcpy(KWORD[ 14],\"MINUSEQUAL\");

strcpy(KWORD[ 15],\"ODD\"); strcpy(KWORD[ 16],\"PROCEDURE\"); strcpy(KWORD[ 17],\"PROGRAM\"); strcpy(KWORD[18],\"READ\"); strcpy(KWORD[19],\"REAL\");strcpy(KWORD[ 20],\"RETURN\"); strcpy(KWORD[ 21],\"STEP\");strcpy(KWORD[22],\"THEN\"); strcpy(KWORD[23],\"UNTIL\");strcpy(KWORD[24],\"VAR\");

strcpy(KWORD[25],\"WHILE\");strcpy(KWORD[26],\"WRITE\"); //添加了 保留字 ELSE,FOR,STEP,UNTIL,RETURN ,CHAR ,INT , REAL WSYM[ 1]=ADDEQUALSYM;WSYM[ 2]=BEGINSYM;

WSYM[ 3]=CALLSYM;WSYM[ 4]=CHARSYM;WSYM[ 5]=CONSTSYM; WSYM[ 6]=DECSYM;WSYM[ 7]=DOSYM;

WSYM[ 8]=ELSESYM; WSYM[ 9]=ENDSYM; WSYM[ 10]=FORSYM; WSYM[11]=IFSYM;

WSYM[ 12]=INCSYM;WSYM[ 13]=INTSYM;WSYM[ 14]=MINUSEQUALSYM; WSYM[ 15]=ODDSYM; WSYM[ 16]=PROCSYM;

WSYM[ 17]=PROGSYM; WSYM[18]=READSYM;WSYM[19]=REALSYM; WSYM[ 20]=RETURNSYM; WSYM[21]=STEPSYM; WSYM[22]=THENSYM; WSYM[ 23]=UNTILSYM; WSYM[24]=VARSYM; WSYM[25]=WHILESYM; WSYM[26]=WRITESYM;

SSYM['+']=PLUS; SSYM['-']=MINUS; SSYM['*']=TIMES; SSYM['/']=SLASH; SSYM['(']=LPAREN; SSYM[')']=RPAREN; SSYM['=']=EQL; SSYM[',']=COMMA; SSYM['.']=PERIOD; SSYM['#']=NEQ;

SSYM[';']=SEMICOLON; SSYM['<']=LESSTHAN; SSYM['>']=MORETHAN;

SSYM['&']=ANDSYM; SSYM['|']=ORSYM;SSYM['!']=NOTSYM;

(二) 课程设计内容

1. 增加运算符+=,-=,++,--

a) 词法分析

在GetSym()中完成INC(+ +)、DEC(- -)、ADDEQUAL(+=)、MINUSEQUAL(- =)的词法分析,代码修改如下:

//----------GetSym()增加功能---- else {if(CH == '+'){

GetCh();

if(CH == '='){ //增加+= SYM = ADDEQUALSYM; GetCh(); }

else if(CH == '+'){ //增加++ SYM = INCSYM; GetCh(); }

else SYM = PLUS; }

else if(CH == '-'){

GetCh();

if(CH == '='){ //增加-= SYM = MINUSEQUALSYM; GetCh(); }

else if(CH == '-'){ //增加-- SYM = DECSYM; GetCh(); }

else SYM = MINUS; }

else { SYM=SSYM[CH]; GetCh(); } }

b) 后+ +和后- -的实现

根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改:

根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改:

根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改: //--------后的++ -- case IDENT: ……………………………..

else if (SYM==INCSYM) //语句中的++运算

{ if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym(); }

else if (SYM==DECSYM) //语句中的--运算

{ if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym (); } …………………… break;

在接受到SYM=IDENT后,如果SYM为INC,则主要执行这四条指令:

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR) 将IDENT的值放到栈顶, GEN(LIT,0,1); 将常数1放到栈顶, GEN(OPR,0,2) 次栈顶加栈顶,

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);将栈顶内容保存到IDENT中。这样

就完成了语句中的++运算。

如果SYM为DEC,则主要执行这四条指令:

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR) 将IDENT的值放到栈顶, GEN(LIT,0,1); 将常数1放到栈顶, GEN(OPR,0,3) 次栈顶减栈顶,

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);将栈顶内容保存到IDENT中。这样就完成了语句中的--运算。

其次,再对因子处理程序FACTOR修改如下:

if(SYM==INCSYM||SYM==DECSYM) //因子中的++和--运算 { count.length++; count.id[count.length]=i; GEN(LIT,0,1);

if(SYM==INCSYM) {

GEN(OPR,0,2);count.i[count.length]=1;

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将栈顶送入变量单元

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送入栈顶 GEN(LIT,0,-1); GEN(OPR,0,2); }//如果为INC,则加1 else {

GEN(OPR,0,3);count.i[count.length]=-1;

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将栈顶送入变量单元

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送入栈顶 GEN(LIT,0,1);GEN(OPR,0,2); }//否则减一

对后++和后—的处理思想是,在表达式中不进行自加/自减操作,但在送往变量的时候进行

c) 前++和前--的实现

语法树:

语句 ........... + + indent ― - indent

根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 前

INC 和 前DEC 操作,首先对语句处理程序STATEMENT进行如下修改:

//--------------- 前的++--

case INCSYM: //前++ GetSym();

if (SYM == IDENT) {

i=POSITION(ID,TX); if (i==0) Error(11); else if (TABLE[i].KIND!=VARIABLE) { /*ASSIGNMENT TO NON-VARIABLE*/

Error(12); i=0; }

if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym(); }

else Error(45); break;

case DECSYM: //前-- GetSym();

if (SYM == IDENT) {

i=POSITION(ID,TX); if (i==0) Error(11); else if (TABLE[i].KIND!=VARIABLE) { /*ASSIGNMENT TO NON-VARIABLE*/

Error(12); i=0; }

if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym (); }

else Error(45); break;

再对因子处理,对于前++、前--,只在EXPRESSION中处理,因子部分只处理后++、后—操作

因子 ........... + + indent ― - indent

else if(SYM == INCSYM) { //前++

GetSym();

if (SYM == IDENT) { i=POSITION(ID,TX); if (i==0) Error(11); else if (TABLE[i].KIND!=VARIABLE) { /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; } if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2); if (i!=0) { GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将栈顶送入变量单元 GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送入栈顶 } GetSym(); } else Error(45); }

else if(SYM == DECSYM) { //前-- GetSym(); if (SYM == IDENT) { i=POSITION(ID,TX); if (i==0) Error(11); else if (TABLE[i].KIND!=VARIABLE) { /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; } if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3); if (i!=0) { GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将栈顶送入变量单元 GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送入栈顶 } GetSym (); } else Error(45); }

d) 扩充+=和-=操作

语法树:

根据图3,在语句处理STATEMENT中,在已经处理INC和DEC的基础上,添加对ADDEQUAL(+=)运算和MINUSEQUAL(-=)运算的扩充,相关代码添加如下: case IDENT:

………………………

else if (SYM==ADDEQUALSYM) //增加运算符+= {

if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym();

EXPRESSION(FSYS,LEV,TX); GEN(OPR,0,2);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); }

else if (SYM==MINUSEQUALSYM) //增加运算符-= {

if (i!=0) GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); GetSym();

EXPRESSION(FSYS,LEV,TX); GEN(OPR,0,3);

if (i!=0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); }

break; 2. 增加Pascal的FOR语句:

UNTIL 表达式 表达式 表达式 STEP:= ident //--------------添加FOR功能 case FORSYM:

GetSym();

if(SYM != IDENT) Error(47); else i=POSITION(ID,TX); if(i == 0) Error(11); else if (TABLE[i].KIND!=VARIABLE) NON-VARIABLE*/ Error(12); i=0; }

{ /*ASSIGNMENT TO

GetSym();

if(SYM == BECOMES) GetSym(); else Error(13);

EXPRESSION(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX); if(i != 0) GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //把栈顶的值送到变量

// GetSym();

if(SYM==STEPSYM) GetSym(); else Error(46);

CX1=CX;GEN(JMP,0,0); CX3=CX;

EXPRESSION(SymSetUnion(SymSetNew(UNTILSYM),FSYS),LEV,TX);

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送回栈顶

GEN(OPR,0,2);

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//把栈顶的值送到变量

// GetSym();

if(SYM==UNTILSYM) GetSym(); else Error(47); CODE[CX1].A=CX;

EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX); //终止条件

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //将变量送回栈顶

GEN(OPR,0,11);

CX2=CX;GEN(JPC,0,0); // GetSym();

if(SYM==DOSYM) GetSym(); else Error(48);

STATEMENT(FSYS,LEV,TX); GEN(JMP,0,CX3); CODE[CX2].A=CX; FOR语句扩充完毕。

3.增加类型:字符类型 和 实数类型

typedef enum { CHARCON, INTCON, REALCON, NOTYP} TYPES; //类型 TYPES TY; //记录类型 struct { ALFA NAME; OBJECTS KIND;

TYPES TYPE; //增加类型 union {

float VAL; /*CONSTANT*/ //统一用浮点型记录 struct { int LEVEL,ADR,SIZE; } vp;

/*VARIABLE,PROCEDUR: 层次、地址、存储空间*/ };

} TABLE[TXMAX];

在SYMBOL中加入REALSYM, INTSYM, CHARSYM, OFSYM 对应的SYMMAX=52; NORW=26;

增加实数和字符词法分析

else //-----------------------------------------加入浮点数读入 if (CH>='0' && CH<='9') { /*NUMBER*/ K=0; NUM=0; SYM = NUMBER; TY=INTCON; float count=10; do{ if(CH=='.'){ //实数 GetCh(); TY=REALCON; while(CH>='0' && CH<='9'){ NUM=NUM+(CH-'0')/count; K++; count*=10; GetCh(); } break; } else{ //整数 NUM=10*NUM+(CH-'0'); K++; GetCh(); } }while((CH>='0' && CH<='9')||CH=='.'); if (K>NMAX) Error(30); } else//----------------------------加入字符类型 只接受 'a' 里面的一个字母 if((int)CH==39) { SYM = CONSTSYM; GetCh(); if((CH>='A' && CH<='Z')||(CH>='a' && CH<='z')) { NUM=(int)CH; GetCh(); if((int)CH==39)

TY=CHARCON; else { NUM=0;SYM=NUL;Error(49);} //类型错误 } else Error(49); //类型不匹配 GetCh(); } 增加覆盖指令 void Interpret() { …………………….

switch ((int)I.A) { /*OPERATOR*/

………………

case 14: //字符输出 Form1->printcs((char)S[T]); fprintf(FOUT,\"%c\\n\

T--; break; case 15: //整数输出 Form1->printls(\"\fprintf(FOUT,\"%d\\n\

T--; break;

case 16: //实数输出 Form1->printrs(\"\fprintf(FOUT,\"%.4f\\n\

T--; break; case 17: break;

case 18: //输入字符 T++; S[T]=InputBox(\"输入\请输入一个字符:\0).ToDouble();

Form1->printcs('?'); Form1->printcs((char)S[T]); fprintf(FOUT,\"? %c\\n\

break; case 19: //输入整型 T++; S[T]=InputBox(\"输入\请输入整数:\0).ToDouble();

while((S[T]-(int)S[T])!=0) { S[T]=InputBox(\"输入\请输入整数:\0).ToDouble();

} Form1->printrs(\"? \

fprintf(FOUT,\"? %f\\n\

break; case 20: //输入实数 T++; S[T]=InputBox(\"输入\请输入实数:\0).ToDouble();

Form1->printrs(\"? \fprintf(FOUT,\"? %f\\n\

break; } }

语法语义分析

void STATEMENT(SYMSET FSYS,int LEV,int &TX) { /*STATEMENT*/ ……………………. case READSYM: GetSym(); if (SYM!=LPAREN) Error(34); else do { GetSym(); if (SYM==IDENT) i=POSITION(ID,TX); else i=0; if (i==0) Error(35); else { switch(TABLE[i].KIND){ case CHARCON: GEN(OPR,0,18); break; case INTCON: GEN(OPR,0,19); break; case REALCON: GEN(OPR,0,20); break; } GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); } GetSym(); }while(SYM==COMMA); if (SYM!=RPAREN) { Error(33); while (!SymIn(SYM,FSYS)) GetSym(); } else GetSym(); break; /* READSYM */

case WRITESYM: GetSym(); if (SYM==LPAREN) { do { GetSym();

if (SYM==IDENT) i=POSITION(ID,TX); else i=0; if(i!=0){

// TY = TABLE[i].KIND;

EXPRESSION(SymSetUnion(SymSetNew(RPAREN,COMMA),FSYS),LEV,TX); switch(TABLE[i].KIND){ //输出处理 case CHARCON: GEN(OPR,0,14); break; case INTCON: GEN(OPR,0,15); break; case REALCON: GEN(OPR,0,16); break; }

}

else Error(35); }while(SYM==COMMA); if (SYM!=RPAREN) Error(33); else GetSym(); } GEN(OPR,0,17); break; /*WRITESYM*/ ………..

} /*STATEMENT*/ 变量定义

void CharDeclaration(int LEV,int &TX,int &DX) { //声明 if (SYM==IDENT) { ENTER(CHARCON,LEV,TX,DX); GetSym(); } else Error(4); } /*CharDeclaration()*/

//---------------------------------------------------------------------------

void RealDeclaration(int LEV,int &TX,int &DX) { //声明 if (SYM==IDENT) { ENTER(REALCON,LEV,TX,DX); GetSym(); } else Error(4); } /*RealDeclaration()*/

六.运行界面

七.调试测试

++,--的测试,测试文件test1.pl0

+=,-=的测试,测试文件test2.pl0

FOR功能的测试,测试文件test4.pl0

八.课程设计总结

编译原理这门课,在计算机专业中也算是最难的一门课程吧,我也确实体会到了。老师之前说的,只要看懂我们要修改的部分就可以了。其实不然。说实在的,想要改动任何一个地方,都要把整个代码从头到尾彻底了解,得到各个函数部分的功能和作用,以及数据类型的定义,才能很好地修改程序。

学完编译原理这门课后,虽然我们没有亲手做一个编译器出来。但在这次拓充功能的课程设计上,我们已经学到了很多。完成了这次课程设计,对我的动手能力有很大提高,特别是对C++ Builder的操作以及对PL/0的理解和使用方面。平时看课本时,有时问题老是弄不懂,做完课程设计,那些问题就迎刃而解了。而且还可以记住很多东西

但是,也存在一些缺点,就是对理论知识的理解上尚不够透切,今后我要加强理论知的学习。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务