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