📄 pl.cpp
字号:
else
{//形式参数
if(CurSymbol->type!=IDENT)
error(14);//应该是标识符
else
{
k=GETPOSITION(CurSymbol->value.lpValue);
getASymbol();
if(k!=0)
{
if(NAMETAB[k].kind!=VARIABLE)
error(16);//应该是变量
typeItem.typ=NAMETAB[k].type;
typeItem.ref=NAMETAB[k].ref;
if(NAMETAB[k].normal)
GEN(LODA,NAMETAB[k].level,NAMETAB[k].unite.address);
else
GEN(LOD,NAMETAB[k].level,NAMETAB[k].unite.address);
if(CurSymbol->type==LBRACK)
{
ARRAYELEMENT(tempList,typeItem);
}
if(NAMETAB[cp].type!=typeItem.typ || NAMETAB[cp].ref!=typeItem.ref)
error(29);//实参与形参类型不一致
}
}
}
}
}
while(CurSymbol->type==COMMA);
delete tempList1;
if(CurSymbol->type==RPAREN)
getASymbol();
else
error(2);//应该是')'
}
if(cp<lastPar)
error(30);//实在参数个数不够
GEN(CAL,NAMETAB[i].level,NAMETAB[i].unite.address);
if(NAMETAB[i].level<displayLevel)
GEN(UDIS,NAMETAB[i].level,displayLevel);
}
}
else
error(18);//应该是过程名
}
else
error(14);//应该是标识符
delete tempList;
}
void STATEMENT(SYMLIST * list) //普通语句的分析,这些语句有几种形式,分别以不同的标识符开头
{
////////////////////////////////////////////////////
SYMLIST * tempList=new SYMLIST;
COPYLIST(tempList,listAddSym(&STATBEGSYS,IDENT));
////////////////////////////////////////////////////
if(SYMINLIST(CurSymbol->type,tempList)) //通过不同的标识符辨别是那种语句
{
switch(CurSymbol->type)
{
case IDENT: ASSIGNMENT(list);break;
case CALLSYM: CALL(list);break;
case IFSYM: IFSTATEMENT(list);break;
case WHILESYM: WHILESTATEMENT(list);break;
case BEGINSYM: COMPOUND(list);break;
//*******************************************************
//修改
case FORSYM: FORSTATEMENT(list);break;//for语句
case REPEATSYM:REPEATSTATEMENT(list);break;//repeat语句
case CASESYM:CASESTATEMENT(list);break;//case语句
//*******************************************************
}
}
delete tempList;
}
void BLOCK(SYMLIST * list,int level) //过程体的分析
{
int cx,tx,programBlock;
int dx;
dx=DX;//记录静态上层局部数据区大小
DX=3;//将本程序体的活动记录留出三个单元出来,用做连接数据
tx=TX;
NAMETAB[tx].unite.address=CX;
if(displayLevel>MAXLEVELDEPTH)
error(26);//程序体表溢出
ENTERBLOCK(); //登记过程体
programBlock=BX;
DISPLAY[displayLevel]=BX;
NAMETAB[tx].type=NOTYP;
NAMETAB[tx].ref=programBlock;
if(CurSymbol->type==LPAREN && displayLevel>1)
{
PARAMENTERLIST(list); //编译过程列表
if(CurSymbol->type==SEMICOLON)
getASymbol();
else
error(1);//应该是';'
}
else if(displayLevel>1)
{
if(CurSymbol->type==SEMICOLON)
getASymbol();
else
error(1);//应该是';'
}
BTAB[programBlock].lastPar=TX;
BTAB[programBlock].pSize=DX;
GEN(JMP,0,0);
do
{
switch(CurSymbol->type) //针对当前不同的不好进行不同的声明
{
case CONSTSYM:
getASymbol();
do
{
CONSTDECLARATION(list); //常量声明,一次可声明多个
}
while(CurSymbol->type==IDENT);
break;
case TYPESYM:
getASymbol();
do
{
TYPEDECLARATION(list); //类型声明,一次可声明多个
}
while(CurSymbol->type==IDENT);
break;
case VARSYM:
getASymbol();
do
{
VARDECLARATION(list); //变量声明,一次可声明多个
}
while(CurSymbol->type==IDENT);
break;
}
while(CurSymbol->type==PROCSYM)
PROCDECLARATION(list); //过程声明,每次只能声明一个
}while(SYMINLIST(CurSymbol->type,&DECLBEGSYS));
CODE[NAMETAB[tx].unite.address].address=CX;//将执行语句的开始处地址回填
JUMADRTAB[JX]=CX;
JX++;
NAMETAB[tx].unite.address=CX;//代码开始地址
cx=CX;
GEN(ENTP,displayLevel,DX);
////////////////////////////////////////////////////
SYMLIST * tempList=new SYMLIST;
COPYLIST(tempList,listAddSym(listAddSym(list,ENDSYM),SEMICOLON));
STATEMENT(tempList);
delete tempList;
////////////////////////////////////////////////////
CODE[cx].address=DX;//回填数据区大小
if(displayLevel>1)
GEN(RETP,0,0);//从程序体返回
else
GEN(ENDP,0,0);//程序结束
QUITBLOCK();
DX=dx;//恢复静态上层局部数据区大小
}
int Feof(FILE *fp)//判断是否到了源文件尾
{
int getChar;
getChar=fgetc(fp);
if(getChar==-1)
{
if(feof(fp))
return 1;//如果是,返回“真”
}
else
fseek(fp,-1,SEEK_CUR);//否则,将指向文件流的指针向后移动一个字符
return 0;
}
SYMBOL GetReserveWord(char *nameValue)//判断得到的符号是否是保留字
{
int i;
char reserveWord[NUMOFWORD][20]=
{
"and","begin","const","else","if","not","or","program","type","while",
"array","call","do","end","mod","of","procedure","then","var",
//添加 @@@@@@
"repeat","until","case","for","to"
};
SYMBOL reserveType[NUMOFWORD]=
{
ANDSYM,BEGINSYM,CONSTSYM,ELSESYM,IFSYM,NOTSYM,ORSYM,PROGRAMSYM,TYPESYM,WHILESYM,
ARRAYSYM,CALLSYM,DOSYM,ENDSYM,MODSYM,OFSYM,PROCSYM,THENSYM,VARSYM,
//添加 @@@@@@
REPEATSYM,UNTILSYM,CASESYM,FORSYM,TOSYM
};
for(i=0;i<NUMOFWORD;i++) //这里采用了遍历的做法,但是效率不高,可以考虑采用二叉查找法
if(!stricmp(reserveWord[i],nameValue))
return reserveType[i];
return (SYMBOL)0;
}
void AddSymbolNode(SymbolItem **current,int lineNumber,SYMBOL type,int iValue) //在词法分析的时候向符号列表中加入一个分析出来的符号
{
(*current)->next=new SymbolItem;
if(!(*current)->next)
{
error(27);//系统为本编译程序分配的堆不够用
exit(4);
}
(*current)=(*current)->next;
(*current)->lineNumber=lineNumber;
(*current)->type=type;
(*current)->value.iValue=iValue;
(*current)->next=NULL;
}
void getSymbols(FILE *srcFile) //从源文件读入字符,获得符号链表,词法分析
{
int lineNumber=1;
char nameValue[MAXSYMNAMESIZE];
int nameValueint;
char readChar;
SymbolItem head,*current=&head;
printf("\n进行词法分析 -->-->-->-->-->-->-->--> ");
while(!Feof(srcFile))
{
readChar=fgetc(srcFile);
if(iscsymf(readChar))
{
nameValueint=0;
do
{
nameValue[nameValueint++]=readChar;
readChar=fgetc(srcFile);
if(Feof(srcFile))
break;
}while(iscsym(readChar) || isdigit(readChar));
nameValue[nameValueint]=0;
fseek(srcFile,-1,SEEK_CUR);
current->next=new SymbolItem;
current=current->next;
current->lineNumber=lineNumber;
if(!(current->type=GetReserveWord(nameValue)))//不是保留字
{
current->type=IDENT;
current->value.lpValue=new char[nameValueint];
strcpy(current->value.lpValue,nameValue);
}
current->next=NULL;
}
else if(isdigit(readChar))
{
nameValueint=0;
do
{
nameValue[nameValueint++]=readChar;
readChar=fgetc(srcFile);
if(Feof(srcFile))
break;
}while(isdigit(readChar));
nameValue[nameValueint]=0;
fseek(srcFile,-1,SEEK_CUR);
AddSymbolNode(¤t,lineNumber,INTCON,atoi(nameValue));
}
else switch(readChar)
{
case ' ': //字符 'tab'
case ' ':
break;
case '\n':
break;
case '\r': //换行符
lineNumber++;
break;
case ':':
if(Feof(srcFile))
break;
readChar=fgetc(srcFile);
if(readChar=='=')
AddSymbolNode(¤t,lineNumber,BECOMES,0);
else
{
fseek(srcFile,-1,SEEK_CUR);
AddSymbolNode(¤t,lineNumber,COLON,0);
}
break;
case '<':
if(Feof(srcFile))
break;
readChar=fgetc(srcFile);
if(readChar=='=')
AddSymbolNode(¤t,lineNumber,LEQ,0);
else if(readChar=='>')
AddSymbolNode(¤t,lineNumber,NEQ,0);
else
{
fseek(srcFile,-1,SEEK_CUR);
AddSymbolNode(¤t,lineNumber,LSS,0);
}
break;
case '>':
if(Feof(srcFile))
break;
readChar=fgetc(srcFile);
if(readChar=='=')
AddSymbolNode(¤t,lineNumber,GEQ,0);
else
{
fseek(srcFile,-1,SEEK_CUR);
AddSymbolNode(¤t,lineNumber,GTR,0);
}
break;
case '.':
if(Feof(srcFile))
{
AddSymbolNode(¤t,lineNumber,PERIOD,0);
break;
}
readChar=fgetc(srcFile);
if(readChar=='.')
AddSymbolNode(¤t,lineNumber,DPOINT,0);
else
{
fseek(srcFile,-1,SEEK_CUR);
AddSymbolNode(¤t,lineNumber,PERIOD,0);
}
break;
case '\'':
readChar=fgetc(srcFile);
if(Feof(srcFile))
break;
if(fgetc(srcFile)=='\'')
AddSymbolNode(¤t,lineNumber,CHARCON,readChar);
else
error(1);//////////////////////////
break;
case '+':
AddSymbolNode(¤t,lineNumber,PLUS,0);
break;
case '-':
AddSymbolNode(¤t,lineNumber,MINUS,0);
break;
case '*':
AddSymbolNode(¤t,lineNumber,TIMES,0);
break;
case '/':
AddSymbolNode(¤t,lineNumber,DIVSYM,0);
break;
case '(':
AddSymbolNode(¤t,lineNumber,LPAREN,0);
break;
case ')':
AddSymbolNode(¤t,lineNumber,RPAREN,0);
break;
case '=':
AddSymbolNode(¤t,lineNumber,EQL,0);
break;
case '[':
AddSymbolNode(¤t,lineNumber,LBRACK,0);
break;
case ']':
AddSymbolNode(¤t,lineNumber,RBRACK,0);
break;
case ';':
AddSymbolNode(¤t,lineNumber,SEMICOLON,0);
break;
case ',':
AddSymbolNode(¤t,lineNumber,COMMA,0);
break;
default:
error(38);
} //switch end
} //while end
Symbols=head.next;
CurSymbol=Symbols;
if(nError)
{
printf("\n%d errors found.",nError);
exit(2);
}
else
printf("词法分析成功!\n\n");
}
void getASymbol() //采用递归下降的语法分析,逐个的获取一个单词符号
{
if(CurSymbol->next)
CurSymbol=CurSymbol->next;
else
{
error(43); //语法分析没有完毕,需要标识符
exit(3);
}
}
void destroySymbols() //编译完毕,将符号链表释放
{
SymbolItem *current,*needDel;
current=Symbols;
while(current)
{
needDel=current;
current=current->next;
delete needDel;
}
}
/////////////下面这三个函数是为了模拟pascal源程序中的set类型而开发的////////////
SYMLIST * listsAdd(SYMLIST * list1,SYMLIST * list2) //两个“集合”相加,返回一个“集合”
{
SYMLIST * temp=new SYMLIST;
COPYLIST(temp,list1);
temp->AddTail(list2);
return temp;
}
SYMLIST * listAddSym(SYMLIST * list,SYMBOL sym) //一个“集合”加上一个“元素”,返回一个“集合”
{
SYMLIST * temp=new SYMLIST;
COPYLIST(temp,list);
temp->AddTail(sym);
return temp;
}
int SYMINLIST(SYMBOL sym,SYMLIST * list) //判断一个“元素”是否在“集合”里面
{
for(POSITION pos=list->GetHeadPosition();pos;)
{
SYMBOL temp;
temp=list->GetNext(pos);
if(temp==sym)
return 1; //如果在,返回非零
}
return 0; //不在,则返回零
}
void COPYLIST(SYMLIST * list1,SYMLIST * list2) //“集合”之间的拷贝
{
for(POSITION pos=list2->GetHeadPosition();pos;)
{
SYMBOL temp;
temp=list2->GetNext(pos);
list1->AddTail(temp);
}
}
///////////////////// 主程序 ///////////////////////
int main(int argc, char* argv[])
{
char srcFilename[FILENAMESIZE];
FILE *srcFile;
char *srcFileNamePoint;
if(argc>1)
strcpy(srcFilename,argv[1]);
else
{
printf("Please input the source file name : ");
scanf("%s",srcFilename);
}
if(!(srcFile=fopen(srcFilename,"rb")))
{
printf("Error : source file %s not found\n",srcFilename);
exit(1);
}
printf("\n第一遍:词法分析");
getSymbols(srcFile);//第一遍,取得所有的符号,第二遍才开始语法分析和代码生成
printf("第二遍:语法分析和代码生成\n");
INITIAL(); //初始化
ENTERPREID(); //预填符号表
printf("\n************** 下面是部分的生成代码 ***************\n\n");
if (CurSymbol->type!=PROGRAMSYM)
error(13); //应该是'program'
getASymbol();
if(CurSymbol->type!=IDENT)
error(14); //应该是标识符
getASymbol();
if(CurSymbol->type!=SEMICOLON)
error(1); //应该是';'
else
getASymbol();
//////////////////////////////////////////////////////////
SYMLIST * tempList3=new SYMLIST;
COPYLIST(tempList3,listsAdd(listAddSym(&DECLBEGSYS,PERIOD),&STATBEGSYS));
BLOCK(tempList3,0);
delete tempList3;
//////////////////////////////////////////////////////////
if(CurSymbol->type!=PERIOD)
error(8); //应该是'.'
if(nError==0)
{
for(srcFileNamePoint=&srcFilename[strlen(srcFilename)];*srcFileNamePoint!='.' && srcFileNamePoint!=srcFilename;srcFileNamePoint--)
;
*srcFileNamePoint=0; //删除后面的扩展名
WriteCodeList(strcat(srcFilename,".lst"));
for(srcFileNamePoint=&srcFilename[strlen(srcFilename)];*srcFileNamePoint!='.' && srcFileNamePoint!=srcFilename;srcFileNamePoint--)
;
*srcFileNamePoint=0; //删除后面的扩展名
WriteObjCode(strcat(srcFilename,".pld"));
for(srcFileNamePoint=&srcFilename[strlen(srcFilename)];*srcFileNamePoint!='.' && srcFileNamePoint!=srcFilename;srcFileNamePoint--)
;
*srcFileNamePoint=0; //删除后面的扩展名
WriteLabelCode(strcat(srcFilename,".lab"));
destroySymbols();
fclose(srcFile);
//printf("\n编译成功!请输入任何字符退出。");
printf("\n编译成功!");
int a=0;
scanf("%d",a); //一个简单的关卡,程序执行完毕后可以停下,您可以观看生成的代码,注意,代码是部分的,有些操作数没有填上去
return 0;
}
destroySymbols();
int b=0;
scanf("%d",b); //一个简单的关卡,程序执行完毕后可以停下,您可以观看生成的代码,注意,代码是部分的,有些操作数没有填上去
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -