中间代码生成实验报告
中间代码生成实验报告

一、实验目的1. 理解编译原理中中间代码生成的基本概念和作用。
2. 掌握中间代码生成的常用算法和策略。
3. 提高对编译器构造的理解和实际操作能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse三、实验内容1. 中间代码生成的基本概念2. 中间代码的表示方法3. 中间代码生成算法4. 实现一个简单的中间代码生成器四、实验步骤1. 了解中间代码生成的基本概念中间代码生成是编译过程中的一个重要环节,它将源程序转换成一种中间表示形式,便于后续的优化和目标代码生成。
中间代码生成的目的是提高编译器的灵活性和可维护性。
2. 研究中间代码的表示方法中间代码通常采用三地址代码(Three-Address Code,TAC)表示。
TAC是一种低级表示,由三个操作数和一个操作符组成,例如:(t1, t2, t3) = op,其中t1、t2、t3为临时变量,op为操作符。
3. 学习中间代码生成算法中间代码生成算法主要包括以下几种:(1)栈式中间代码生成算法(2)归约栈中间代码生成算法(3)递归下降中间代码生成算法4. 实现一个简单的中间代码生成器本实验采用递归下降中间代码生成算法,以一个简单的算术表达式为例,实现中间代码生成器。
(1)定义语法规则设表达式E由以下语法规则表示:E → E + T | E - T | TT → T F | T / F | FF → (E) | i(2)设计递归下降分析器根据语法规则,设计递归下降分析器,实现以下功能:①识别表达式E②识别项T③识别因子F(3)生成中间代码在递归下降分析器中,针对不同语法规则,生成相应的中间代码。
例如:当遇到表达式E时,生成以下中间代码:(t1, t2, t3) = op1(t1, t2) // op1表示加法或减法(t4, t5, t6) = op2(t4, t5) // op2表示乘法或除法(t7, t8, t9) = op3(t7, t8) // op3表示赋值(4)测试中间代码生成器编写测试用例,验证中间代码生成器的正确性。
lab14语义分析报告报告材料与中间代码生成

实验报告封面课程名称:编译原理课程代码:SS2027任课老师:彭小娟实验指导老师: 彭小娟实验报告名称:实验十四:语义分析与中间代码生成1学生姓名:学号:教学班:递交日期:签收人:我申明,本报告内的实验已按要求完成,报告完全是由我个人完成,并没有抄袭行为。
我已经保留了这份实验报告的副本。
申明人(签名):实验报告评语与评分:评阅老师签名:彭小娟一、实验名称:语义分析与中间代码生成1二、实验日期: 年 月 日三、实验目的:1. 理解相关概念:中间代码、三地址码,各种语句的目标代码结构2. 掌握三地址码(三元式、四元式、DAG 图),3. 理解赋值语句三地址代码的翻译模式四、实验用的仪器和材料:(操作系统:CPU :内存:硬盘:软件:)硬件:PC 人手一台软件:office五、实验的步骤和方法:1. 给出下面中缀式的逆波兰表示(后缀式),后缀式的中缀式表示/*)(*)/(*++-+-+-++e d c ab d c b a e d c b anot A or not (C or not D)2. 请将表达式-(a+b)*(c+d)-(a+b+c)分别表示成三元式、四元式序列。
3. 按7.3节所说的方法,写出下面赋值句)A+=的自下而上语法制导B-(*:DC翻译过程。
给出所产生的三地址代码。
六、数据记录和计算:七、实验结果或结论:(总结)八、备注或说明:可写上实验成功或失败的原因,实验后的心得体会、建议等。
九、引用参考文献:即在本实验中所引用的之資料。
中间代码生成实验报告doc

中间代码生成实验报告篇一:编译方法实验报告(中间代码生成器)编译方法实验报告XX年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。
实验内容二、(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。
输入——算术表达式;输出——语法分析结果;相应的四元式序列。
(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文法,使用扩展的语法分析器实现语法制导翻译。
三、实验原理及基本步骤●算术表达式文法:G(E):E ? E ω0 T | TT ? T ω1 F | FF ? i | (E)●文法变换:G’(E) E ? T {ω0 T(本文来自:小草范文网:中间代码生成实验报告)}T ? F {ω1 F}F ? i | (E)●属性翻译文法:E ? T {ω0 “push(SYN, w)” T “QUAT”}T ? F {ω1 “push(SYN, w)” F “QUAT”}F ? i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i.T = newtemp;ii.QT[j] =( SYN[k], SEM[s-1], SEM[s], T); j++;iii.pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构:SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计,同时,运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )");//QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--;//pop(SYN);i_sem--;//pop(SEM);i_sem--;//pop(SEM);sem[++i_sem]=temp; //push(SEM,temp); temp++;}五、关键代码分析(带注释)及运行结果#include#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15];//四元式区int j=0;char temp='q'; //临时变量,取值为r--z int E();int T();int F();void quat();//生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:"); scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]='0' && exp[i] sem[++i_sem]=exp[i]; } //push(SEM,w)else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )");//QT[j]:=(SYN[k],SEM[s-1] ,SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp;//push(SEM,temp);temp++;}篇二:中间代码生成实验报告一、实验目的通过在实验二的基础上,增加中间代码生成部分,使程序能够对实验二中的识别出的赋值语句,if语句和while语句进行语义分析,生成四元式中间代码。
编译方法实验报告(中间代码生成器)

编译方法实验报告2011年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。
二、实验内容(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。
输入——算术表达式;输出——语法分析结果;相应的四元式序列。
(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法, 并根据这些属性翻译文法, 使用扩展的语法分析器实现语法制导翻译。
三、实验原理及基本步骤●算术表达式文法:G(E): E ( E ω0 T | TT →T ω1 F | FF → i | (E)●文法变换:G’(E) E →T {ω0 T}T →F {ω1 F}F → i | (E)●属性翻译文法:E →T {ω0“push(SYN, w)” T “QUAT”}T →F {ω1“push(SYN, w)” F “QUAT”}F →i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i. T = newtemp;ii. QT[j] =( SYN[k], SEM[s-1], SEM[s], T);j++;iii. pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构: SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计, 同时, 运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}五、关键代码分析(带注释)及运行结果#include <iostream>#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15]; //四元式区int j=0;char temp='q'; //临时变量, 取值为r--zint E();int T();int F();void quat(); //生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:");scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i<j;i++) //输出四元式序列printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]<='p')||(exp[i]>='0' && exp[i]<='9')){ sem[++i_sem]=exp[i]; } //push(SEM,w) else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。
中间代码生成实验报告

中间代码生成实验报告《中间代码生成实验报告》摘要:本实验旨在通过编写中间代码生成程序,实现将高级语言源代码转换为中间代码的功能。
通过实验,我们掌握了中间代码的生成过程和相关算法,并对编译器的工作原理有了更深入的理解。
本实验采用了C语言作为源语言,通过词法分析、语法分析和语义分析,生成了对应的中间代码。
一、实验目的1. 理解编译器的工作原理,掌握中间代码生成的基本概念和方法;2. 掌握中间代码的表示方法和生成算法;3. 通过实践,提高编程能力和对编译原理的理解。
二、实验环境1. 操作系统:Windows 10;2. 编程语言:C语言;3. 开发工具:Visual Studio 2019。
三、实验内容1. 设计并实现中间代码生成程序,将给定的C语言源代码转换为中间代码;2. 实现词法分析、语法分析和语义分析,生成对应的中间代码;3. 测试程序,验证中间代码的正确性和有效性。
四、实验步骤1. 设计中间代码的表示方法,包括四元式、三地址码等;2. 实现词法分析器,将源代码转换为词法单元序列;3. 实现语法分析器,将词法单元序列转换为语法树;4. 实现语义分析器,对语法树进行语义检查并生成中间代码;5. 测试程序,验证中间代码的正确性和有效性。
五、实验结果经过测试,中间代码生成程序能够正确地将C语言源代码转换为中间代码,并且生成的中间代码能够正确地表达源代码的语义和逻辑结构。
通过实验,我们成功地掌握了中间代码的生成过程和相关算法,加深了对编译器工作原理的理解。
六、实验总结通过本次实验,我们深入了解了编译器的工作原理和中间代码生成的基本概念和方法。
通过实践,我们提高了编程能力和对编译原理的理解,为进一步深入学习编译原理和设计编译器打下了良好的基础。
希望通过不断的实践和学习,能够更加熟练地掌握编译原理的知识,为今后的学习和工作打下坚实的基础。
编译原理中间代码生成实验报告

竭诚为您提供优质文档/双击可除编译原理中间代码生成实验报告篇一:编译原理-分析中间代码生成程序实验报告课程名称编译原理实验学期至学年第学期学生所在系部年级专业班级学生姓名学号任课教师实验成绩计算机学院制开课实验室:年月日篇二:编译原理实验中间代码生成实验四中间代码生成一.实验目的:掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。
二.实验内容:1、逆波兰式定义:将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
2、抽象(语法)树:运算对象作为叶子结点,运算符作为内部结点。
3、三元式:形式序号:(op,arg1,arg2)4、四元式:形式(op,arg1,arg2,result)三、以逆波兰式为例的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
四、程序代码://这是一个由中缀式生成后缀式的程序#include#include#include#include#definemaxbuffer64voidmain(){chardisplay_out(charout_ch[maxbuffer],charch[32]);//intcaculate_array(charout_ch[32]);staticinti=0;staticintj=0;charch[maxbuffer],s[maxbuffer],out[maxbuffer];cout cin>>ch;for(i=0;i {out[i]=ch[i];}cout while(out[j]!=#)cout j++;}cout display_out(s,out);//caculate_array;}chardisplay_out(charout_ch[32],charch[]) {inttop=-1;inti=0,data[maxbuffer],n;intj=0;charsta[20];while(ch[i]!=#){if(isalnum(ch[i])){while(isalnum(ch[i])){out_ch[j]=ch[i];j++;i++;}out_ch[j]=;j++;else{switch(ch[i]){case+:case-:if(sta[top]==(||top==-1) {top++;sta[top]=ch[i];i++;}else{//j--;out_ch[j]=sta[top];j++;top--;//i++;}break;//break;case*:case/:if(sta[top]==*/) {out_ch[j]=sta[top];j++;//i++;top--;}else{top++;sta[top]=ch[i];i++;}break;//break;case(:top++;sta[top]=ch[i];i++;break;case):if(sta[top]==() {top--;i++;}if(top==-1){//cout }else{//while(sta[top]!=?(?){ out_ch[j]=sta[top];top--;j++;//}break;}break;/*case?#?:out_ch[j]=?#?; j++;break;*/default:cout ch[i]=#;j=0;break;}}}while(top!=-1){out_ch[j]=sta[top];j++;top--;}out_ch[j]=#;n=0;co(:编译原理中间代码生成实验报告)utwhile(out_ch[n]!=#){cout n++;}cout j=0;returnout_ch[maxbuffer];}五、实验结果:要求:自己给出3个测试用例,观察结果。
实验五-编译-用语法制导方式生成中间代码生成器

实验五-编译-⽤语法制导⽅式⽣成中间代码⽣成器实验5 ⽤语法制导⽅式⽣成中间代码⽣成器⼀、实验⽬的掌握语法制导定义和翻译的原理和技术,在语法分析器的基础上,加上语义分析,构造⼀个中间代码⽣成器。
⼆、实验内容在实验四⽣成的语法分析器基础上加⼊语义动作,将源程序翻译为对应的中间代码序列。
三、实验要求1. 个⼈完成,提交实验报告。
实验报告必须包括设计的思路,以及测试报告(输⼊测试例⼦,输出结果)。
2. 实验报告中给出采⽤测试源代码⽚断,及其对应的三地址码形式(内部表⽰形式可以⾃⾏考虑)。
例如,程序⽚断对应的中间代码为:四、实验过程本次实验运⽤flex和bison⼯具进⾏中间代码的⽣成。
并⾃动⽣成中间代码。
1.⾸先创建⼀个example⽂件夹,该⽂件夹中包含有flex.exe2.⽤⽂本编译器编辑相应的flex⽂件mylex.l,此次mylex.l可以在上次实验的l⽂件上做⼀些修改,再利⽤flex将l⽂件⽣成相应的lex.yy.c程序,mylex.l 的代码如下所⽰:mylex.l%{#include "myyacc.tab.h"%}delim [ \t\n\r]ws {delim}+letter [A-Za-z]digit [0-9]id {letter}({letter}|{digit})*integer {digit}+exponent E[+-]?{integer}number {integer}{exponent}?real integer(\.integer)?{exponent}?%option noyywrap%%"<"|"<="|">"|">="|"!="|"==" { filloperator(&yylval, yytext); return( REL); }if { return( IF ); }else { return( ELSE ); }while { return( WHILE ); }do { return( DO ); }for { return( FOR ); }switch { return( SWITCH ); }case { return( CASE ); } default { return( DEFAULT ); } break { return( BREAK ); } true { return( TRUE ); }false { return( FALSE ); } int { return( INT ); }long { return( LONG ); } char { return( CHAR ); } bool { return( BOOL ); } float { return( FLOAT ); } double { return( DOUBLE ); } "&&" { return( AND ); } "||" { return( OR ); } "!" { return( '!'); }"++" { return( INC ); } "--" { return( DEC ); } "+" { return( '+' ); } "-" { return( '-' ); } "*" { return( '*' ); } "/" { return( '/' ); } "=" { return( '=' ); } "{" { return( '{' ); }"}" { return( '}' ); }"[" { return( '[' ); }"]" { return( ']' ); }"(" { return( '(' ); }")" { return( ')' ); }";" { return( ';' ); }{ws} { }{id} { filllexeme(&yylval, yytext); return( ID ); }{number} { filllexeme(&yylval, yytext); return( NUMBER ); }{real} { filllexeme(&yylval, yytext); return( REAL ); }%%在代码中,先定义正则定义,即对letter,digit,专⽤符号, 空格进⾏声明;接着在转换规则中,定义⼀些识别规则的代码。
编译原理实验三:中间代码生成

编译原理——语义分析成员:杨霞 030802107王日日 030802139方艳丽 030802102实验三:语义分析:生成中间代码一、实验目的通过语法制导或翻译模式生成中间代码。
二、实验内容在自底向上语法分析基础上设计语义规则(语法制导翻译),将源程序翻译为四元式输出.三、实验环境Windows microsoft visual c++ 6.0四.实验原理三地址码的几种常见指令:1.X=Y OP Z 的赋值指令,其中OP 是一个双目运算符或逻辑运算符。
2.X= Y 的复制指令。
3.无条件转移指令 GOTO L 把下一步要执行的带有标号L的三地址指令4.IF X GOTO L 或 IF FALSE X GOTO L的条件转移指令5.IF X RELOP Y GOTO L的条件转移指令。
三地址码四元式实验环境:windows microsoft visual c++语法制导定义:控制流语句的语法制导定义:实验代码分析:struct midcode//四元式结构;{int label;//存放标号;char op;//存放操作符;char arg1;//存放操作数1;char arg2;//存放操作数2;char result;//存放目的操作数(转移标号)}m_midcode[100];如何实现语句的跳转:主要利用了语义规则与规约过程的结合;例如:Label为四元式产生的新标号;Mnew 为四元式中最新的标号;case 9:tab1=t-1;while(tab1--){if(m_midcode[tab1].op=='>'&& (int)(m_midcode[tab1].result)==0){m_midcode[tab1].result=(char)m_midcode[tab1+2].label;/E.true=newlabelm_midcode[tab1+1].result=(char)(m_midcode[tab1+2].label+1);/E.false=newlabeltab2=tab1;for(;tab2<t;tab2++)if(m_midcode[tab2].op=='g'&&(int)m_midcode[tab2].result==0)m_midcode[tab2].result=(char)(mnew-1);//S1.next=s2.next=S.nextbreak ;}实验结果:心得体会:四元式序列是编译原理最后一个实验,最后的实验也要建立在之前两个实验的基础上。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
k=0; do { if(k<15) { token[k]=ch; k++;} getch(); } while(jstr(ch)==1); if (li==0) retract(); else ret(); token[k]='\0'; /*截去t(id,token); for(t =0;t<=20;t++) {if(strcmp(reserve[t],id)==0) break;} if ( t<=20 ) kind=t ; else kind=21; strcpy(sym,id); } else if (jnum(ch)==1) { k=0; do{ if ( k<15 ) { token[k]=ch; k++;} getch(); } while( jstr(ch)==1);
#include<string.h> #include<stdio.h> #include<stdlib.h> #define reser 20 char *charstring="abcdefghijklmnopqrstuvwxyz"; char *numstring="0123456789"; char *strstring="abcdefghijklmnopqrstuvwxyz0123456789"; char reserve[reser][10]; char idshed[40][10],opshed[40][10]; char token[15],id[15],sym[15]; char line[80],tempp[240]; char ch,ch1,temp,tem;
char tx[10]; char tn[4],signt1[20],signt2[20],ju[20]; int cc,ii,k,num,kind,t,e4=0,e3=0,judge=1,row1=0; int startc,idsh=0,opsh=0,tt=1,nn=1,signwh,over=0,adds=0,whs=0,pp=0; int li=0; char filename[15]; FILE *fp;
三 、 测试程序
ff:=6+6*6-; if sl>89+56*67 then f:=7*7+4; ff:=6+6*6-6%4+8; if sl+78*76>89*56+67 then while a-7>98+45*45 do f:=7*7+4;
. 四 、 运行结果
首先对测试程序进行语法分析,识别出正确 的句子,当识别出正确的句子时,就对当前句 子进行语义分析,而语法不正确的句子不进行 语义分析。
case 8:{printf(" Error(8):Except 'then' \n");break;} case 9:{printf(" Error(9):Except Condition Expression\n ");break;} case 10:{printf(" Error(10):Except 'do' ");break;} default: ; } }
void getch(){ if(li==0) { if (cc==ii){ cc=1; ii=0; if (row1==1) fseek(fp,-1,1); 整个文本的开头,则不需要*/ line[0]=fgetc(fp); row1=1; /*读行首字符将指针退回一格,若是
while(((temp=fgetc(fp))!='\n') && (temp!=EOF)) { line[cc]=temp; cc++; tempp[pp]=temp; pp++; } line[cc]=' '; /*将缓冲带后加上一个空字符,以便行和行之间 号区分 */ cc++; tempp[pp]=' ';
void e(){ advance(); if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)|| (strcmp(sym,"*")==0)||(strcmp(sym,"%")==0)) { printf("%s",sym); advance(); if((kind==21) || (kind==22)){ /* kind为21,22分别表示的是标志 符和数字 */ printf("%s",sym); e();} else { e4=1 ;error(4);} } /*出错退出,e4=1*/ } void c(){ advance(); if((kind==21) || (kind==22)){ printf("%s",sym); e(); if(e4==1); /*e4的作用是判断程序从e()中是不是出错 退出*/
} void ret(){ pp--; } int jchar(char ch){ if(strchr(charstring,ch)==0) return 0; else return 1; } int jnum(char ch){ if(strchr(numstring,ch)==0) return 0; else return 1; } /* 判断ch是不是字母 */
一 、 实验目的
通过在实验二的基础上,增加中间代码生成部 分,使程序能够 对实验二中的识别出的赋值语句,if语句和 while语句进行语义分析,生成四元式中间代 码。
二 、 实验方法
实验程序由c语言完成,在Turboc 2.0环境中调 试通过。 语义分析程序的基本做法是对文法中的每 个产生式分别编写一个语义分析子程序,当 程序语法部分进行推倒或规约时,就分别调 用各自的语义分析程序。当语法分析结束 时,语义分析也就结束了。 在本实验程序中,当语法分析部分识别出 语法正确的句子时,就进入content函数 (当语法分析识别出不正确的句子时,不进 入content函数,也就是不进行语义分 析),然后根据句子的类型进行分类,进入 不同的语义处理部分。 对于赋值语句,关键是产生正确的处理算
术表达式E的四元式。程序中的ec函数的功 能就是产生算术表达式的四元式,在ec函数 中使用了两个栈idshed,opshed,分别是 算术表达式的数据栈和符号栈。每次提取一 个数字和一个算符,然后将算符与与栈顶算 符进行优先级比较,优先级高则将单前数字 和算符进栈,低或者相等的话则将当前栈顶 元素进行合并,产生四元式。直至整个算术 表达式结束。其中还有一些细节问题,具体 的做法可以参看程序。 对于实验给定的if语句的文法格式,条件判 断式C只中可能是>或者<=两种关系,不可能 是布尔表达式,这样程序就简单的多了。 通过ec函数可以产生条件判断式C中的E的四 元式,然后只要加上转向四元式就可以了。 本实验程序中只给出真出口的转向四元式, 没有给出假出口的转向四元式,这在实际中 是不可以的,但在本实验中,实际上是对每 条独立的语句进行语法分析,给出假出口转 向四元式实际上意义不大,而且假出口转向 语句的转移目标必须要到整个语句分析结束 以后才可以知道,这样就要建立栈,然后回 填,这样会使程序复杂很多,所以没有加上 假出口转向四元式。 对于while语句,具体的做法和if语句差不 多,所不同的是当while语句结束时,要多出
/* 判断ch是不是数字 */
int jstr(char ch){ /* 判断ch是不是字母或数字 */ if(strchr(strstring,ch)==0) return 0; else return 1; } void advance() { getnbc(); kind=0; if (jchar(ch)==1) {
if (li==0) retract(); else ret(); kind=22; token[k]='\0'; strcpy(sym,token); } else { if(ch=='.') kind=26; k=0; do{ sym[k]=' '; k++; }while(k!=15); sym[0]=ch; sym[1]='\0'; } } void error(int n){ judge=0; /*出错退出,将judge=0*/ switch(n){ case 0:{printf(" Error(0):Expect ':' \n"); break;} case 1:{printf(" Error(1):Expect '=' \n"); break;} case 2:{printf(" Error(2):Syntax error \n");break;} case 3:{printf(" Error(3):Except Operater \n");break;} case 4:{printf(" Error(4):Except ID or NUM \n");break;} case 5:{printf(" Error(5):Except ';' \n");break;} case 6:{printf(" Error(6):Except '<' or '>'\n");break;} case 7:{printf(" Error(7):Except '=' \n" );break;}
五 、 实验小结