📄 pl.cpp
字号:
// PL.cpp : Defines the entry point for the console application.
//
#include "common.h"
////////////////////////////////////////////////////////////
////////////////////////函数头定义如下//////////////////////
////////////////////////////////////////////////////////////
SYMLIST * listsAdd(SYMLIST * list1,SYMLIST * list2);
SYMLIST * listAddSym(SYMLIST * list,SYMBOL sym);
int SYMINLIST(SYMBOL sym,SYMLIST * list);
void COPYLIST(SYMLIST * list1,SYMLIST * list2);
void error(int);
int nError;
void INITIAL();
void ENTERID();
void ENTERPREID();
void getSymbols(FILE *);
void getASymbol();
void destroySymbols();
SymbolItem *Symbols=NULL;
SymbolItem *CurSymbol=NULL;
void GEN(OPCOD func,int level,int address);
void WriteObjCode(char *);
void WriteCodeList(char *);
void ENTERARRAY(SYMLIST * list,TYPES type,int low,int high);
void ENTERBLOCK();
void ENTER(OBJECT object);
int GETPOSITION(char * id);
void CONSTANT(SYMLIST * list,CONSTREC & constRec);
void ARRAYTYP(SYMLIST * list,int & aref,int & arsz);
void TYP(SYMLIST * list,TYPES & tp,int & rf,int & sz);
void PARAMENTERLIST(SYMLIST * list);
void CONSTDECLARATION(SYMLIST * list);
void TYPEDECLARATION(SYMLIST * list);
void VARDECLARATION(SYMLIST * list);
void PROCDECLARATION(SYMLIST * list);
void FACTOR(SYMLIST * list,TYPEITEM & typeItem);
void TERM(SYMLIST * list,TYPEITEM & typeItem);
void SIMPLEEXPRESSION(SYMLIST * list,TYPEITEM & typeItem);
void EXPRESSION(SYMLIST * list,TYPEITEM & typeItem);
void ARRAYELEMENT(SYMLIST * list,TYPEITEM & typeItem);
void ASSIGNMENT(SYMLIST * list);
void IFSTATEMENT(SYMLIST * list);
void WHILESTATEMENT(SYMLIST * list);
void FORSTATEMENT(SYMLIST * list);
void REPEATSTATEMENT(SYMLIST * list);
void CASESTATEMENT(SYMLIST * list);
void soncase(SYMLIST * list,int & jumpback,int temp);
void COMPOUND(SYMLIST * list);
void STANDPROC(SYMLIST * list,int i);
void CALL(SYMLIST * list);
void STATEMENT(SYMLIST * list);
void BLOCK(SYMLIST * list,int level);
////////////////////////////////////////////////////////////
////////////////////函数过程定义如下////////////////////////
////////////////////////////////////////////////////////////
void GEN(OPCOD func,int level,int address) //将产生的代码保存到代码数组CODE里面
{ //并将代码索引CX增加 1
static int lineNumber=0;
if(CX>MAXNUMOFCODEADDRESS)
{
printf("PROGRAM TOO LONG!");
exit(0);
}
printf("%d\t",lineNumber); //下面三个语句用来在编译的过程中显示代码
printf(ObjCodeScript[func],level,address); //注意:现实的代码不是完全的,但是可以帮助理解
printf("\n");
CODE[CX].lineNumber=lineNumber++;
CODE[CX].func=func;
CODE[CX].level=level;
CODE[CX].address=address;
CX++;
}
void WriteObjCode(char *filename) //将产生的代码写进*.pld文件里面(二进制形式)
{
FILE *fcode;
fcode=fopen(filename,"wb");
if(!fcode)
error(40); //不能打开.pld文件
for(int i=0;i<CX;i++)
{
fwrite(&CODE[i].func,sizeof(OPCOD),1,fcode);
fwrite(&CODE[i].level,sizeof(int),1,fcode);
fwrite(&CODE[i].address,sizeof(int),1,fcode);
}
fclose(fcode);
}
void WriteCodeList(char *filename) //将产生的代码写进*.lst文件(可见字符形式)
{
FILE *flist;
flist=fopen(filename,"wb");
if(!flist)
error(39); //不能打开.lst文件
for(int i=0;i<CX;i++)
{
fprintf(flist,"%d\t",i);
fprintf(flist,ObjCodeScript[CODE[i].func],CODE[i].level,CODE[i].address);
fprintf(flist,"\n");
}
fclose(flist);
}
void WriteLabelCode(char *filename) //将产生的代码写进*.lab文件(可见字符形式)
{
FILE *flabel;
flabel=fopen(filename,"wb");
if(!flabel)
error(41); //不能打开.lst文件
for(int i=0;i<JX;i++)
{
fprintf(flabel,"第%d项:\t",i+1);
fprintf(flabel,"%d",JUMADRTAB[i]);
fprintf(flabel,"\n");
}
fclose(flabel);
}
void ENTERARRAY(TYPES type,int low,int high) //向数组信息表填入一个表项
{
if(low>high)
{
error(19); //"数组上下大小关系界错误"
}
if (AX==MAXNUMOFARRAYTABLE)
{
error(24); //数组表溢出
printf("TOO LONG ARRAYS IN PROGRAM!");
}
else
{
AX++;
ATAB[AX].intType=type;
ATAB[AX].low=low;
ATAB[AX].high=high;
}
}
void ENTERBLOCK() //每当编译一个过程开始时,保证调用该函数一次
{ //用来向程序体表填入一个表项以登记此过程体
if(BX==MAXNUMOFBLOCKTABLE)
{
error(26); //程序体表溢出
printf("TOO MANY PROCEDURE IN PROGRAM!");
}
else
{
BX++;
displayLevel++; //编译到了一个过程,层次加一
BTAB[BX].last=0;
BTAB[BX].lastPar=0;
}
}
void QUITBLOCK() //每当一个过程编译完时,保证调用该函数一次
{
displayLevel--; //层次减一
}
void ENTER(OBJECT kind) //在编译的过程中将遇到的符号填入符号表中
{ //如果在同一层次内有两次定义性质的出现,则报错
int j,l;
if(TX==MAXNUMOFNAMETABLE)
{
error(25); //名字表溢出
printf("PROGRAM TOO LONG!");
}
else
{
strcpy(NAMETAB[0].name,CurSymbol->value.lpValue); //当前标识符(注意:只能是标识符)的内容填入符号表的第一项??????????
j=BTAB[DISPLAY[displayLevel]].last; //将临时变量j设成当前DISPLAY表项所指向的程序体表项的last域
l=j;
while(stricmp(NAMETAB[j].name,CurSymbol->value.lpValue))
j=NAMETAB[j].link; //顺藤摸瓜
if(j>0)
error(31); //如果摸着了,则本程序体内符号重复定义
else
{ //否则,填入相应的信息
TX++;
strcpy(NAMETAB[TX].name,CurSymbol->value.lpValue);
NAMETAB[TX].link=l;
NAMETAB[TX].kind=kind;
NAMETAB[TX].type=NOTYP;
NAMETAB[TX].ref=0;
NAMETAB[TX].level=displayLevel;
NAMETAB[TX].normal=0;
switch(kind)
{
case VARIABLE:
case PROCEDURE:
NAMETAB[TX].unite.address=0;break;
case KONSTANT:
NAMETAB[TX].unite.value=0;break;
case TYPEL:
NAMETAB[TX].unite.size=0;break;
}
BTAB[DISPLAY[displayLevel]].last=TX;
}
}
}
int GETPOSITION(char * id) //通过标识符的内容在名字表里面查找其索引
{
int i=0,j=displayLevel;
strcpy(NAMETAB[0].name,id);
//j=displayLevel;
do //在所有的活动记录(注意:是活动的)里面顺藤摸瓜
{
i=BTAB[DISPLAY[j]].last;
while (stricmp(NAMETAB[i].name,CurSymbol->value.lpValue))
i=NAMETAB[i].link;
j--; //一个记录里面没有摸到,则到上一级里面去
}while( j>=0 && i==0);
if(i==0) // 表示没有摸到
error(33); //没有定义符号
return (int)i;
}
void CONSTANT(SYMLIST * list,CONSTREC & constRec) //从源程序里面获取一个常量类型的数据
{ //传引用参数constRec 用来记录获取的结果
int x,sign;
constRec.type=NOTYP;
constRec.value=0;
if(SYMINLIST(CurSymbol->type,&CONSTBEGSYS))
{
if(CurSymbol->type==CHARCON)
{
constRec.type=CHARS;
constRec.value=CurSymbol->value.iValue;
getASymbol();
}
else
{
sign=1; //将常量的符号默认置为正
if(CurSymbol->type==PLUS || CurSymbol->type==MINUS)
{
if(CurSymbol->type==MINUS)
sign=-1; //置为负
getASymbol();
}
if(CurSymbol->type==IDENT)
{
x=GETPOSITION(CurSymbol->value.lpValue); //查表
if(x!=0)
{
if(NAMETAB[x].kind!=KONSTANT)
error(17);// 应该是常量或者常量标识符
else
{
constRec.type=NAMETAB[x].type;
constRec.value=sign*NAMETAB[x].unite.value;
}
}
getASymbol();
}
else if(CurSymbol->type==INTCON)
{
constRec.type=INTS;
constRec.value=sign*CurSymbol->value.iValue;
getASymbol();
}
}
}
}
void ARRAYTYP(SYMLIST * list,int & arrayRef,int & arraySize) //获取一个数组类型的信息,传引用参数arrayRef和arraySize
{ //用来记录从数组获取的引用信息和大小信息
TYPES eleType;
CONSTREC low,high;
int eleRef,eleSize;
//////////////////////////////////////////////////////////
SYMLIST * tempList=new SYMLIST;
tempList->AddHead(COLON); tempList->AddHead(RBRACK);
tempList->AddHead(RPAREN); tempList->AddHead(OFSYM);
CONSTANT(tempList,low); //获得数组下标的下限
delete tempList;
//////////////////////////////////////////////////////////
if(low.type!=INTS && low.type!=CHARS)
error(20); //下标元素类型错误
if(CurSymbol->type==DPOINT)
getASymbol();
else
error(42);//应该是'..'
//////////////////////////////////////////////////////////
SYMLIST * tempList1=new SYMLIST;
tempList1->AddHead(COMMA); tempList1->AddHead(RBRACK);
tempList1->AddHead(RPAREN); tempList1->AddHead(OFSYM);
CONSTANT(tempList1,high); //获得数组下标的上限
delete tempList1;
//////////////////////////////////////////////////////////
if(low.type!=high.type)
{
error(21); //上下界的类型不一致
high.value=low.value;
}
ENTERARRAY(low.type,low.value,high.value); //向数组信息表登记
arrayRef=AX;
if(CurSymbol->type==COMMA) //如果当前符号是逗号,表示数组是多维的
{
getASymbol();
eleType=ARRAYS; //数组的“子维”的类型是数组
ARRAYTYP(list,eleRef,eleSize); //获取较低维的数组的信息
}
else
{
if(CurSymbol->type==RBRACK)
getASymbol();
else
{
error(5); //应该是']'
if(CurSymbol->type==RPAREN)
getASymbol();
}
if(CurSymbol->type==OFSYM)
getASymbol();
else
error(10); //应该是'of'
TYP(list,eleType,eleRef,eleSize); //获取数组元素的类型
}
arraySize=(high.value-low.value+1)*eleSize; //计算本数组类型的大小
ATAB[arrayRef].size=arraySize;
ATAB[arrayRef].eleType=eleType; //填信息
ATAB[arrayRef].elRef=eleRef;
ATAB[arrayRef].elSize=eleSize;
}
void TYP(SYMLIST * list,TYPES & type,int & ref,int & size)//获取(到名字表里面查找)当前的标识符的类型信息
{
int x;
type=NOTYP;
ref=0;
size=0;
if(SYMINLIST(CurSymbol->type,&TYPEBEGSYS))
{
if(CurSymbol->type==IDENT)
{
x=GETPOSITION(CurSymbol->value.lpValue); //查表
if(x!=0)
{
if(NAMETAB[x].kind!=TYPEL)
{
error(15); //应该是类型标识符
}
else
{
type=NAMETAB[x].type;
ref=NAMETAB[x].ref;
size=NAMETAB[x].unite.size;
if(type==NOTYP)
error(36); //类型定义出错
}
getASymbol();
}
}
else if (CurSymbol->type==ARRAYSYM) //如果是数组类型
{
getASymbol();
if(CurSymbol->type==LBRACK)
getASymbol();
else
{
error(4); //应该是'['
if(CurSymbol->type==LPAREN)
getASymbol();
}
type=ARRAYS;
ARRAYTYP(list,ref,size); //返回数组类型的信息
}
}
}
void PARAMENTERLIST(SYMLIST * list) //编译某个过程的参数列表
{
TYPES type;
int ref,size,x,helper;
type=NOTYP;
ref=0;
size=0;
getASymbol();
while(CurSymbol->type==IDENT || CurSymbol->type==VARSYM)
{
int valuePar=0; //默认是变量参数
if(CurSymbol->type!=VARSYM)
valuePar=1; //如果当前符号不是var则表明是值参数
else
getASymbol();
helper=TX;
if(CurSymbol->type==IDENT)
{
ENTER(VARIABLE); //编译到一个变量,将其信息填入符号表
getASymbol();
}
else
error(14); //应该是标识符
while(CurSymbol->type==COMMA) //如果当前符号是逗号,则说明是一个参数列表,继续读入下一个标识符
{
getASymbol();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -