?? util.cpp
字號(hào):
/****************************************************/
/* 文件 util.cpp */
/* 說(shuō)明 類(lèi)PASCAL語(yǔ)言編譯器功能函數(shù)的實(shí)現(xiàn) */
/* 主題 編譯器結(jié)構(gòu):原理和實(shí)例 */
/****************************************************/
/* 頭文件globals.h定義了全局類(lèi)型與變量 */
#include "globals.h"
#include "stdio.h"
#include "string.h"
#include "symbTable.h"
#include "code.h"
#include "cgen.h"
int fp_num=0; /*輸出時(shí)記錄token個(gè)數(shù)的變量*/
/*****************************************************************/
/* 函數(shù)名 printTokenlist */
/* 功 能 將文件tokenlist中的信息作為返回值 */
/* 一般,listing指向標(biāo)準(zhǔn)輸出。 */
/* 說(shuō) 明 用于顯示詞法分析結(jié)果 */
/*****************************************************************/
void printTokenlist()
{
TokenType token;
int m;
fp=fopen("c:\\Tokenlist","rb"); /*打開(kāi)文件*/
if(fp==NULL)
{
printf("can not open the file:Tokenlist!\n");
Error = TRUE;
//exit(0);
}
for (m=1;m<=Tokennum;m++)
{
fread(&token,TOKENLEN,1,fp);
fprintf(listing,"\t%d: ",token.lineshow);/*打印行號(hào)*/
/* 對(duì)函數(shù)參數(shù)Lex給定單詞進(jìn)行分類(lèi)處理 */
switch (token.Lex)
{
/* 單詞token為保留字,將保留字詞元以指定格式寫(xiě)入列表文件listing */
case PROGRAM:
case PROCEDURE:
case TYPE:
case VAR:
case IF:
case THEN:
case ELSE:
case FI:
case INTEGER:
case CHAR:
case WHILE:
case DO:
case ENDWH:
case BEGIN:
case END:
case READ:
case WRITE:
case ARRAY:
case OF:
case RECORD:
case RETURN:
fprintf(listing, /*打印保留字*/
"reserved word: %s\n",token.Sem);
break;
/* 單詞token為特殊符號(hào):ASSIGN (賦值),將":="寫(xiě)入文件listing */
case ASSIGN: fprintf(listing,":=\n"); break;
/* 單詞token為特殊符號(hào):LT (小于),將"<"寫(xiě)入文件listing */
case LT: fprintf(listing,"<\n"); break;
/* 單詞token為特殊符號(hào):EQ (等于),將"="寫(xiě)入文件listing */
case EQ: fprintf(listing,"=\n"); break;
/* 單詞token為特殊符號(hào):LPAREN (左括號(hào)),將"("寫(xiě)入文件listing */
case LPAREN: fprintf(listing,"(\n"); break;
/* 單詞token為特殊符號(hào):RPAREN (右括號(hào)),將")"寫(xiě)入文件listing */
case RPAREN: fprintf(listing,")\n"); break;
/* 單詞token為特殊符號(hào):SEMI (分號(hào)),將";"寫(xiě)入文件listing */
case SEMI: fprintf(listing,";\n"); break;
/* 單詞token為特殊符號(hào):PLUS (加號(hào)),將"+"寫(xiě)入文件listing */
case PLUS: fprintf(listing,"+\n"); break;
/* 單詞token為特殊符號(hào);MINUS (減號(hào)),將"-"寫(xiě)入文件listing */
case MINUS: fprintf(listing,"-\n"); break;
/* 單詞token為特殊符號(hào):TIMES (乘號(hào)),將"*"寫(xiě)入文件listing */
case TIMES: fprintf(listing,"*\n"); break;
/* 單詞token為特殊符號(hào):OVER (除號(hào)),將"/"寫(xiě)入文件listing */
case OVER: fprintf(listing,"/\n"); break;
case DOT: fprintf(listing,".\n"); break;
case COMMA: fprintf(listing,",\n"); break;
case LMIDPAREN: fprintf(listing,"[\n"); break;
case RMIDPAREN: fprintf(listing,"]\n"); break;
case UNDERANGE: fprintf(listing,"..\n"); break;
/* 單詞token為簿記單詞符號(hào):ENDFILE (文件結(jié)尾),將EOF寫(xiě)入文件listing */
case ENDFILE: fprintf(listing,"EOF\n"); break;
/* 單詞token為多字符單詞符號(hào):NUM (數(shù)字),將數(shù)值寫(xiě)入文件listing */
case INTC:
fprintf(listing,
"NUM, val= %s\n",token.Sem);
break;
case CHARC:
fprintf(listing,
"INCHAR, char=%c\n",token.Sem);
break;
/* 單詞token為多字符單詞符號(hào):ID (標(biāo)識(shí)符),將標(biāo)識(shí)符名寫(xiě)入文件listing */
case ID:
fprintf(listing,
"ID, name= %s\n",token.Sem);
break;
/* 單詞token為簿記單詞符號(hào):ERROR (錯(cuò)誤),將錯(cuò)誤信息寫(xiě)入文件listing */
case ERROR:
fprintf(listing,
"ERROR: %s\n",token.Sem);
break;
/* 單詞token為其他未知單詞,未知信息寫(xiě)入文件listing,此種情況不應(yīng)發(fā)生 */
default:
fprintf(listing,"Unknown token: %d\n",token.Lex);
break;
}
fseek(fp,m*TOKENLEN,0);
}
fprintf(listing,"\n");
fclose(fp);
}
/*****************************************************************/
/* 函數(shù)名 ReadNextToken */
/* 功 能 將文件tokenlist中的信息作為返回值 */
/* 一般,listing指向標(biāo)準(zhǔn)輸出。 */
/* 說(shuō) 明 返回值為T(mén)okenType類(lèi)型,用于語(yǔ)法分析中 */
/*****************************************************************/
void ReadNextToken(TokenType *p)
{
FILE *fp2;
/*按只讀方式打開(kāi)文件*/
fp2=fopen("c:\\Tokenlist","rb");
if (fp==NULL)
{
printf("cannot create file Tokenlist!\n");
Error = TRUE;
//exit(0);
}
fseek(fp2,fp_num*sizeof(TokenType),0);
fread(p,sizeof(TokenType),1,fp2);
fp_num++;
fclose(fp2);
}
/********************************************************/
/* 函數(shù)名 copyString */
/* 功 能 字符串復(fù)制函數(shù) */
/* 說(shuō) 明 該函數(shù)為已存在的字串分配內(nèi)存單元,并將其復(fù)制 */
/********************************************************/
char * copyString(char * s)
{ int n;
char * t;
/* 函數(shù)參數(shù)s所給字串為NULL(空), 函數(shù)返回NULL */
if (s==NULL) return NULL;
/* 函數(shù)參數(shù)s所給字串非空,計(jì)算字串s長(zhǎng)度+1賦給臨時(shí)變量n */
n = strlen(s)+1;
/* 動(dòng)態(tài)分配內(nèi)存單元,指定單元長(zhǎng)度為n,t為指向該單元的指針 */
t = (char *)malloc(n);
/* 單元指針t為NULL(空),未能成功分配 *
* 將出錯(cuò)信息及行號(hào)lineno寫(xiě)入列表文件listing */
if (t==NULL)
{
fprintf(listing,"Out of memory error at line %d\n",lineno);
Error = TRUE;
}
/* 調(diào)用庫(kù)函數(shù)string.h,復(fù)制給定字串s到新字串單元t */
else strcpy(t,s);
/* 函數(shù)返回復(fù)制得到的新字串指針t */
return t;
}
/*****************************************************************/
/* 函數(shù)名 ChainToFile */
/* 功 能 將鏈表中的Token結(jié)點(diǎn)依次存入文件中 */
/* 說(shuō) 明 參數(shù)p是指針變量,指向Token鏈表的表頭 */
/*****************************************************************/
void ChainToFile (ChainNodeType *Chainhead)
{
int num=1;
ChainNodeType *currentP=Chainhead;
/*創(chuàng)建一個(gè)新的文件"Tokenlist",以存儲(chǔ)Token序列*/
fp=fopen("c:\\Tokenlist","wb+");
if (fp==NULL)
{ printf("cannot create file Tokenlist!\n");
Error = TRUE;
//exit(0);
}
fp=fopen("c:\\Tokenlist","ab"); /*按追加方式打開(kāi)文件*/
if (fp==NULL)
{ printf("cannot open file Tokenlist!\n");
Error = TRUE;
//exit(0);
}
/*從表頭到表尾,依次將所有的Token寫(xiě)入文件*/
do
{ fwrite(currentP,TOKENLEN,1,fp);
currentP=currentP->nextToken;
num++;
}
while (currentP!=NULL);
fclose(fp); /*關(guān)閉文件*/
}
/********************************************************
*********以下是LL1語(yǔ)法分析方法所用到的棧操作************
********************************************************/
/*用鏈表實(shí)現(xiàn)棧操作,棧中存放的是終極符和非終極符,上面的兩個(gè)枚舉
類(lèi)型*/
void Push(int i,int j)
{ StackNode *p;
p=(StackNode *)malloc(sizeof(StackNode));
if (i==1)
(*p).var.Ntmlvar=(NontmlType)j;
else if (i==2)
(*p).var.tmlvar=(TmlType)j;
p->flag=i;
p->underNode=StackTop;
StackTop=p;
STACKEMPTY=false;
}
void Pop()
{ StackNode *p;
p=StackTop;
StackTop=(*StackTop).underNode;
free(p);
if (StackTop==NULL)
STACKEMPTY=true;
}
/*讀棧頂標(biāo)志,看是終極符還是非終極符*/
int readStackflag()
{ int j;
j=StackTop->flag ;
return(j);
}
/*非終極符時(shí)*/
NontmlType readstackN()
{
return ((*StackTop).var.Ntmlvar);
}
/*終極符*/
TmlType readstackT()
{
return ((*StackTop).var.tmlvar);
}
/*壓棧的實(shí)現(xiàn)過(guò)程,壓入的是指向樹(shù)節(jié)點(diǎn)的指針的地址*/
void PushPA(TreeNode **t)
{
StackNodePA *p=NULL;
p=(StackNodePA *)malloc (sizeof(StackNodePA));
p->pointer= t ;
p->underNode =StackTopPA;
StackTopPA=p;
paSTACKEMPTY=false;
}
/*彈棧的實(shí)現(xiàn)過(guò)程*/
TreeNode ** PopPA()
{
StackNodePA *p=NULL;
TreeNode **backpointer;
p = StackTopPA;
backpointer=p ->pointer;
StackTopPA=StackTopPA->underNode;
free(p);
if (StackTopPA==NULL)
paSTACKEMPTY=true;
return backpointer;
}
/*操作符棧的壓棧實(shí)現(xiàn)過(guò)程,壓入的是指向樹(shù)節(jié)點(diǎn)的指針*/
void PushOp(TreeNode *t)
{
StackNodeP *p=NULL;
p=(StackNodeP *)malloc (sizeof(StackNodeP));
p->pointer= t ;
p->underNode =OpStackTop;
OpStackTop=p;
OpSTACKEMPTY=FALSE;
}
/*操作符棧的彈棧實(shí)現(xiàn)過(guò)程*/
TreeNode * PopOp()
StackNodeP *p=NULL;
TreeNode *backpointer;
p=OpStackTop;
backpointer=p->pointer;
OpStackTop=OpStackTop->underNode;
free(p);
if (OpStackTop==NULL)
OpSTACKEMPTY= TRUE;
return backpointer;
}
LexType ReadOpStack()
{
TreeNode *t1;
t1=OpStackTop->pointer;
return (t1->attr.ExpAttr.op);
}
/*操作數(shù)棧的壓棧實(shí)現(xiàn)過(guò)程,壓入的是指向樹(shù)節(jié)點(diǎn)的指針*/
void PushNum(TreeNode *t)
{
StackNodeP *p=NULL;
p =(StackNodeP *)malloc (sizeof(StackNodeP));
p->pointer= t ;
p->underNode =NumStackTop;
NumStackTop=p;
NumSTACKEMPTY=false;
}
/*操作數(shù)棧的彈棧實(shí)現(xiàn)過(guò)程*/
TreeNode * PopNum()
{
StackNodeP *p=NULL;
TreeNode *backpointer;
p =NumStackTop;
backpointer=p->pointer;
NumStackTop=NumStackTop->underNode;
free(p);
if (NumStackTop==NULL)
NumSTACKEMPTY=true;
return backpointer;
}
/********************************************************
*********以下是創(chuàng)建語(yǔ)法樹(shù)所用的各類(lèi)節(jié)點(diǎn)的申請(qǐng)***********
********************************************************/
/********************************************************/
/* 函數(shù)名 newRootNode */
/* 功 能 創(chuàng)建語(yǔ)法樹(shù)根節(jié)點(diǎn)函數(shù) */
/* 說(shuō) 明 該函數(shù)為語(yǔ)法樹(shù)創(chuàng)建一個(gè)新的根結(jié)點(diǎn) */
/* 并將語(yǔ)法樹(shù)節(jié)點(diǎn)成員初始化 */
/********************************************************/
TreeNode * newRootNode(void)
{
/* 在內(nèi)存中動(dòng)態(tài)申請(qǐng)分配單元,返回指向該單元的語(yǔ)法樹(shù)結(jié)點(diǎn)類(lèi)型指針t */
TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
/* 語(yǔ)法樹(shù)節(jié)點(diǎn)指針t為NULL,未能成功分配內(nèi)存單元 *
* 將出錯(cuò)信息及行號(hào)lineno寫(xiě)入列表文件listing */
if (t==NULL)
{
fprintf(listing,"Out of memory error at line %d\n",lineno);
Error = TRUE;
}
/* 語(yǔ)法樹(shù)節(jié)點(diǎn)指針t不是NULL,成功分配內(nèi)存單元 */
else {
/* 初始化新語(yǔ)法樹(shù)節(jié)點(diǎn)t各子節(jié)點(diǎn)child[i]為NULL */
for (i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;
/* 初始化新語(yǔ)法樹(shù)節(jié)點(diǎn)t兄弟節(jié)點(diǎn)sibling為NULL */
t->sibling = NULL;
/* 指定新語(yǔ)法樹(shù)節(jié)點(diǎn)t成員:結(jié)點(diǎn)類(lèi)型nodekind為語(yǔ)句類(lèi)型ProK */
t->nodekind = ProK;
/* 指定新語(yǔ)法樹(shù)節(jié)點(diǎn)t成員:源代碼行號(hào)lineno為全局變量lineno */
t->lineno = lineno;
for(i=0;i<10;i++)
{
strcpy(t->name[i],"\0");
t->table[i] = NULL;
}
}
/* 函數(shù)返回語(yǔ)法樹(shù)根節(jié)點(diǎn)指針t */
return t;
}
/********************************************************/
/* 函數(shù)名 newPheadNode */
/* 功 能 創(chuàng)建程序頭類(lèi)型語(yǔ)法樹(shù)節(jié)點(diǎn)函數(shù) */
/* 說(shuō) 明 該函數(shù)為語(yǔ)法樹(shù)創(chuàng)建一個(gè)新的程序頭類(lèi)型結(jié)點(diǎn) */
/* 并將語(yǔ)法樹(shù)節(jié)點(diǎn)成員初始化 */
/********************************************************/
TreeNode * newPheadNode(void)
{
/* 在內(nèi)存中動(dòng)態(tài)申請(qǐng)分配單元,返回指向該單元的語(yǔ)法樹(shù)結(jié)點(diǎn)類(lèi)型指針t */
TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
/* 語(yǔ)法樹(shù)節(jié)點(diǎn)指針t為NULL,未能成功分配內(nèi)存單元 *
* 將出錯(cuò)信息及行號(hào)lineno寫(xiě)入列表文件listing */
if (t==NULL)
{
fprintf(listing,"Out of memory error at line %d\n",lineno);
Error = TRUE;
}
/* 語(yǔ)法樹(shù)節(jié)點(diǎn)指針t不是NULL,成功分配內(nèi)存單元 */
else {
/* 初始化新語(yǔ)法樹(shù)節(jié)點(diǎn)t各子節(jié)點(diǎn)child[i]為NULL */
for (i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;
/* 初始化新語(yǔ)法樹(shù)節(jié)點(diǎn)t兄弟節(jié)點(diǎn)sibling為NULL */
t->sibling = NULL;
/* 指定新語(yǔ)法樹(shù)節(jié)點(diǎn)t成員:結(jié)點(diǎn)類(lèi)型nodekind為語(yǔ)句類(lèi)型PheadK */
t->nodekind = PheadK;
/* 指定新語(yǔ)法樹(shù)節(jié)點(diǎn)t成員:源代碼行號(hào)lineno為全局變量lineno */
t->lineno = lineno;
t->idnum = 0;
for(i=0;i<10;i++)
{
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -