1、Subject: Product Internal Specification of Release Date: Rev.0 xxxx Project Page 1 of XProject Name/Model No:XXXXXPL/X编译器软件设计说明书作者:xxx日期:2009/4/301介绍本编译器可以按照PL/X语言语法要求进行词法、语法、语义、出错处理,并最终成生目标代码,通过解释执行得到最终结果。完成了求余、for语句、dowhile语句、read语句、call语句以及自增、自减、常量的定义和使用等扩展功能。2编译器系统结构2.1 编译器2.1.1 PL/X语法图l prog=”p
2、rogram”block”.”.l block=ds”procedure”ident”;”block”;”begin”ss”end”.l ds=d“;”d.l d=”integer”aident“,”aident|”logical”bident“,”bident|const ident”=”number“,”ident”=”number.l ss=s1“;”s1.l s1=aident”:=”ae|bident”:=be|”if”be”then”ss“else”ss”end”|”while”be”do”ss”end”|”repeat”ss”until”be|”write”ae|“do”ss”e
3、nd”while”be|”read”(“aident“,”aident”)”|”call” ident|“for” aident”:=”number”to”number”do”(s1|”begin”ss”end”)|aident”+”|bident”“.l ae=“-“at(“-“|”+”)at l at=af(“*”|”/”|”odd”|”%”)af.l af=aident|number|”(“ae”)”.l be=bt“or”bt.l bt=bf“and”bf.l bf=bident|”true”|false”|”not”bf|”(“be”)”|re.l re=(aident|number
4、)(“=”|”|”=”|”|”=”|”/=”)ae.扩展部分:1.能够进行求余运算;2.能够正确执行read语句;3.能够正确执行dowhile.语句。4.能够正确执行for语句。5.能够正确执行call语句。6.能够正确定义和使用const常量定义。7.能够正确执行自增自减运算。8.能够进行奇偶判断。2.1.2判断是否符合两条限制规则1、找出图中每一个分支点,考察每个分枝点的各个分支的头符号是否相异。2、找出图中每一个透明结构,考察每个透明结构的头符号集合与其跟随符号集合是否相异。2.1.3 过程调用相关图2.1.5 语法出错表定义1源文件缺少program入口.2程序缺少结束符号!3过程定
5、义缺少结束分号!4过程定义缺少开始分号!5不可识别的过程定义标识符!6程序语句缺少begin关键字.7程序缺少end关键字.8不可识别的标识符!9赋值语句不能使用 = 标识符!10左值使用出错!11为过程变量!12if 语句缺乏 end标记符13if 语句缺少 then标识符!14在 while 循环里需要一个 end 标识符15while 语句缺少 do标识符!16repeat 缺乏until标识符!17repeat 缺乏until标识符!18被调用的不是过程!19call 语句无法识别!20应该为赋值21缺少了do22数值类型23应该为to24应该为标识符25运算式中不可使用26缺乏)标识
6、符28不可识别的运算因子29应该为数值或标识符,30错误的运算符号2.2 虚拟机2.2.1 虚拟机组织结构程序存储器 指令存储器 数据存储器 si Code程序地址寄存器 基本地址寄存器 地址寄存器tbP2.2.2 虚拟机指令格式LIT 0,a 把一个常数置入栈顶OPR 0,a 一组算术和关系运算指令LOD l,a 把一个变量置入栈顶 STO l,a 从栈顶把数置入到一个变量单元里INT 0,a 预留数据存储位置JMP 0,a 无条件转移指令JPC 0,a 有条件转移指令WRC0,a 写出一个变量值2.2.3 虚拟机指令系统及其解释switch(i.f)case LIT:t+;st=i.a;b
7、reak;case OPR: switch(i.a)case 0:t=b-1;p=st+3;b=st+2;break;case 1:st=-st;break;case 2:t-;st=st+st+1;break;case 3:t-;st=st-st+1;break;case 4:t-;st=st*st+1;break;case 5:t-;st=st/st+1; break;case 6:st=st%2;break;case 8:t-;st=(st=st+1); break;case 9:t-;st=(st!=st+1); break;case 10:t-;st=(st=st+1); break
8、;case 12:t-;st=(stst+1); break;case 13:t-;st=(st=st+1); break;case 14:t-;st=st%st+1;break;case 15:t+;printf(?);scanf(%d,&(st);break;case 16:if(st!=0)st=0;elsest=1;break;break;case LOD: t+;st=sbase(i.l)+i.a;break;case STO: sbase(i.l)+i.a=st;/printf(%dn,st);t-;break;case CAL: st+1=base(i.l); st+2=b; s
9、t+3=p; b=t+1; p=i.a; break;case INT: t+=i.a;break;case JMP: p=i.a;break;case JPC: if(st=0)p=i.a;t-; break;case WRC:printf(%dn,st);fprintf(fout,%dn,st);t-;break; 3模块架构词法分析语法分析语义分析及目标代码生成目标代码生成表格管理出错处理源程序单词符号语法单位目标代码4模块功能介绍1、词法分析:词法分析子程序名为getsym,功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中,语法分析器需要单词
10、时,直接从这三个变量中获得。(注意!语法分析器每次用完这三个变量的值就立即调用getsym子程序获取新的单词供下一次使用。而不是在需要新单词时才调用getsym过程。)getsym过程通过反复调用getch子过程从源程序过获取字符,并把它们拼成单词。getch过程中使用了行缓冲区技术以提高程序运行效率。词法分析器的分析过程:调用getsym时,它通过getch过程从源程序中获得一个字符。如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过
11、程的名字),把sym置为ident,把这个单词存入id变量。查保留字表时使用了二分法查找以提高效率。如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把sym则成相应的类型。如果遇到不合法的字符,把sym置成nul。词法分析器的分析过程:调用getsym时,它通过getch过程从源程序中获得一个字符。如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有
12、查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把sym置为ident,把这个单词存入id变量。查保留字表时使用了二分法查找以提高效率。如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把sym则成相应的类型。如果遇到不合法的字符,把sym置成nul。2、语法分析:语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语意生成相应的代码,并提供了出错处理的机制。语法分析主要由分程序分析过程b
13、lock、ds(变量定义)、ss(语句序列)、s(语句分析,含有对whiledo.,dowhile.,if,repeat.,read,write,for等语句的分析)、ae at af be bt bf re这些表达式的分析过程。它们在结构上构成一个嵌套的层次结构。除此之外,还有出错报告过程(error)、代码生成过程(gen)、测试单词合法性及出错恢复过程(test)、登录名字表过程(enter)、查询名字表函数(position)以及列出类PCODE代码过程(listcode)作过语法分析的辅助过程。3、类code码生成程序通过gen过程来生成类code代码,并使用过程listcode列出
14、类code代码;4、出错处理程序能检测处源程序的非法符号,语句中的语法错误等相关错误,该机制通过过程error来实现。5全局数据结构、常量和变量#define stacksize 500#define norw 23 #define txmax 100 #define nmax 14 #define al 10 #define levmax 3 #define cxmax 200 #define fctnum 9enum symbolnul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rpa
15、ren,comma,semicolon,period,becomes,beginsym, endsym,ifsym,thensym,whilesym,dosym,callsym,constsym,procsym,writesym, readsym,forsym,odd,mo,andsym,orsym, truesym,falsesym,notsym,progsym,intesym,logisym,repeasym,tosym,elsesym,untilsym,zizeng,zijian, ;enum object constant, inte, logical, procedur,;enum
16、fctLIT,OPR,LOD,STO,CAL,INT,JMP,JPC,WRC,;struct instruction enum fct f; int l; int a;struct instruction codecxmax;struct tablestruct char nameal; enum object kind; int val; int level; int adr; ;struct tablestruct tabletxmax; char ch;enum symbol sym,op;char idal+1;int num;int cc,ll;int cx=0,index,cx1,
17、cx2,lev;char line81;char aal+1;char wordnorwal;enum symbol wsymnorw;enum symbol ssym256;char mnemonicfctnum5;int sstacksize;FILE* fin;FILE* fout;char fnameal;int err;int tx=0,dx,b; 6函数原型函数原型void init();参数描述无函数描述初始化返回值无函数原型void error(int n);参数描述出错编号函数描述显示出错信息返回值无函数原型int getch();参数描述无函数描述取词返回值0表示取词成功函
18、数原型int getsym();参数描述无函数描述读取下一个标识返回值0表示读取成功函数原型int gen(enum fct x,int y,int z);参数描述X:指令名称;Y:层差;Z:偏移量函数描述中间代码代码生成返回值0表示中间代码生成成功函数原型void block();参数描述无函数描述块定义返回值无函数原型void ds();参数描述无函数描述变量声明块返回值无函数原型void d();参数描述无函数描述变量声明返回值无函数原型void constdeclaration();参数描述无函数描述常量的定义返回值无函数原型void ss();参数描述无函数描述语句块返回值无函数原型
19、void s1();参数描述无函数描述语句返回值无函数原型void ae();参数描述无函数描述数学表达式返回值无函数原型void at();参数描述无函数描述数学表达式返回值无函数原型void af();参数描述无函数描述表达式因子返回值无函数原型void be();参数描述无函数描述布尔表达式返回值无函数原型void bt();参数描述无函数描述布尔表达式返回值无函数原型void bf();参数描述无函数描述布尔表达式返回值无函数原型void re();参数描述无函数描述表达式返回值无函数原型void enter (enum object k,int value);参数描述K为变量类型,value为值,用于常量函数描述向table表插入变量返回值无函数原型int position(char* idt);参数描述Idt指向读入的标识符函数描述读取当前标识符的位置返回值返回所查询的标识符在table表中的位置函数原型void listcode(int cx0);参数描述Cx0指出开始列出代码的位置函数描述列出中间代码返回值无函数原型void interpret();参数描述无函数描述解释执行中间代码返回值无函数原型int base(int l);参数描述L表示层差函数描述用于计算层次差,取得绝对地址返回值返回绝对地址值17