以下各节的代码根据教材P288的附录A中的pascal代码改写而来。改写时的要求是
1、尽量使用原有的变量名和类型名、函数名和参数名
2、对c++中未提供的运算符或者函数,则额外实现
3、尽量不改动原有的处理流程。
此外,代码中的注释基本摘自技术高手李凡希的博客。地址为http://blog.csdn.net/lifanxi/article/details/3833
这里向这位技术大牛致以崇高的敬意!
由于代码较多,故分几次贴出,本次先贴出头文件包含语句和全局变量定义语句
/* PL/0编译程序与代码生成解释运行程序 */ /* PL/0 compiler with code generation */ /*引入必要的头文件和类型名*/ #include<set> using std::set; #include<fstream> using std::fstream; using std::ifstream; using std::ofstream; #include <iostream> using std::istream ; using std::cin; using std::cout; using std::endl; #include <iomanip> using std::setw; using std::left; using std::boolalpha; #include <cstring> #include <cctype> /* 常量定义 */ const int norw = 13; /* of reserved words */ /* 保留字的个数 */ const int txmax = 100; /* length of identifier table */ /* 标识符表的长度(容量) */ const int nmax = 14; /* max number of digits in numbers */ /* 数字允许的最长位数 */ const int al = 10; /* length of identifiers */ /* 标识符最长长度 */ const int amax = 2047; /* maximum address */ /* 寻址空间 */ const int levmax = 3; /* max depth of block nesting */ /* 最大允许的块嵌套层数 */ const int cxmax = 200; /* size of code array */ /* 类PCODE目标代码数组长度(可容纳代码行数) */ /* 类型定义 */ 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 }; /* symobl类型标识了不同类型的词汇 */ typedef char alfa[al]; /* alfa类型用于标识符 */ enum object{constant, variable, procedure}; /* object为三种标识符的类型 */ typedef set<symbol> symset; /* symset是symbol类型的一个集合类型,可用于存放一组symbol */ enum fct{lit, opr, lod, sto, cal, _int, jmp, jpc}; /* fct类型分别标识类PCODE的各条指令 */ struct instruction { fct f; /* function code */ int l; /* level */ int a; /* displacement addr */ }; /* 类PCODE指令类型,包含三个字段:指令f、层差l和另一个操作数a */ /* lit 0, a load constant a opr 0, a execute opr a lod l, a load variable l, a sto l, a store variable l, a cal l, a call procedure a at level l int 0, a increment t-register by a jmp 0, a jump to a jpc 0, a jump conditional to a */ /* 全局变量定义 */ ofstream fa; /* 文本文件fa用于列出源程序 */ ofstream fa1, fa2; /* 文本文件fa1用于列出类PCODE代码、fa2用于记录解释执行类PCODE代码的过程 */ bool listswitch; /* true set list object code */ /* 如果本变量置true,程序编译后将为列出类PCODE代码, 否则不列出类PCODE代码 */ char ch; /* last char read */ /* 主要用于词法分析器,存放最近一次从文件中读出的字符 */ symbol sym; /* last symbol read */ /* 词法分析器输出结果之用,存放最近一次识别出来的token的类型 */ alfa id; /* last identifier read */ /* 词法分析器输出结果之用,存放最近一次识别出来的标识符的名字 */ int num; /* last number read */ /* 词法分析器输出结果之用,存放最近一次识别出来的数字的值 */ int cc; /* character count */ /* 行缓冲区的列指针 */ int ll; /* line length */ /* 行缓冲区长度 */ int kk; /* 引入此变量是出于程序性能考虑,见getsym过程注释 */ int cx; /* code allocation index */ /* 代码分配指针,代码生成模块总在cx所指位置生成新的代码 */ char line[81];/* 行缓冲区,用于从文件读出一行,供词法分析获取单词时之用 */ alfa a; /* 词法分析器中用于临时存放正在分析的词 */ instruction code[cxmax];/* 生成的类PCODE代码表,存放编译得到的类PCODE代码 */ alfa word[norw];/* 保留字表 */ symbol wsym[norw];/* 保留字表中每一个保留字对应的symbol类型 */ symbol ssym['^'-' '+1];/* 一些符号对应的symbol类型表 */ char mnemonic[8][5]; /* 类PCODE指令助记符表 */ symset declbegsys, statbegsys, facbegsys; /* 声明开始、表达式开始和项开始符号集合 */ /* 符号表 */ struct{ alfa name; /* 符号的名字 */ object kind; union { int val; /* 如果是常量名 val中放常量的值 */ struct{ int level, adr, size; /* 如果是变量名或过程名,存放层差、偏移地址和大小 */ }; }; }table[txmax+1]; ifstream fin; /* fin文本文件用于指向输入的源程序文件,fout程序中没有用到 */ alfa fname; /* 存放PL/0源程序文件的文件名 */ int err; /* 出错总次数 */