logo资料库

编译原理实验报告.docx

第1页 / 共48页
第2页 / 共48页
第3页 / 共48页
第4页 / 共48页
第5页 / 共48页
第6页 / 共48页
第7页 / 共48页
第8页 / 共48页
资料共48页,剩余部分请下载后查看
编译原理实验一报告
1、目的及意义
2、C-语言词法特点及正则表达式
3、Token的DFA
4、重要的数据类型数据结构
5、介绍DFA实现代码的各种方法的特点,说明自己选择的方案
6、实现的关键代码分析
7、运行结果实例、分析
8、小结
9、参考资料
编译原理实验二报告
1、目的及意义
2、输入输出要求
3、网页中邮件地址的构成规律分析,构造正则表达式,进行分析
4、爬虫的爬取策略,爬虫所使用重要数据结构设计
5、解析网页识别邮件地址、抽取URL的方法
6、运行结果实例、分析
7、小结
编译原理实验三报告
1、目的及意义
2、Lex词法分析器构造方法
3、C-语言词法分析的设计
4、运行结果及分析
5、小结
6、参考资料
编译原理实验四报告
1、实验目的及意义
2、C-的语法和语义
3、实验方法
4、编程方法
5、代码分析设计
6、关键代码
7、实验结果及分析
8、小结
姓名: 学号: 指导老师:于中华 编译原理实验一报告 ——手工构造 C-语言的词法分析器 1、 目的及意义 掌握正则表达式;掌握 DFA 的构造方法,能根据实际情况构造合适 DFA; 能根据 DFA 转化出成词法分析器的具体实现代码;设计一个 C-词法分析 程序,理解词法分析器实现的原理,掌握程序设计语言中的各类单词的词 法分析方法,加深对词法分析原理的理解。 2、 C-语言词法特点及正则表达式 1) 关键字:else,if,int,return,void,while 所有关键字都是保留字, 并且都是小些。 2) 专用符号:+ - * / < <= > >= == != = ; , () [] {},/* */ 3) 其他标记是 ID 和 NUM,正则表达式为: ID = letter letter* NUM = digit digit* letter = a|…|z|A|…|Z digit = 0|…|9 所有大写和小写字母是有区别的。 4) 空格有空白、换行、和制表符组成。空格通常被忽略,除了它必须分 开的 ID、NUM 关键字。 5) 注释通常用通用的 C 语言符号/*…*/围起来。注释可以放在任何空白 出现的位置(级注释不能放在标记内)上,且可以超过一行。注释不 能嵌套。 3、 Token 的 DFA 页 1
姓名: 学号: 指导老师:于中华 4、 重要的数据类型数据结构 enum ERROR,//文件结尾和错误识别 用枚举量保存 C-所有的保留字,以及后面识别出的标识符类型: typedef { ENDFILE, ID, IF, ASSIGN,EQ,LT,LTEQ,BG,BGEQ,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,S EMI,NOTEQ,CMMA,FLPAREN,FRPAREN,DLPAREN,DRPAREN//所有类型的 Token }TokenType; NUM,//ID 和数字 ELSE, WHILE,//保留字 RETURN, VOID, INT, enum 用枚举量保存程序中 DFA 状态转换的所有状态:这些类型在上面 DFA 图中 都有表示: typedef { START,INASSIGN,INCOMMENT,INNUM,INID,DONE,SLT,SBG,SEQ,SDEV,SNOTE Q,STIME,ENDCOMMENT,INCOMMENT1 }StateType; 用两个文件指针分别指向源文件和创建的目标文件: FILE*source; FILE*listing; 用一个字符类型的数组保存从文件读出的每行代码 #define static lineBuf[BUFLEN]; BUFLEN char 256 struct 用一个结构保存 C-的转换保留字,因为 C 语言中小写也是保留字,为了 避免冲突,所以程序中先转为大写,在最后输出的时候,再转为小写 static { char*str; TokenType }reservedWords[MAXRESERVED] tok; IF }, { RETURN }, "else", "v { ELSE }, { "int", INT = }, { { "if", { "return", oid", VOID }, { "while", WHILE } }; 用一个字符类型的数组保存识别的 Token char tokenString[MAXTOKENLEN + 1]; 5、 介绍 DFA 实现代码的各种方法的特点,说明自己选择的方案 页 2
姓名: 学号: 指导老师:于中华 1) 方法一: {starting in state 1} If the next character is a letter then Advance the input; {now in state 2} While the next character is a letter or a digit do Advance the input;{stay in 2} End while; {go to state 3 without advancing the input} Accept; Else {error or other cases} End if; 这种方法使用于没有太多的状态(要求有许多嵌套层)且 DFA 中的循环 叫小;它的缺点是首先它是特殊的,即必须使用循环不同的方法处理各个 DFA, 而且规定一个用这种办法将每个 DFA 翻译为代码的算法非常困难;其次当状态增 多或明确时,切当相异的状态与仁义路径增多时,代码会变得非常复杂。所以没 有选择方法一。 2) 方法二: State :=1;{start} While state = 1 or 2 do Case state of 1: case input character of Letter:advance the input; State :=2; Else state := …{error or other}; End case; 2 ;case input character of Letter,digit:advance the input; State := 2;{actually unnecessary} Else state := 3; End case; End case; End while; If state := 3 then accept else error; 方法二利用一个变量保持当前的状态,并将转换写成以恶双层嵌套的 case 语句;其中第一个 case 语句测试当前的状态,嵌套的第二层测 试输入字符及所给状态。这种方法转换与对 state 变量新赋的状态相 对应,并提前输入。这种方法实现比较简单,所以 C-语言词法分析器 就采用的正中方法。 3) 方法三: State := 1; Ch := next input character; While not accept[state] and not error (state) do 页 3
姓名: 学号: 指导老师:于中华 Newstate := T[state,ch]; If advance[state,ch] then ch := next input char; State := newstate; End while; If accept [state] then accept; 这种方法代码的长度缩短了,相同的代码可以解决许多不同的问题, 代码也叫容易改动;但是彪哥会变得非常大,是的程序要求使用的空 间也变得很大。所以也不采用这种方法。 6、 实现的关键代码分析 1) TokenType getToken(void)函数 在判断注释的时候设置了三个状态分别为 INCOMMENT,INCOMMENT1 和 ENDCOMMENT,当输入为/时进入 INCOMMENT,进行判断若下一个字符为*则 设置状态为 INCOMMENT1 否则把 currentToken 设置为 Over;在出注释状 态时,若*则设置状态为 ENDCOMMENT 若下一个字符为/则状态设置为 END, 否者回到状态 INCOMMENT1; 在判断< <=;> >=;!=;==时,以< <=为例,先判断第一个字符,若为<则置 状态为 SLT,接着判断下一个状态若为=这 currentToken 值为 LTEQ,否则 currentToken 值为 LT,状态都设置为 DONE。若为+ - * ; ,符号是直接 判断是否为相应的符号若是则置 currentToken 为相应的状态,否则继续 执行程序。 关键词法分析代码如下: TokenType getToken(void) { int tokenStringIndex = 0; TokenType currentToken; StateType state = START; int save; while (state != DONE) { char c = getNextChar(); save = TRUE; switch (state) { case START: if (isdigit(c)) state = INNUM; else if(isalpha(c)) state = INID; else if(c == '/') { state = INCOMMENT; } else if(c == '<') { 页 4
姓名: 学号: 指导老师:于中华 state = SLT; } else if(c == '>') { state = SBG; } else if(c == '=') { state = SEQ; } else if(c == '!') { state = SNOTEQ; } else if((c == ' ') || (c == '\t') || (c == '\n')) save = FALSE; else { state = DONE; switch (c) { case EOF: save = FALSE; currentToken = ENDFILE; break; case '+': currentToken = PLUS; break; case '-': currentToken = MINUS; break; case '*': currentToken = TIMES; break; case '(': currentToken = LPAREN; break; case ')': currentToken = RPAREN; break; case '[': currentToken = FLPAREN; break; case ']': 页 5
姓名: 学号: 指导老师:于中华 currentToken = FRPAREN; break; case '{': currentToken = DLPAREN; break; case '}': currentToken = DRPAREN; break; case ';': currentToken = SEMI; break; case ',': currentToken = CMMA; break; default: currentToken = ERROR; break; } } break; case INCOMMENT: if(c == '*') { state = INCOMMENT1; } else { state = DONE; ungetNextChar(); currentToken = OVER; } break; case INCOMMENT1: if(c == EOF) { state = DONE; currentToken = ENDFILE; } else if(c == '*') { state = ENDCOMMENT; } else state = INCOMMENT1; 页 6
姓名: 学号: 指导老师:于中华 break; case ENDCOMMENT: if(c == '/') { state = DONE; currentToken = COMMENT; } else { state = INCOMMENT1; } break; case SLT: if(c == '=') { currentToken = LTEQ; } else { currentToken = LT; } state = DONE; break; case SBG: if(c == '=') { currentToken = BGEQ; } else { currentToken = BG; } state = DONE; break; case SEQ: if(c == '=') { currentToken = EQ; } else { currentToken = ASSIGN; } 页 7
姓名: 学号: 指导老师:于中华 state = DONE; break; case SNOTEQ: if(c == '=') { currentToken = NOTEQ; } else { ungetNextChar(); save = FALSE; currentToken = ERROR; } break; case INNUM: if(!isdigit(c)) { ungetNextChar(); save = FALSE; state = DONE; currentToken = NUM; } break; case INID: if(!isalpha(c)) { ungetNextChar(); save = FALSE; state = DONE; currentToken = ID; } break; case DONE: default: fprintf(listing,"Scanner Bug: state= %d\n",state); state = DONE; currentToken = ERROR; break; } if((save) && (tokenStringIndex <= MAXTOKENLEN)) { tokenString[tokenStringIndex++] = (char) c; } 页 8
分享到:
收藏