ifXi为非终结符,Xi+1为终结符then
forLastVT中的每个元素ado
a>Xi+1;
end;
3、构造算符优先分析和中间代码产生过程。
四、输入数据和输出数据
若输入文法:
E->E+T|T
T->T*F|F
F->(E)|i
将得到如下所示的FirstVT集和LastVT数组。
输出的优先关系表如下:
若输入的语句是
a:
=b+c*(e-a)
则输出:
(-,e,a,T1)
(*,c,T1,T2)
(+,b,T2,T3)
(:
=,T3,_,a)
实验四PL/0编译器的分析和理解
一、实验目的
通过阅读PL/0编译器,理解整个编译过程,掌握编译每一阶段的实现方法;并加深对理论知识的认识。
二、实验要求
阅读PL/0编译器,完成以下任务:
1、画出整个程序流程图及各编译阶段处理的流程图;
2、写出每一编译阶段实现中用到的主要理论,及对该理论的理解;
3、写出你的心得和体会。
4、就上述部分写出实验报告,A4纸(10页以内)。
(初步这样定)
三、实验提示
(一)PL/0语言的语法图
1、程序
2、程序体
3、语句序列
4、语句
5、条件
6、表达式
7、项
8、因子
(二)语法分析
这里采用递归下降的方法来设计PL/0编译器。
以下我们给出该语言的FIRST和FOLLOW集合。
非终结符(S)
FIRST(S)
FOLLOW(S)
程序体
constvarprocedureidentcallifbeginwhile
.;
语句
identcallbeginifwhile
.;end
条件
odd+-(identnumber
thendo
表达式
+-(identnumber
.;)Rendthendo
项
identnumber(
.;)R+-endthendo
因子
identnumber(
.;)R+-*/endthendo
注:
表中R代表六个关系运算符。
(三)PL/0处理机的指令集
根据PL/0语言的要求,它包括以下的指令:
(1)LIT/*将常数置于栈顶*/
(2)LOD/*将变量值置于栈顶*/
(3)STO/*将栈顶的值赋与某变量*/
(4)CAL/*用于过程调用的指令*/
(5)INT/*在数据栈中分配存贮空间*/
(6)JMP,JPC/*用于if,while语句的条件或无条件控制转移指令*/
(7)OPR/*一组算术或逻辑运算指令*/
F
L
A
上述指令的格式由三部分组成:
其中,f,l,a的含义见下表:
F
L
a
INT
———
常量
LIT
———
常量
LOD
层次差
数据地址
STO
层次差
数据地址
CAL
层次差
程序地址
JMP
———
程序地址
JPC
———
程序地址
OPR
———
运算类别
(四)PL/0语言编译器源程序
PL/0语言编译器源程序包括如下C程序文件,PL0.h、PL0.c、set.h和set.c。
/************PL0.h*************/
#include
#defineNRW11//numberofreservedwords
#defineTXMAX500//lengthofidentifiertable
#defineMAXNUMLEN14//maximumnumberofdigitsinnumbers
#defineNSYM10//maximumnumberofsymbolsinarrayssymandcsym
#defineMAXIDLEN10//lengthofidentifiers
#defineMAXADDRESS32767//maximumaddress
#defineMAXLEVEL32//maximumdepthofnestingblock
#defineCXMAX500//sizeofcodearray
#defineMAXSYM30//maximumnumberofsymbols
#defineSTACKSIZE1000//maximumstorage
enumsymtype
{
SYM_NULL,
SYM_IDENTIFIER,
SYM_NUMBER,
SYM_PLUS,
SYM_MINUS,
SYM_TIMES,
SYM_SLASH,
SYM_ODD,
SYM_EQU,
SYM_NEQ,
SYM_LES,
SYM_LEQ,
SYM_GTR,
SYM_GEQ,
SYM_LPAREN,
SYM_RPAREN,
SYM_COMMA,
SYM_SEMICOLON,
SYM_PERIOD,
SYM_BECOMES,
SYM_BEGIN,
SYM_END,
SYM_IF,
SYM_THEN,
SYM_WHILE,
SYM_DO,
SYM_CALL,
SYM_CONST,
SYM_VAR,
SYM_PROCEDURE
};
enumidtype
{
ID_CONSTANT,ID_VARIABLE,ID_PROCEDURE
};
enumopcode
{
LIT,OPR,LOD,STO,CAL,INT,JMP,JPC
};
enumoprcode
{
OPR_RET,OPR_NEG,OPR_ADD,OPR_MIN,
OPR_MUL,OPR_DIV,OPR_ODD,OPR_EQU,
OPR_NEQ,OPR_LES,OPR_LEQ,OPR_GTR,
OPR_GEQ
};
typedefstruct
{
intf;//functioncode
intl;//level
inta;//displacementaddress
}instruction;
//////////////////////////////////////////////////////////////////////
char*err_msg[]=
{
/*0*/"",
/*1*/"Found':
='whenexpecting'='.",
/*2*/"Theremustbeanumbertofollow'='.",
/*3*/"Theremustbean'='tofollowtheidentifier.",
/*4*/"Theremustbeanidentifiertofollow'const','var',or'procedure'.",
/*5*/"Missing','or';'.",
/*6*/"Incorrectprocedurename.",
/*7*/"Statementexpected.",
/*8*/"Followthestatementisanincorrectsymbol.",
/*9*/"'.'expected.",
/*10*/"';'expected.",
/*11*/"Undeclaredidentifier.",
/*12*/"Illegalassignment.",
/*13*/"':
='expected.",
/*14*/"Theremustbeanidentifiertofollowthe'call'.",
/*15*/"Aconstantorvariablecannotbecalled.",
/*16*/"'then'expected.",
/*17*/"';'or'end'expected.",
/*18*/"'do'expected.",
/*19*/"Incorrectsymbol.",
/*20*/"Relativeoperatorsexpected.",
/*21*/"Procedureidentifiercannotbeinanexpression.",
/*22*/"Missing')'.",
/*23*/"Thesymbolcannotbefollowedbyafactor.",
/*24*/"Thesymbolcannotbeasthebeginningofanexpression.",
/*25*/"Thenumberistoogreat.",
/*26*/"",
/*27*/"",
/*28*/"",
/*29*/"",
/*30*/"",
/*31*/"",
/*32*/"Therearetoomanylevels."
};
//////////////////////////////////////////////////////////////////////
charch;//lastcharacterread
intsym;//lastsymbolread
charid[MAXIDLEN+1];//lastidentifierread
intnum;//lastnumberread
intcc;//charactercount
intll;//linelength
intkk;
interr;
intcx;//indexofcurrentinstructiontobegenerated.
intlevel=0;
inttx=0;
charline[80];
instructioncode[CXMAX];
char*word[NRW+1]=
{
"",/*placeholder*/
"begin","call","const","do","end","if",
"odd","procedure","then","var","while"
};
intwsym[NRW+1]=
{
SYM_NULL,SYM_BEGIN,SYM_CALL,SYM_CONST,SYM_DO,SYM_END,
SYM_IF,SYM_ODD,SYM_PROCEDURE,SYM_THEN,SYM_VAR,SYM_WHILE
};
intssym[NSYM+1]=
{
SYM_NULL,SYM_PLUS,SYM_MINUS,SYM_TIMES,SYM_SLASH,
SYM_LPAREN,SYM_RPAREN,SYM_EQU,SYM_COMMA,SYM_PERIOD,SYM_SEMICOLON
};
charcsym[NSYM+1]=
{
'','+','-','*','/','(',')','=',',','.',';'
};
#defineMAXINS8
char*mnemonic[MAXINS]=
{
"LIT","OPR","LOD","STO","CAL","INT","JMP","JPC"
};
typedefstruct
{
charname[MAXIDLEN+1];
intkind;
intvalue;
}comtab;
comtabtable[TXMAX];
typedefstruct
{
charname[MAXIDLEN+1];
intkind;
shortlevel;
shortaddress;
}mask;
FILE*infile;
//EOFPL0.h
/************SET.h*************/
#ifndefSET_H
#defineSET_H
typedefstructsnode
{
intelem;
structsnode*next;
}snode,*symset;
symsetphi,declbegsys,statbegsys,facbegsys,relset;
symsetcreateset(intdata,.../*SYM_NULL*/);
voiddestroyset(symsets);
symsetuniteset(symsets1,symsets2);
intinset(intelem,symsets);
#endif
//EOFset.h
/************SET.c*************/
#include
#include
#include
#include"set.h"
symsetuniteset(symsets1,symsets2)
{
symsets;
snode*p;
s=p=(snode*)malloc(sizeof(snode));
while(s1&&s2)
{
p->next=(snode*)malloc(sizeof(snode));
p=p->next;
if(s1->elemelem)
{
p->elem=s1->elem;
s1=s1->next;
}
else
{
p->elem=s2->elem;
s2=s2->next;
}
}
while(s1)
{
p->next=(snode*)malloc(sizeof(snode));
p=p->next;
p->elem=s1->elem;
s1=s1->next;
}
while(s2)
{
p->next=(snode*)malloc(sizeof(snode));
p=p->next;
p->elem=s2->elem;
s2=s2->next;
}
p->next=NULL;
returns;
}//uniteset
voidsetinsert(symsets,intelem)
{
snode*p=s;
snode*q;
while(p->next&&p->next->elem{
p=p->next;
}
q=(snode*)malloc(sizeof(snode));
q->elem=elem;
q->next=p->next;
p->next=q;
}//setinsert
symsetcreateset(intelem,.../*SYM_NULL*/)
{
va_listlist;
symsets;
s=(snode*)malloc(sizeof(snode));
s->next=NULL;
va_start(list,elem);
while(elem)
{
setinsert(s,elem);
elem=va_arg(list,int);
}
va_end(list);
returns;
}//createset
voiddestroyset(symsets)
{
snode*p;
while(s)
{
p=s;
s=s->next;
free(p);