📄 pl0.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 + -