?? pl0.cpp
字號:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "stdarg.h"
#define NORW 20 // 保留字的個數
#define TXMAX 100 // 標識符表的長度
#define MAXNUMLEN 14 // 數字的最長位數
#define MAXIDLEN 10 // 標識符最長長度
#define MAXADDRESS 2047 // 尋址空間
#define MAXLEVEL 3 // 最大允許的塊嵌套層數
#define CXMAX 200 // 類PCODE目標代碼數組長度
#define NSYM 10 // 符號的個數
#define MAXSYM 30 // symbols的最大個數
#define STACKSIZE 500 // 常量定義,假想的棧式計算機有500個棧單元
#define MAXINS 10
enum idtype //idtype標識符的類型
{
ID_CONSTANT, ID_VARIABLE, ID_PROCEDURE
};
enum opcode //opcode類型分別標識類PCODE的各條指令
{
LIT, OPR, LOD, STO, CAL, INT, JMP, JPC, RED, WRT
};
enum oprcode
{
OPR_RET, OPR_NEG, OPR_ADD, OPR_MIN,
OPR_MUL, OPR_DIV, OPR_ODD, OPR_EQU,
OPR_NEQ, OPR_LSS, OPR_LEQ, OPR_GTR,
OPR_GEQ
};
enum symtype //symset是symbol類型的一個集合類型,可用于存放一組symbol,symobl類型標識了不同類型的詞匯
{
SYM_NULL, // 0
SYM_IDENTIFIER, // 1
SYM_NUMBER, // 2
SYM_PLUS, // 3 +
SYM_MINUS, // 4 -
SYM_TIMES, // 5 *
SYM_SLASH, // 6 /
SYM_ODD, // 7 odd
SYM_EQU, // 8 =
SYM_NEQ, // 9 <>
SYM_LSS, // 10 <
SYM_LEQ, // 11 <=
SYM_GTR, // 12 >
SYM_GEQ, // 13 >=
SYM_LPAREN, // 14 (
SYM_RPAREN, // 15 )
SYM_COMMA, // 16 ,
SYM_SEMICOLON, // 17 ;
SYM_PERIOD, // 18 .
SYM_BECOMES, // 19 :=
SYM_BEGIN, // 20 begin
SYM_END, // 21 end
SYM_IF, // 22 if
SYM_THEN, // 23 then
SYM_WHILE, // 24 while
SYM_DO, // 25 do
SYM_CALL, // 26 call
SYM_CONST, // 27 const
SYM_VAR, // 28 var
SYM_PROCEDURE, // 29 procedure
SYM_READ, // 30 read
SYM_WRITE, // 31 write
SYM_ELSE, // 32 else
SYM_DOWNTO, // 33 downto
SYM_BY, // 34 by
SYM_TO, // 35 to
SYM_FOR, // 36 for
SYM_REPEAT, // 37 repeat
SYM_UNTIL // 38 until
};
typedef struct //類PCODE指令類型,包含三個字段:指令f、層差l和另一個操作數a
{
int f; // 指令
int l; // 層差
int a; // 操作數
} instruction;
/*************************************************************************/
char* err_msg[] =
{
/* 0 */ "",
/* 1 */ "常數說明中的\"=\"寫成\":=\"!",
/* 2 */ "常數說明中的\"=\"后應是數字!",
/* 3 */ "常數說明中標識符后應是\"=\"!",
/* 4 */ "'const', 'var', 'procedure'后應為標識符!",
/* 5 */ "漏掉了\',\' 或\';\'!",
/* 6 */ "過程說明后的符號不正確(應是語句開始符,或過程定義符)!",
/* 7 */ "應是語句開始符!",
/* 8 */ "程序體內語句部分后的符號不正確!",
/* 9 */ "程序結尾丟了句號\'.\'!",
/* 10 */ "語句之間漏';'!",
/* 11 */ "標識符未說明!",
/* 12 */ "賦值語句中, 賦值號左部標識符屬性應是變量,不可向常量或過程賦值!",
/* 13 */ "賦值語句左部標識符后應是賦值號\':=\'!",
/* 14 */ "'call'后應為標識符!",
/* 15 */ "不可調用常量或變量.",
/* 16 */ "條件語句中丟了\'then\'!",
/* 17 */ "丟了\'end\' 或\';\'!",
/* 18 */ "while 型循環語句中丟了\'do\'!",
/* 19 */ "語句后的符號不正確!",
/* 20 */ "應為關系運算符!",
/* 21 */ "表達式內標識符屬性不能是過程!",
/* 22 */ "表達式中漏掉右括號\')\'!",
/* 23 */ "因子后的非法符號!",
/* 24 */ "表達式不能以此符號開始!",
/* 25 */ "“for”后應為變量標識符",
/* 26 */ "缺少“to”或“downto”",
/* 27 */ "應為“do”或“by”",
/* 28 */ "應為“do”",
/* 29 */ "repeat 型循環語句中沒有until!",
/* 30 */ "數值過大",
/* 31 */ "編譯器溢出",
/* 32 */ "過程嵌套過深",
/* 33 */ "read語句括號中的標識符不是變量!",
/* 34 */ "應當為右括號",
/* 35 */ "應為負數",
/* 36 */ "應為正數",
/* 40 */ "應當為左括號"
};
/*************************************************************************/
//全局變量定義
char ch; // 主要用于詞法分析器,存放最近一次從文件中讀出的字符
int sym; // 詞法分析器輸出結果之用,存放最近一次識別出來的token的類型
char id[MAXIDLEN + 1]; // 詞法分析器輸出結果之用,存放最近一次識別出來的標識符的名字
int num; // d詞法分析器輸出結果之用,存放最近一次識別出來的數字的值
int cc; // 行緩沖區指針
int ll; // 行緩沖區長度
int err;
int cx; //代碼分配指針,代碼生成模塊總在cx所指位置生成新的代碼
int level = 0;
int tx = 0;
char line[80]; //行緩沖區,用于從文件讀出一行,供詞法分析獲取單詞時之用
int dx; //全局變量
instruction code[CXMAX]; //生成的類PCODE代碼表,存放編譯得到的類PCODE代碼
char* word[NORW +1] = //保留字表
{
"","begin", "call", "const", "do", "end",
"if","odd", "procedure", "then", "var", "while",
"read", "write", "else","downto","by","to","for",
"repeat", "until"
};
int wsym[NORW +1] = //保留字表中每一個保留字對應的symbol類型
{
SYM_NULL, SYM_BEGIN, SYM_CALL, SYM_CONST, SYM_DO, SYM_END,
SYM_IF, SYM_ODD, SYM_PROCEDURE, SYM_THEN, SYM_VAR, SYM_WHILE,
SYM_READ, SYM_WRITE, SYM_ELSE,SYM_DOWNTO,SYM_BY,SYM_TO,SYM_FOR,
SYM_REPEAT, SYM_UNTIL
};
int ssym[NSYM + 1] = //一些符號對應的symbol類型表
{
SYM_NULL, SYM_PLUS, SYM_MINUS, SYM_TIMES, SYM_SLASH,
SYM_LPAREN, SYM_RPAREN, SYM_EQU, SYM_COMMA, SYM_PERIOD, SYM_SEMICOLON
};
char csym[NSYM + 1] =
{
' ', '+', '-', '*', '/', '(', ')', '=', ',', '.', ';'
};
char* mnemonic[MAXINS] =
{
"LIT", "OPR", "LOD", "STO", "CAL", "INT", "JMP", "JPC", "RED", "WRT"
};
typedef struct
{
char name[MAXIDLEN + 1];
int kind;
int value;
} comtab;
comtab table[TXMAX];
typedef struct
{
char name[MAXIDLEN + 1];
int kind;
short level;
short address;
} mask;
FILE* infile, *outfile;//in文本文件用于指向輸入的源程序文件,out程序中沒有用到
typedef struct snode
{
int elem;
struct snode* next;
}snode, *symset;
symset phi, declbegsys, statbegsys, facbegsys, relset; //定義的結構體symset的變量
symset uniteset(symset s1, symset s2)
{
symset s;
snode* p;
s = p = (snode*) malloc(sizeof(snode));
s1 = s1->next;
s2 = s2->next;
while (s1 && s2)
{
p->next = (snode*) malloc(sizeof(snode));
p = p->next;
if (s1->elem < s2->elem)
{
p->elem = s1->elem;
s1 = s1->next;
}
else
{
p->elem = s2->elem;
s2 = s2->next;
}
}
if (s2)
s1 = s2;
while (s1)
{
p->next = (snode*) malloc(sizeof(snode));
p = p->next;
p->elem = s1->elem;
s1 = s1->next;
}
p->next = NULL;
return s;
}
void setinsert(symset s, int elem)
{
snode* p = s;
snode* q;
while (p->next && p->next->elem < elem)
p = p->next;
q = (snode*) malloc(sizeof(snode));
q->elem = elem;
q->next = p->next;
p->next = q;
}
symset createset(int elem, ...)
{
va_list list;
symset s;
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);
return s;
}
void destroyset(symset s) //釋放空間
{
snode* p;
while (s)
{
p = s;
s = s->next;
free(p);
}
}
int inset(int elem, symset s)
{
s = s->next;
while (s && s->elem < elem)
s = s->next;
if (s && s->elem == elem)
return 1;
else
return 0;
}
void showset(symset s) //輸出
{
s = s->next;
while (s)
{
printf("%d,", s->elem);
s = s->next;
}
printf("\n");
}
/*************************************************************************/
void error(int); //出錯處理
void getsym(void); //詞法分析,讀取一個單詞
void getch(void); //讀取字符
void gen(int, int, int); //生成Pcode指令,送入目標程序區
void listcode(int, int); //列出Pcode指令清單
void test(symset, symset, int n); //測試當前單詞符號是否合法
void enter(int); //登錄名字表
int position(char*); //查找標識符在名字表中的位置
void constdeclaration(); //常量定義處理
void vardeclaration(void); //變量說明處理
void block(symset fsys); //分程序分析處理
void statement(symset); //語句部分分析處理
void expression(symset); //表達式分析處理
void term(symset); //項分析處理
void factor(symset); //因子分析處理
void condition(symset); //條件分析處理
void interpret(); //Pcode解釋執行程序
int base(int stack[], int, int); //通過靜態鏈求出數據區的基地址
/*************************************************************************/
int main () //主程序
{
char s[80],*finddot;
//int i;
symset set0, set1, set2;
printf("請輸入要編譯的源文件名(文件名+文件后綴): ");
scanf("%s", s);
if ((infile = fopen(s, "r")) == NULL) //判斷讀入文件是否為空
{
printf("文件 %s 不能打開!\n", s);
exit(1);
}
finddot = strchr(s,'.'); // 打開輸出文件
if (finddot!=NULL)
{
strcpy(finddot, ".out"); //將字符指針的內容拷貝到與源文件同名的后綴名為.out的文件內
}
else
{
strcat(s, ".out");
printf("%s\n", s);
}
printf("輸出文件是 %s\n", s);
if ((outfile = fopen(s, "w")) == NULL)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -