⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pl0.h

📁 本程序实现编译原理中
💻 H
字号:
#include<math.h>
//bool数据块
typedef enum{
	false,
	true
}bool;

#define	NUM_OF_KEYWORD			17			/*关键字个数,包括13个保留字和三个三角函数(cos,sin,tan),一个指数函数(exp)*/
#define	NUM_OF_TABLE			100			/*名字表容量*/
#define	MAX_NUM_LENGTH			14			/*具体数值number的最大位数*/
#define MAX_IDENT_LENGTH		10			/*符号的最大长度*/
#define UPPER_LIMIT_ADDRESS		2047		/*地址上界*/
#define MAX_LEVEL				3			/*最大嵌套层数*/
#define	MAX_CODE_NUM			200			/*最多的虚拟机代码数*/

/*符号*/
enum symbol{nul,		ident,		number,		plus,		minus,
			times,		slash,		oddsym,		eql,		neq,
			lss,		leq,		gtr,		geq,		lparen,
			rparen,		comma,		semicolon,	period,		becomes,
			beginsym,	endsym,		ifsym,		thensym,	whilesym,
			writesym,	readsym,	dosym,		callsym,	constsym,
			varsym,		procsym,	cossym,		sinsym,		tansym,
			expsym
};
/*符号的个数*/
#define	symnum	36
/*名字表中的类型:常量,变量,过程*/ 
enum object{
	constant,
	variable,
	procedur
};
/*虚拟机代码(指令)*/
enum fac{
	lit,		opr,		lod,
	sto,		cal,		inte,
	jmp,		jpc,		fun
};
/*
					指令解释(lev:调用层与声明层的层差)
lit lev a:将常量值(a)放在栈顶;
opr 0 number:number=0 表示返回调用点并退栈,
				=1 栈顶值取反放在栈顶
		        =2 执行次栈顶与栈顶相加,两者出栈,和入栈
				=3 ..................减,........,差....
				=4 ..................乘,........,积....
				=5 ..................商,........,商....
			2--5中,注意次栈顶(前)与栈顶的顺序(后)
				=6 对栈顶值做奇偶判断,奇为真,结果放在栈顶
				=8 次栈顶与栈顶是否相等,退两栈元素,结果入栈
				=k k为9:次栈顶与栈顶不等,10:次栈顶小于栈顶,11:次栈顶大于等于栈顶,12:次栈顶大于栈顶,13:次栈顶小于等于栈顶
				=14栈顶值输出到屏幕
				=15屏幕输出换行
				=16从命令行读入一个输入到栈顶
lod lev a:将变量放到栈顶(a:地址偏移量)
sto lev a:将栈顶值送入某个变量(a:地址偏移量)
cal lev a:调用过程(a:过程地址)
inte lev a:在运行栈中为被调用的过程开辟a个单元数据区
jmp lev a:无条件转到a
jpc lev a:栈顶布尔值非真转到a,否则顺序执行
fun lev a:a=0:cos,a=1:sin,a=2:tan,a=3:exp
*/
/*指令个数*/
#define	fctnum	9
/*虚拟机代码结构*/
struct instruction
{
	enum fac f;								/*虚拟机代码指令*/
	int l;									/*引用层与说明层的层次差*/
	int a;									/*根据 f的不同而不同*/
};

FILE*	fas;								/*输出名字表*/
FILE*	fa;									/*输出虚拟机代码*/
FILE*	fa1;								/*输出源文件及其各行对应的首地址*/
FILE*	fa2;								/*输出结果*/

bool listswitch;							/*显示虚拟机代码与否*/
bool tableswitch;							/*显示名字表与否*/

char ch;									/*获取字符的缓冲区,getch使用*/
enum symbol sym;							/*当前的符号*/
char id[MAX_IDENT_LENGTH+1];				/*当前的ident(标识符),多出的一个字节用于存放0*/
int num;									/*当前的number*/
int cc,ll;									/*getch使用的计数器,cc表示当前字符(ch)的位置*/
/*
sym:存放单词的类别(ident:标识符)
   如:initial:= 60;中各单词对应的类别为:
   initial ident,  ‘:=‘ becomes,  60 number,  ‘;’ semicolon
id:存放用户标识符,对initial(sym<-ident,id<-initial)
num:存放用户定义的数  对60(sym<-number,num<-60)

*/
int cx;										/*虚拟代码指针,取值范围[0,MAX_CODE_NUM-1]*/
char line[81];								/*读取行缓冲器,getch使用*/
char a[MAX_IDENT_LENGTH+1];					/*临时符号,多出的一个字节用于存放0*/
struct instruction code[MAX_CODE_NUM];		/*存放虚拟机代码的数组*/
char word[NUM_OF_KEYWORD][MAX_IDENT_LENGTH];/*存放保留字的数组*/
enum symbol wsym[NUM_OF_KEYWORD];			/*保留字对应的符号值*/
enum symbol ssym[256];						/*单字符的符号值*/
char mnemonic[fctnum][5];					/*虚拟机代码指令名称*/
bool declbegsys[symnum];					/*表示声明开始的符号集合*/
bool statbegsys[symnum];					/*表示语句开始的符号集合*/
bool facbegsys[symnum];						/*表示因子开始的符号集合*/
int numlen;									/*数字长度 add by daka*/

//名字表中存放所有标识符(常量、变量、过程名)
struct tablestruct
{
	char name[MAX_IDENT_LENGTH];//标识符的名字
	enum object kind;//类型
	int val;//值(仅const使用)
	int level;//所在的层(仅const不使用)
	int adr;//地址(仅const不使用)
	int size;//需要分配的数据空间,仅procedure使用
};
struct tablestruct table[NUM_OF_TABLE];//名字表

FILE* fin;//fin文本文件用于指向输入的源程序文件
FILE* fout;
char fname[MAX_IDENT_LENGTH];//存放PL/0源程序文件的文件名
int err;//错误计数器

/*
如果在某一层的处理过程中发生了错误
例如:在没有遇到句点的情况下文件结束、
或产生的代码太长以致超出了code数组的长度
都会返回-1,表示处理出错!这时编译程序会从
出错层逐层往外跳,直到跳到主函数中,结束了编译程序的生命。
*/
#define getsymdo					if(-1==getsym()) return -1
#define getchdo						if(-1==getch()) return -1
#define	testdo(a,b,c)				if(-1==test(a,b,c)) return -1
#define gendo(a,b,c)				if(-1==gen(a,b,c)) return -1
#define expressiondo(a,b,c)			if(-1==expression(a,b,c))return -1
#define factordo(a,b,c)				if(-1==factor(a,b,c)) return -1
#define termdo(a,b,c)				if(-1==term(a,b,c)) return -1
#define conditiondo(a,b,c)			if(-1==condition(a,b,c)) return -1
#define statementdo(a,b,c)			if(-1==statement(a,b,c)) return -1
#define constdeclarationdo(a,b,c)	if(-1==constdeclaration(a,b,c)) return -1
#define vardeclarationdo(a,b,c)		if(-1==vardeclaration(a,b,c)) return -1
#define funcdo(a,b,c)				if(-1==func(a,b,c)) return -1
void error(int n);//出错处理,打印出错位置与错误编码
int getsym();//词法分析,读取一个单词或数字串
int getch();//漏掉空格,读取一个单词
void init();//初始化变量
int gen(enum fac x,int y,int z);//生成目标代码,并送入目标程序区
int test(bool* s1,bool* s2,int n);//测试当前单词符号是否合法
int inset(int e,bool* s);//
int addset(bool* sr,bool* s1,bool* s2,int n);
int subset(bool* sr,bool* s1,bool* s2,int n);
int mulset(bool* sr,bool* s1,bool* s2,int n);
int block(int lev,int tx,bool* fsys);//分程序分析处理过程
void interpret();//对目标代码解释执行
int factor(bool* fsys,int *ptx,int lev);//因子处理
int func(bool* fsys,int *ptx,int lev);
int term(bool*fsys,int *ptx,int lev);//项处理
int condition(bool* fsys,int *ptx,int lev);//条件处理
int expression(bool* fsys,int *ptx,int lev);//表达式处理
int statament(bool* fsys,int* ptx,int lev);//句子处理
void listcode();//列出目标代码清单
int vardeclaration(int* ptx,int lev,int* pdx);//变量说明处理
int constdeclaration(int* ptx,int lev,int* pdx);//常量说明处理
int position(char* idt,int tx);//查找标识符在名字表中的位置
void enter(enum object k,int* ptx,int lev,int* pdx);//登录名字表
int base(int l,double* s,int b);//通过静态链求出数据区的基地址

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -