课 程 设 计
课程名称___ 编译原理______ __ 题目名称__编译原理课程设计__ _ 学生学院__ 计算机学院_________ 专业班级_ 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的理解和使用方面。平时看课本时,有时问题老是弄不懂,做完课程设计,那些问题就迎刃而解了。而且还可以记住很多东西
但是,也存在一些缺点,就是对理论知识的理解上尚不够透切,今后我要加强理论知的学习。
因篇幅问题不能全部显示,请点此查看更多更全内容