pl0函数注释.doc_第1页
pl0函数注释.doc_第2页
pl0函数注释.doc_第3页
pl0函数注释.doc_第4页
pl0函数注释.doc_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/ pl0 compiler source code#include #include #include #include #include set.h#include pl0.h/ print error message./出错报告过程void error(n)/打印字符串数组err_msg对应的下标为n的字符串int i;printf( );for (i = 1; i = cc - 1; i+)printf( );fprintf(outfile, );fprintf(outfile, n);printf(n);fprintf(outfile, Error %3d: %sn, n, err_msgn);printf(Error %3d: %sn, n, err_msgn);err+; / error/void getch(void)/获得字符if (cc = ll) 如果行缓冲区读完if (feof(infile)/检查文件是否结束 结束返回非零值 否则返回0printf(nPROGRAM INCOMPLETEn);exit(1);ll = cc = 0;/line length , character countfprintf(outfile, %5d , cx);printf(%5d , cx);while ( (!feof(infile) / added & modified by alex 01-02-09 & (ch = getc(infile) != n)/从文件infile中读取字符并放ch中fprintf(outfile, %c, ch);printf(%c, ch);line+ll = ch;/将从文件中读取的字符存储在数组line中 / whilefprintf(outfile, n);printf(n);line+ll = ;ch = line+cc;/将当前第一个读取到的字符赋值给ch;字符数+1; / getch/ gets a symbol from input stream.void getsym(void)int i, k;char aMAXIDLEN + 1;while (ch = | ch = t)/若是空格或是制表符 直接跳过 获取下一字符/ modified by yzhang 02-03-12,add some white spacegetch();/判断ch是保留字或者是标识符if (isalpha(ch)/判断字符ch是否为英文字母 若为英文字母 返回非零值 否则返回零 / symbol is a reserved word or an identifier. 判断是为标识符和保留字k = 0;/k记录当前数组a中存入的字符个数doif (k MAXNUMLEN) /该数字中所含数字的个数大于MAXNUMLENerror(25); / The number is too great.该数字过大/判断ch是否是关系运算符else if (ch = :)/如果当前字符是:getch();/获取下一字符if (ch = =)/下一字符为=,表示赋值sym = SYM_BECOMES; / :=getch();/继续读取字符else/非法字符sym = SYM_NULL; / illegal?else if (ch = )/如果当前字符为getch();/获取下一字符if (ch = =)/下一字符为= ,表示=sym = SYM_GEQ; / =getch();else/表示sym = SYM_GTR; / else if (ch = )/如果当期字符为getch();if (ch = =)/读取下一字符为=,表示=sym = SYM_LEQ; / )/读取下一字符为,表示不相等sym = SYM_NEQ; / getch();else/表示sym = SYM_LES; / CXMAX)/cx的值大于CXMAX(size of code array)当前生成代码的行号大于允许的最大代码行数 /报错fprintf(outfile, Fatal Error: Program too long.n);printf(Fatal Error: Program too long.n);exit(1);/将x,y,z 对应赋值给数组code中下标为cx的元素 /把代码写进当前目标代码数组当前cx所指的位置codecx.f = x;codecx.l = y;codecx+.a = z;/并移动cx指向下一个空位 / gen/ tests if error occurs and skips all symbols that do not belongs to s1 or s2./测试是否出现错误 并跳过所有不属于s1和s2的符号/出错恢复过程void test(symset s1, symset s2, int n)/s1:当语法分析进入或退出某一语法单元时当前单词符合应属于的集合/s2:在某一出错状态下,可恢复语法分析正常工作的补充单词集合/n:出错信息编号,当当前符号不属于合法的s1集合时发出的出错信息symset s;if (! inset(sym, s1)/调用inset函数 判断sym是否在s1中/当前符号符号不在s1中showset(s1);/调用showset 函数 输出s1和s2中的元素showset(s2);printf(sym=%d, id=%sn, sym, id);error(n);/报错s = uniteset(s1, s2);/将s1和s2合并 并赋值给swhile(! inset(sym, s)getsym();/通过循环找到下一个合法的符号,以恢复语法分析工作destroyset(s);/删除s / test/int dx; / data allocation index 数据分配指数/ enter object(constant, variable or procedre) into table./登陆名字表过程void enter(int kind)mask* mk;/ added by yzhang 02-02-28/id在table中已经存在 报错 标识符重复定义if ( position(id) 0 )error(26); /Redeclared identifier./ end /id在table中不存在tx+;/table中所含标识符个数+1strcpy(, id);/将id赋值给table中第tx号元素tabletx.kind = kind;switch (kind)/判别id类型case ID_CONSTANT:/常数if (num MAXADDRESS)/该数中所含数字个数过多error(25); / The number is too great.num = 0;tabletx.value = num;break;case ID_VARIABLE:/变量mk = (mask*) &tabletx;mk-level = level;mk-address = dx+;break;case ID_PROCEDURE:/程序mk = (mask*) &tabletx;mk-level = level;break; / switch / enter/ locates identifier in symbol table./查找id在table中的位置 ,并将位置返回/查询名字表过程int position(char* id)int i;strcpy(, id);/将id赋值给table中的0号元素i = tx + 1;while (strcmp(, id) != 0);return i;/返回id在table中对应的下标 / position/常量定义分析过程void constdeclaration()if (sym = SYM_IDENTIFIER)/当前为标识符getsym();/调用getsym函数,获取下一个tokenif (sym = SYM_EQU | sym = SYM_BECOMES)/当前字符特征表示为=或:=if (sym = SYM_BECOMES)/若为:=报错(常量声明中应为等号不是赋值号)error(1); / Found := when expecting =.1号错误getsym();/调用getsym(),获取下一个tokenif (sym = SYM_NUMBER)/读取的是数字enter(ID_CONSTANT);/调用enter函数 并传递参数ID_CONTANT 常数,把这个常量登录到符号表getsym();/调用getsym(),获取下一个tokenelse/读到的不是数字 报错 error(2); / There must be a number to follow =.等号后应接数字/常量标识符后接的不是=或:=elseerror(3); / There must be an = to follow the identifier./常量声明过程中遇到的第一个符号不是标识符 报错else/added by yzhang 02-02-28error(4); / There must be an identifier to follow const, var, or procedure. / constdeclaration/变量定义分析过程void vardeclaration(void)if (sym = SYM_IDENTIFIER)/当前为标识符enter(ID_VARIABLE);/将参数ID_VARIABLE传递给函数enter,登陆到符号表getsym();/继续读取,获取下一个token else/变量声明后遇到的第一个符号不是标识符 报错 error(4); / There must be an identifier to follow const, var, or procedure. / vardeclaration/列出code代码过程void listcode(int from, int to)int i;printf(n);fprintf(outfile, n);for (i = from; i level, mk-address);break;case ID_PROCEDURE:/如果在因子处理中遇到的标识符是过程名,出错,抛21号错error(21); / Procedure identifier can not be in an expression.break; / switchgetsym();/获取下一个tokenelse if (sym = SYM_NUMBER)/遇到的是数字if (num MAXADDRESS)/数字过大,抛出25号错误 error(25); / The number is too great.num = 0;/把数字按0处理gen(LIT, 0, num);/生成lit指令,把这个数值常量放到栈顶getsym();/获取下一个tokenelse if (sym = SYM_LPAREN)/遇到的是左括号getsym();/获取下一个tokenset = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys);/合并expression(set);/调用expression表达式分析过程,分析setdestroyset(set);/删除setif (sym = SYM_RPAREN)/遇到的是右括号getsym();/获取下一个tokenelse/否则抛出错误,缺少右括号error(22); / Missing ).else/ added by yzhang 02-02-28test(fsys, createset(SYM_LPAREN, SYM_NULL), 23);/一个因子处理完毕,遇到的token应在fsys集合中,如果不是,抛23号错,/并找到下一个因子的开始,使语法分析可以继续运行下去 / while / factor/项处理过程void term(symset fsys)int mulop;symset set;set = uniteset(fsys, createset(SYM_TIMES, SYM_SLASH, SYM_NULL);factor(set);/调用因子处理过程,每一个项都应该由因子开始,因此调用factor子程序分析因子while (sym = SYM_TIMES | sym = SYM_SLASH)/一个因子后应当遇到乘号或除号mulop = sym;/保存当前运算符getsym();/获取下一个tokenfactor(set);/运算符后应是一个因子,故调factor子程序分析因子if (mulop = SYM_TIMES)/遇到乘号gen(OPR, 0, OPR_MUL);/生成乘法指令elsegen(OPR, 0, OPR_DIV);/生成除法指令 / whiledestroyset(set);/删除set / term/表达式处理过程void expression(symset fsys)int addop;symset set;set = uniteset(fsys, createset(SYM_PLUS, SYM_MINUS, SYM_NULL);/将fsys与新建的含有+,-的链表合并if (sym = SYM_PLUS | sym = SYM_MINUS)/若当前为+或-, /一个表达式可能会由加号或减号开始,表示正负号addop = sym;/把当前符号保存,并继续向下读取getsym();/获取下一个tokenterm(set);/调用项处理过程termif (addop = SYM_MINUS)/保存下来的是-gen(OPR, 0, OPR_NEG);/生成取反指令else/如果不是由正负号开头,就应是一个项开头term(set);/调用term子程序分析项while (sym = SYM_PLUS | sym = SYM_MINUS)/项后应该是加减运算addop = sym;/保存运算符getsym();/获取下一个tokenterm(set);/加减运算符后应跟一个项,调用term 分析项if (addop = SYM_PLUS)/保存的是+,生成加法指令gen(OPR, 0, OPR_ADD);else/否则生成减法指令gen(OPR, 0, OPR_MIN); / whiledestroyset(set);/删除set / expression/条件处理过程/fsys: 如果出错可用来恢复语法分析的符号集合void condition(symset fsys)int relop;/用来临时记录token内容symset set;if (sym = SYM_ODD)/如果是odd运算符getsym();/获取下一个tokenexpression(fsys);/调用expression 进行处理运算gen(OPR, 0, 6);/生成6号指令:奇偶判断else/不是odd运算符set = uniteset(relset, fsys);/relset中存储逻辑运算符expression(set);/对表达式左部进行处理运算destroyset(set);if (! inset(sym, relset)/如果不是逻辑运算符,抛出20号错误error(20);elserelop = sym;/记录当前逻辑运算符getsym();/获取下一个tokenexpression(fsys);/对表达式右边进行处理switch (relop)/分析保存下来的逻辑运算符case SYM_EQU:/=,生成判断相等的指令gen(OPR, 0, OPR_EQU);break;case SYM_NEQ:/-,生成判断不等的指令gen(OPR, 0, OPR_NEQ);break;case SYM_LES:/=,生成大于等于的指令gen(OPR, 0, OPR_GEQ);break;case SYM_GTR:/,生成大于的指令gen(OPR, 0, OPR_GTR);break;case SYM_LEQ:/level, mk-address);else if (sym = SYM_CALL)/如果是CALL / procedure callgetsym();/获取下一个tokenif (sym != SYM_IDENTIFIER)/不是标识符,14号错误,call后应连接标识符error(14); / There must be an identifier to follow the call.elseif (! (i = position(id)/未在符号表中查找到该标识符,11号错误error(11); / Undeclared identifier.else if (tablei.kind = ID_PROCEDURE)/该标识符是过程名mask* mk;mk = (mask*) &tablei;gen(CAL, level - mk-level, mk-address);/生成call目标代码,呼叫该过程else/不是过程名,15号错误error(15); / A constant or variable can not be called. getsym();/或取下一个token / else else if (sym = SYM_IF)/如果是if / if statementgetsym();/获取下一个token(应为一个逻辑表达式)set1 = createset(SYM_THEN, SYM_DO, SYM_NULL);set = uniteset(set1, fsys);/出错恢复集中加入then和do语句condition(set);/对逻辑表达式进行分析计算destroyset(set1);/删除set1,setdestroyset(set);if (sym = SYM_THEN)/遇到thengetsym();/获取下一个token(应为一个语句)else/没有遇到then,16号错误error(16); / then expected.cx1 = cx;/记下当前代码分配指针位置gen(JPC, 0, 0);/生成跳转指令,跳转位置暂时填0,分析完语句后再填写statement(fsys);/分析then后语句codecx1.a = cx;/上一行指令(cx1所指的)的跳转位置应为当前cx所指位置else if (sym = SYM_BEGIN)/如果遇到begin / blockgetsym();/获取下一个tokenset1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL);set = uniteset(set1, fsys);statement(set);/对begin和end之间的语句进行处理while (sym = SYM_SEMICOLON | inset(sym, statbegsys)/如果分析完一句后遇到分号或语句开始符/循环分析if (sym = SYM_SEMICOLON)/遇到分号getsym();/获取下一个tokenelse/否则报错error(10);statement(set);/分析语句 / whiledestroyset(set1);destroyset(set);if (sym = SYM_END)/遇到endgetsym();/或取下一个tokenelse/否则报错error(17); / ; or end expected.else if (sym = SYM_WHILE)/遇到while / while statementcx1 = cx;/记下当前代码分配位置,这是while循环的开始位置getsym();/获取下一个tokenset1 = createset(SYM_DO, SYM_NULL);set = uniteset(set1, fsys);condition(set);/进行分析运算destroyset(set1);destroyset(set);cx2 = cx;/记下当前代码分配位置,这是while的do中的语句的开始位置gen(JPC, 0, 0);/生成条件跳转指令,跳转位置暂时填0if (sym = SYM_DO)/遇到dogetsym();/获取下一个tokenelse/报错error(18); / do expected.statement(fsys);/分析do后的语句gen(JMP, 0, cx1);/循环跳转到cx1位置,即再次进行逻辑判断codecx2.a = cx;/把刚才填0的跳转位置改成当前位置,完成while语句的处理else/added by yzhang 02-02-28test(fsys, phi, 19); / 至此一个语句处理完成,一定会遇到fsys集中的符号,如果没有遇到,就抛19号错 / statement/程序分析过程/fsys:用于出错恢复的单词集合void block(symset fsys)int cx0; / initial code index 记录本层开始时代码段分配位置mask* mk;/mask是在pl0.h中声明的结构体 定义mask类的指针mkint block_dx;int savedTx;symset set1, set;dx = 3;/声明的全局变量 数据分配指数/地址指示器给出每层局部量当前已分配到的相对位置。 / 置初始值为3的原因是:每一层最开始的位置有三个空间用于存放静态链SL、动态链DL和返回地址RAblock_dx = dx;mk = (mask*) &tabletx;/将tabletx的地址强制转化成mask*类型 并赋值给mkmk-address = cx;/mk对应的元素address赋值为cx/符号表当前位置记下当前层代码的开始位置gen(JMP, 0, 0);/产生一条跳转指令,跳转位置暂时填0if (level MAXLEVEL)/大于最大嵌套深度MAXLEVEL 报错 error(32); / There are too many levels.do/开始循环处理源程序中所有的声明部分if (sym = SYM_CONST)/特征表示为常量 / constant declarationsgetsym();/获取下一个tokendo/反复进行常量声明constdeclaration();/声明以当前token为标识符的常量while (sym = SYM_COMMA)/如果遇到了逗号则反复声明下一个常量getsym();constdeclaration();if (sym = SYM_SEMICOLON)/为;getsym();/获取下一个token,为下一轮循环做好准备else/报错error(5); / Missing , or ;.while (sym = SYM_IDENTIFIER);/若当前特征表示为标识符 循环执行 / ifif (sym = SYM_VAR)/当前token为变量 / variable declarationsgetsym();/获取下一个tokendo/反复进行变量声明vardeclaration();/调用变量定义函数,以当前token为标识符声明一个变量while (sym = SYM_COMMA)/如果遇到了逗号则反复声明下一个变量getsym();vardeclaration();if (sym = SYM_SEMICOLON)/读到;,继续向下读getsym();/获取下一个token,为下一轮循环做好准备else/否则报错error(5); / Missing , or ;.while (sym = SYM_IDENTIFIER);/当前特征表示为标识符 循环判断block_dx = dx;/ modified by yzhang 02-03-15 / ifwhile (sym = SYM_PROCEDURE)/循环声明各子过程 / procedure declarationsgetsym();/获取下一个token,此处正常应为作为过程名的标识符if (sym = SYM_IDENTIFIER)/为标识符enter(ID_PROCEDURE);/把这个过程登录到名字表中getsym();/获取下一个tokenelse/否则报错error(4); / There must be an identifier to follow const, var, or procedure.if (sym = SYM_SEMICOLON)/读到的是;getsym(); / 获取下一个token,准备进行语法分析的递归调用else/否则报错error(5); / Missing , or ;.level+;/嵌套深度+1savedTx = tx;/暂存tx的值,初始符号表指针指向当前层的符号在符号表中的开始位置,set1 = createset(SYM_SEMICOLON, SYM_NULL);/创建链表 并将;插入set = uniteset(s

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论