logo资料库

编译方法实验报告.doc

第1页 / 共13页
第2页 / 共13页
第3页 / 共13页
第4页 / 共13页
第5页 / 共13页
第6页 / 共13页
第7页 / 共13页
第8页 / 共13页
资料共13页,剩余部分请下载后查看
编译方法实验报告 姓 班 名 级 学 号 指 导 教 师 实 验 名 称 扫描器的设计、中间代码生成器设计 开 设 学 期 实 验 时 间 评 定 成 绩 2 0 1 3 - 2 0 1 4 第 一 学 期 第 9 周 评 定 人 签 字 评 定 日 期 东北大学软件学院 2013 年 10 月
实验 1 扫描器的设计 一、 实验目的 熟悉并实现一个扫描器(词法分析程序)。 二、 实验内容 (1) 设计扫描器的有限自动机(识别器); (2) 设计翻译、生成 Token 的算法(翻译器); (3) 编写代码并上机调试运行通过。 输入——源程序文件或源程序字符串; ·输出——相应的 Token 序列; · 关键字表和界符表; 符号表和常数表; 三、 实验原理及基本步骤 实验流程图解: 单词 扫描器 Token (1) 有限自动机的状态转换图 d e d +① d ② . ③ d ④ e ⑤ l b l/d ⑧ -1 12 -1/+/- ⑨ b ⑩ -1 13 -1 14 +|- d ⑥ d ⑦ d -1/+/- -1/+/- 11 - - - - -1 15 - 其中:d 为数字,l 为字母,b 为界符,-1 代表其它符号(如在状态 8 处遇到 了非字母或数字的其它符号,会变换到状态 12)。
状态转换矩阵: d · E|e 3 5 5 +|- 11 11 6 11 l 8 8 b 9 10 -1 15 11 11 11 12 14 13 2 2 4 4 7 7 7 8 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (2) 关键字表和界符表 Program Begin End Var While Do Repeat Until For To If Then Else ; : ( ) , := + - * / > >= == < <= (3) 数据设计: ①状态转换矩阵:int aut[10][7]={ 2, 0, 0, 0, 8, 9, 15, 2, 3, 5,11, 0, 0, 11,
4, 0, 0, 0, 0, 0, 0, 4, 0, 5,11, 0, 0, 11, 7, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 7, 0, 0,11, 0, 0, 11, 8, 0, 0, 0, 8, 0, 12, 0, 0, 0, 0, 0, 10, 14, 0, 0, 0, 0, 0, 0, 13}; ②关键字表: char keywords[30][12]={“program”,”begin”,”end”,”var”,”while”,”do”, ”repeat”,”until”,”for”,”to”,”if”,”then”,”else”, “;”, ”:”, ”(“, ”)”, ”,”, ”:=”, ”+”, ”-“, ”*”, ”/”, ”>”, ”>=”, ”==”, “<”, “<=”}; //表中存有源程序中的标 ③符号表:char ID[50][12]; 识符 ④常数表:float C[20]; ⑤其它变量: struct token { int code; int value}; struct token tok[100]; int s; int n,p,m,e,t; //Token 结构 //Token 数组 //当前状态 //尾数值,指数值,小数位数,指数 符号,类型 float num; char w[50]; int i; char strTOKEN[12]; //常数值 //源程序缓冲区 //源程序指针,当前字符为 w[i] //当前已经识别出的单词 (4) 语义动作: ·q1:n=m=p=t=0; e=1; num=0; 其它变量初始化; ·q2:n=10*n+(w[i]); ·q3:t=1; ·q4:n=10*n+( w[i]); m++; ·q5:t=1; ·q6:if ‘-‘ then e=-1; ·q7:p=10*p+(w[i]); ·q8:将 w[i]中的符号拼接到 strTOKEN 的尾部; ·q9:将 w[i]中的符号拼接到 strTOKEN 的尾部; ·q10:将 w[i]中的符号拼接到 strTOKEN 的尾部; //标识符的编码为 1,值为其在常数表中的位置;常数的编码为 2, 值为其在符号表中的位置;关键字和界符的编码为其在关键字表中的位 置,值为 0。 q11:num=n*10e*p-m; t[i].code=2; //计算常数值 t[i].value=InsertConst(num); // 生 成 常 数
Token ·q12:code=Reserve(strTOKEN); //查关键字表 if code then { t[i].code=code; t[i].value=0; } //生成关键字 Token else { t[i].code=1; t[i].value=InsertID(strTOKEN); //生成标识符 Token ·q13:code=Reserve(strTOKEN); } //查界符表 code t[i].code=code; t[i].value=0; //生成界符 Token if then { } else { } strTOKEN[strlen(strTOKEN)-1]=’\0’; 源程序缓冲区指针减 1; code=Reserve(strTOKEN); t[i].code=code; t[i].value=0; //查界符表 //生成界符 Token //单界符 ·q14:code=Reserve(strTOKEN); t[i].code=code; t[i].value=0; //查界符表 //生成界符 Token ·q15:stop. (5) 查状态变换表 int find(int s,char ch) //s 是当前状态,ch 是当前字符,返回值是转换 后状态 { } 查状态转换矩阵 aut[10][7]; 返回新状态; 四、 数据结构设计 主程序流程: 初始化; 打开用户源程序文件; while (文件未结束) {
读入一行到 w[i],i=0; do { //处理一行,每次处理一个单词 滤空格,直到第一个非空的 w[i]; i--; s=1; while (s!=0) { act(s); if (s>=11 && s<=14) break; i++; s=find(s, w[i]); } if (s==0) //处理一个单词开始 //拼单词并生成相应 Token //执行 qs //一个单词处理结束 //getchar() 词法错误; }while (w[i]!=换行符); } 关闭用户源程序文件; 生成 Token 文件; 输出关键字表; 输出 Token 序列; 输出符号表; 输出常数表; 五、 关键代码分析(带注释)及运行结果 //滤空格 //判定单词类别 1. 判定单词类型: while (w[i]==' ') i++; if (w[i]>='a' && w[i]<='z') { ptr=col2; num_map=2; } else if (w[i]>='0' && w[i]<='9') { ptr=col1; num_map=4; } else if (strchr(col3[0].str,w[i])==NULL) { printf("非法字符%c\n",w[i]); i++; continue; }
else { ptr=col3; num_map=1; } 2. 处理单词: s=1; while (s!=0) { act(s); if (s>=11 && s<=14) break; i++; s=find(s,w[i]); } if (s==0) { //开始处理一个单词 //getchar() strTOKEN[i_str]='\0'; printf("词法错误:%s\n",strTOKEN); } 3. 输出关键字表的结果: printf("关键字表:"); for (i=0;i<30;i++) printf("%s ",keywords[i]); printf("\n"); printf("Token 序列:"); for (i=0;i
if (strchr((p+i)->str,ch)) { col=(p+i)->col; break; } //printf("aut[s][col]: %d\n",aut[s][col]); return aut[s][col]; } 5. 判断有多少个常数 int InsertConst(double num)//判断有多少个常数用的 { int i; for (i=0;i
分享到:
收藏