编译原理-递归下降子程序-课程设计报告
编译原理实验报告——实验二 递归下降分析
printf("T'->*FT'\t"); printf("#E'T'F*\t\t"); print(); } else { printf("T'->/FT'\t"); printf("#E'T'F/\t\t"); print(); }
7
myAdvance(); printf("\t\t"); printf("#E'T'F\t\t"); print(); myF(); } if( sym!='*'||sym!='/') { printf("T'->^\t\t"); printf("#E'\t\t"); print(); } return(1); } else return(0); } /*判断是否是表达式或者括号*/ int myF() { int p; if (sym >= 'A' && sym <= 'Z' || sym >= 'a' && sym <= 'z' ) { printf("F->i\t\t"); printf("#E'T'i\t\t"); print(); myAdvance(); printf("\t\t"); printf("#E'T'\t\t"); print(); return(1); } else{
编译原理实验报告算术表达式递归下降分析程序设计
武汉工程大学计算机科学与工程学院《编译原理》实验报告一、实验目的(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下: E E+T | TT T*F | FF(E) | i设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归函数,函数的名字表示规则左部的非终结符;函数体按规则右部符号串的顺序编写。
三、设计分析(1)消去该文法左递归,得到文法:E TE1E1+TE1|εT FT1T1*FT1|εF(E)| I(2)根据LL(1)文法的判断条件,计算这个文法的每个非终结符的FIRST 集和FOLLOW集,经验证,改后的文法已经是LL(1)文法。
(3)最后构造递归下降分析程序,每个函数名是相应的非终结符,函数体则是根据右部符号串的结构编写。
a.当遇到非终结符时,如:+。
则编写语句 if(当读来的输入符号 == +) 读下一个输入符号b.当遇到非终结符时,例如:T。
则编写语句调用T()。
c.当遇到非终结符ε规则时,例如:Tε。
则编写语句 if(当前读来的输入字符不属于FOLLOW(T)) error()d.当某个非终结符的规则有很多个候选式时。
按LL(1)文法的条件能唯一的选择一个候选式进行推导。
(4)递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。
因此需要分别构造E,E1,T,T1,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。
Scaner函数用于字符串的推进,input函数用于字符串的输入。
四、程序代码#include <>#include <>#include <iostream>using namespace std;char a[80];char sym;int i=0;void E();void E1();void T();elseError();}else if (sym =='i')Scaner();elseError();}五、测试用例1.输入的字符串只含有一个字符时:输入 i#a#2.输入的字符串含有 + 时:输入 ++#输入 i++#输入 i+i#3.输入的字符串含有 * 时:输入 **#输入 **i#输入 *i*#输入 i*i#i*i*#3.输入的字符串含有()时:输入()#(i)#4.输入的字符串含有多种字符:输入i+i*i#(i+i)*i#(i+i)*(i+i)#(i+*#。
编译原理_实验二_语法分析_递归下降分析器设计_实验报告
递归下降分析器设计一、实验/实习过程内容:利用JavaCC生成一个MiniC的语法分析器;要求:1. 用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。
2. 具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3. 如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉〈语句串〉|〈语句〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|==|!=2.消除语句中的回溯与左递归3.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)4.完成的功能包括词法分析,语法分析二、代码:options {JDK_VERSION = "1.5";}PARSER_BEGIN(eg1)public class eg1 {public static void main(String args[]) throws ParseException { eg1 parser = new eg1(System.in);parser.start();}}PARSER_END(eg1)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS: "+" >| < MINUS: "-" >| < MULTIPLY: "*" >| < DIVIDE: "/" >}TOKEN :{<BIGGER:">"> |<SMALLER:"<"> |<NOTVOLUTION:"!="> |<SMALLEREQDD:"<="> |<BIGGEREE:">=" > |<DOUBLE:"==">TOKEN: //关键字{<MAIN:"main"> |<VOID:"void"> |<IF:"if"> |<INT:"int"> | <WHILE:"while"> |<CHAR:"char"> | <VOLUTION:"="> }TOKEN : //定义整型数{< INTEGER: ["0" - "9"]( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN : //数字{<NUMBER:(<DIGIT>)+ | (<DIGIT>)+"."| (<DIGIT>)+"."(<DIGIT>)+| "."(<DIGIT>)+>}TOKEN : //标记{<COMMA:","> | <SEMICOLON:";"> | <COLON:":"> | <LEFTPARENTHESES:"("> |<RIGHTPARENTHESES:")"> | <LEFTBRACE:"{"> | <RIGHTBRACE:"}"> }TOKEN : //标识符{<IDENTIFIER:<LETTER> |<LETTER>(<LETTER> | <DIGIT> )* >|<#LETTER:["a"-"z", "A"-"Z"]>}void start():{}{<MAIN> <LEFTPARENTHESES> <RIGHTPARENTHESES> block() }void block():{}{<LEFTBRACE> string() <RIGHTBRACE>}void string():{}{yuju() (string())?}void yuju():{}{fuzhiyuju() | tiaojianyuju() | xunhuanyuju()}void fuzhiyuju():{}{<IDENTIFIER> <VOLUTION> biaodashi() <SEMICOLON>}void tiaojianyuju():{}{<IF> tiaojian() block()}void xunhuanyuju():{}<WHILE> tiaojian() block()}void tiaojian():{}{<LEFTPARENTHESES> biaodashi() guanxifu() biaodashi()<RIGHTPARENTHESES>}void biaodashi():{}{( <LEFTPARENTHESES> biaodashi() <RIGHTPARENTHESES> biaodashi2()) |(<IDENTIFIER> biaodashi2() ) | ( <NUMBER> biaodashi2() )}void biaodashi2():{}{(yunsuanfu() biaodashi() biaodashi2() )?}void yunsuanfu():{}{< PLUS > | < MINUS > |< MULTIPLY> | < DIVIDE >}void guanxifu() :{}{<BIGGER> | <SMALLER> | <NOTVOLUTION><SMALLEREQDD> | <BIGGEREE> | <DOUBLE>}三、实验/实习总结本次实习,我使用javacc完成了包括词法分析,语法分析(输出语法树),能够读文件的功能,总的来说比较满意,通过本次实习掌握了javacc基本的使用。
编译原理递归下降子程序
北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx _ 作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求1.针对算术表达式文法:E→TE’E’→ +TE’|εT→FT’T’→*FT’ |εF→(E) |i为其编写递归下降子程序,判定某个算术表达式是否正确:如j+k*m,j*k+m输入:其输入数据应该为词法分析器输出的记号形式:i+i*i,i*i+i输出:分析结果:算术表达式结构正确或结构错误。
三、实验程序设计说明1.实验方案设计各个函数之间的调用关系如下图所示:2.程序源代码源代码如下:#include<stdio.h>#include<iostream>#include<fstream>#include<string>char a[10];int lookahead=0;void E1();void T();void T1();void F();void E(){printf("E->TE'\n");T();E1();}void E1(){if(a[lookahead]=='+'){printf("E'->+TE'\n");lookahead++;T();E1();}elseprintf("T'->ε\n"); }void T(){printf("T->FT'\n");F();T1();}void T1(){if(a[lookahead]=='*'){printf("T'->*FT'\n");lookahead++;F();T1();}elseprintf("T'->ε\n"); }void F(){if(a[lookahead]=='i'){printf("F->i\n");lookahead++;}else if (a[lookahead]=='('){lookahead++;E();if(a[lookahead]==')'){printf("F->(E)\n");lookahead++;}else{printf("\n括号不匹配分析失败!\n");exit (0);}}else{printf("括号不匹配,分析失败!\n");exit(0);}}int main(){while(1){printf("请输入算数表达式(以#键结束):");scanf("%s",a);E();if((a[lookahead]=='#'))printf("句子结构正确\n");elseprintf("无结束标志,分析失败\n");}return 0;}3.程序的执行结果程序运行结果如下所示:四、实验中出现的问题及解决方法1.错误处理:最初程序只是将所有的错误都简单的显示为句子结构错误,并没有进行具体详细的说明和解释,最后通过修改程序,细化错误类型,使用了对if语句的嵌套,将错误分为三种类型。
编译原理-实验二-递归下降分析程序构造
编译原理-实验⼆-递归下降分析程序构造集美⼤学计算机⼯程学院实验报告课程名称:编译原理指导教师:付永钢实验成绩:实验编号:实验⼆实验名称:递归下降分析程序构造班级:计算12姓名:学号:上机实践⽇期:2014.11上机实践时间: 4学时⼀、实验⽬的通过设计、编制、调试⼀个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进⾏语法检查和结构分析,掌握常⽤的语法分析⽅法。
通过本实验,应达到以下⽬标:(1) 掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序内部表⽰⽂件的⽅法;(2)掌握语法分析的实现⽅法;(3)上机调试编出的语法分析程序。
⼆、实验环境Windows7 x64、VC6.0三、实验原理递归下降法是语法分析中最易懂的⼀种⽅法。
它的主要原理是,对每个⾮终结符按其产⽣式结构构造相应语法分析⼦程序,其中终结符产⽣匹配命令,⽽⾮终结符则产⽣过程调⽤命令。
因为⽂法递归相应⼦程序也递归,所以称这种⽅法为递归⼦程序下降法或递归下降法。
其中⼦程序的结构与产⽣式结构⼏乎是⼀致的。
递归下降分析程序的实现思想是:识别程序由⼀组⼦程序组成。
每个⼦程序对应于⼀个⾮终结符号。
每⼀个⼦程序的功能是:选择正确的右部,扫描完相应的字。
在右部中有⾮终结符号时,调⽤该⾮终结符号对应的⼦程序来完成。
⾃上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。
分析速度慢。
⽽⽆回溯的⾃上向下分析技术,可根据输⼊串的当前符号以及各产⽣式右部⾸符,选择某⾮终结符的产⽣式,效率⾼,且不易出错。
⽆回溯的⾃上向下分析技术可⽤的先决条件是:⽆左递归和⽆回溯。
即:假设A 的全部产⽣式为A →α1|α2|……|αn ,则必须满⾜如下条件才能保证可以唯⼀的选择合适的产⽣式First(A →αi )∩First (A →αj )=Φ,当i≠j.⽆左递归:既没有直接左递归,也没有间接左递归。
⽆回溯:对于⼈以⾮中介符号U 的产⽣式右部n x x x |...||21,其对应的字的⾸终结符号两两不相交。
编译原理语法分析递归下降子程序实验报告
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行FirstVT集及LastVT集的分析,并对输入的字符串进行规约输出规约结果成功或失败。
二、设计内容及步骤内容:在C++ 6.0中编写程序代码实现语法分析功能,调试得到相应文法的判断结果:是算符优先或不是。
若是,则输出各非终结符的FirstVT与LastVT集的结果,还可进行字符串的规约,输出详细的规约步骤,程序自动判别规约成功与失败。
步骤:1.看书,找资料,了解语法分析器的工作过程与原理2.分析题目,列出基本的设计思路1定义栈,进栈,出栈函数○2栈为空时的处理○3构造函数判断文法是否是算符文法,算符优先文法○4构造FirstVT和LastVT函数对文法的非终结符进行分析○5是算符优先文法时,构造函数对其可以进行输入待规约○串,输出规约结果○6构造主函数,对过程进行分析3.上机实践编码,将设计的思路转换成C++语言编码,编译运行4.测试,输入不同的文法,观察运行结果详细的算法描述详细设计伪代码如下:首先要声明变量,然后定义各个函数1.void Initstack(charstack &s){//定义栈s.base=new charLode[20];s.top=-1; }2. void push(charstack&s,charLode w){//字符进栈s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}3. void pop(charstack&s,charLode &w){//字符出栈w.E=s.base[s.top].E; 三、w.e=s.base[s.top].e;s.top--;}4. int IsEmpty(charstack s){//判断栈是否为空if(s.top==-1)return 1;else return 0;}5.int IsLetter(char ch){//判断是否为非终结符if(ch='A'&&ch= 'Z')return 1;else return 0;}6.int judge1(int n){ //judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法}7. void judge2(int n){//judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法8.int search1(char r[],int kk,char a){ //search1是查看存放终结符的数组r中是否含有重复的终结符}9.void createF(int n){ //createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体}10.void search(charLode w){ //search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1 }分情况讨论://产生式的后选式的第一个字符就是终结符的情况//产生式的后选式的第一个字符是非终结符的情况11.void LastVT(int n){//求LastVT}12.void FirstVT(int n){//求FirstVT}13.void createYXB(int n){//构造优先表分情况讨论://优先级等于的情况,用1值表示等于}//优先级小于的情况,用2值表示小于//优先级大于的情况,用3值表示大于}14.int judge3(char s,char a){//judge3是用来返回在归约过程中两个非终结符相比较的值}15.void print(char s[],charSTR[][20],int q,int u,int ii,int k){//打印归约的过程}16. void process(char STR[][20],int ii){//对输入的字符串进行归约的过程}四、设计结果分两大类,四种不同的情况第一类情况:产生式的候选式以终结符开始候选式以终结符开始经过存在递归式的非终结符后再以终结符结束篇二:编译原理递归下降子程序北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx_作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
编译原理实验二递归下降子程序
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
#include<stdio.h>#include<stdlib.h>#define N 20char Str[N]; /* 用于存放输入的字符串 */int i=0;int max=0; /* 输入字符串的长度下标 */int curr=0; /* 当前字符的下标 */int flag=0; /* 用于标记判断过程中是否出现错误 */void inputString(); /* 输入要分析的字符串 */void nextChar(); /* 分析下一个字符 */void E();void G();void T();void S();void F();void outputResult(); /* 输出分析结果 */void inputString(){printf("\n实验名:递归下降分析程序\n\n");printf("姓名:汪茁\t学号:0904011035\t班级:09计本(4)班\n\n");printf("文法如下:\n");printf("(1) E->TG\n(2) G->+TG|-TG\n(3) G->ε\n(4) T->FS\n");printf("(5) S->*FS|/FS\n(6) S->ε\n(7) F->(E)\n(8) F->i\n\n");printf("请输入要分析的字符串(以'#'号结束):\n");for(i=0;i<N;i++){scanf_s("%c",&Str[i]);if(Str[i]=='#'){max=i;break;}}printf("\n");}void nextChar(){if(curr==max){exit(0);}else{curr++;}}void E(){T();}void G(){if(Str[curr]=='+'){nextChar();T();G();}else if(Str[curr]=='-'){nextChar();T();G();}}void T(){F();S();}void S(){if(Str[curr]=='*'){nextChar();F();S();}else if(Str[curr]=='/'){nextChar();F();S();}}void F(){if(Str[curr]=='('){nextChar();E();if(Str[curr]==')'){nextChar();}else{flag=1;}}else if(Str[curr]=='i'){nextChar();}{flag=1;}}void outputResult(){printf("分析结果:符号串");for(i=0;i<max;i++){printf("%c",Str[i]);}if(flag==0){printf("是合法的符号串!\n\n");}else{printf("是非法的符号串!\n\n");}}void main(){inputString();E();outputResult();}图 1 合法符号串[i*i+i-i/i]图 2 非法符号串[i*i+i-i/i-]图 3 带括号的合法符号串[i*(i+i)-i]图 4 带括号的非法符号串[i*(i+i-i]。
编译原理实验递归下降分析器的设计含源代码和运行结果
FIRST(exp)= FIRST(term)= FIRST(factor)={id, number, ( }
FIRST(texp)={ ε,+, - }
FIRST(Addop)={+, - }
FIRST(tterm)={ ε,*, / }
FIRST(mulop)={*, / }
由于分析的文件中可能出现非法字符,而一旦发现非法字符就无需再接着分析,所以在每次读取一个字符时调用islegal函数判断是否是合法字符,并返回0或1.
在main()函数中,while((lookahead=='\n'||lookahead==' ')&&lookahead!=EOF)ﻩfscanf(resource,"%c",&lookahead);
void match(chart)//写入result文件,打印输出,并读取下一个
{
fprintf(result,"%c",lookahead);//向result写入
printf("%c",lookahead);
fscanf(resource,"%c",&lookahead);//读数据
}
number()//识别数字,如果遇到数字就一直接着读直到不是数字
{
while('0'<=lookahead&&lookahead<='9')
ﻩ{
ﻩfprintf(result,"%c",lookahead);//写入
printf("%c",lookahead);
递归下降程序实验报告
一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
编译原理实验报告二递归下降语法分析程序 (1)
编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期:201 年 5 月 25 日一、实验目的通过设计、调试递归下降语法分析程序,实现用词法分析从源程序中分出各种单词并对词法分析程序提供的单词序列进行语法检查和结构分析,熟悉并掌握常用的语法分析方法。
明确语法分析器的功能,在词法分析的基础上进一步分析程序;加深对课堂教学的理解;提高语法分析方法的实践能力;通过本实验,应达到以下目标:1、掌握递归下降的结构模型。
2、掌握语法分析的实现方法。
3、上机调试编出的语法分析程序。
二、实验过程有了第一次的经验,这次还是先画出流程图。
流程图如下:三、实验结果语法分析实验成功。
赋值时少写数字:缺少括号时:附(txt文档内容):程序运行后写入的:四、讨论与分析这个程序是在实验一的基础上写的,用的递归下降的方法。
不止能识别,还能判断一些语法的正误。
刚看书上附录的代码时,头都大了,觉得自己完成不了。
但是真正一步一步看下去,画出了流程图,就很清晰明白了。
一个函数嵌套一个函数,一步一步往细处走,刚开始是大体轮廓,然后就深入,直到最低层的判断。
书上的程序还是有一些漏洞,比如要写多个语句时,if,for,while在语句内不能加括号,不然只能分析至第一个,遇到“}”就结束了,所以在txt文件里写程序代码的时候要注意不能加{},这样才可以全部printf出来。
五、附录:关键代码(给出适当注释,可读性高)全部代码附vc++,这里粘贴主程序,以及各类函数。
int TESTparse();int TESTscan();int program();int compound_stat();int statement();int expression_stat();int expression();int bool_expr();int additive_expr();int term();int factor();int if_stat();int while_stat();int for_stat();int write_stat();int read_stat();int declaration_stat();int declaration_list();int statement_list();int compound_stat();#include<stdio.h>#include<ctype.h>int TESTscan();int TESTparse();FILE *fin,*fout;void main(){int es=0;es=TESTscan();if(es>0)printf("词法分析有错!编译停止!\n");else{printf("词法分析成功!\n");}if(es==0){es=TESTparse();if(es==0)printf("语法分析成功!\n");elseprintf("语法分析错误!\n");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。
递归下降分析程序的实现——合肥工业大学编译原理课程设计报告
课程设计报告设计题目17.递归下降分析程序的实现设计要求对文法 G:E→E+T|TT→T*F|FF→(E)|i构造出G的递归下降分析程序。
程序显示输出匹配过程(即自上而下生成语法分析树的步骤,输出各匹配产生式序号即可)。
设计思路(1)分析a) ∵E=>E+T=>E+T*F=>E+T*(E)即有E=>E+T*(E)存在左递归。
用直接改写法消除左递归,得到如下:E →TE’E’ →+TE’ | −TE’|εT →FT’T’ →*FT’ | /FT’|εF → (E) | ib) 对于以上改进的方法。
可得:对于E’:FIRST( E’ )=FIRST(+TE’)∪FIRST(-TE’)∪{ε}={+,−,ε} 对于T’:FIRST( T’ )=FIRST(*FT’)∪FIRST(/FT’)∪{ε}={*,∕,ε}而且:FIRST( E ) = FIRST( T ) = FIRST( F )=FIRST((E))∪FIRST(i)={(,i }由此得出各非终结符的FOLLOW集合如下:FOLLOW( E )= { ),#}FOLLOW(E’)= FOLLOW(E)={ ),#}FOLLOW( T )= FIRST(E’)\ε∪FOLLOW(E’)={+,−,),#}FOLLOW( T’ ) = FOLLOW( T ) ={+,−,),#}FOLLOW( F )=FIRST(T’)\ε∪FOLLOW(T’)={*,∕,+,−,),#}由以上FOLLOW集可以我们可以得出SELECT集如下:对ESELECT(E→TE’)=FIRST(TE’)=FIRST(T)={ (,i }对E’SELECT(E’→+TE’)={ + }SELECT(E’→−TE’)={ − }SELECT(E’→ε)={ε,),#}对TSELECT(T→FT’)={(,i}对T’SELECT(T’→*FT’)={ * }SELECT(T’→∕FT’)={ ∕ }SELECT(T’→ε)={ε,+,−,),#}对FSELECT(F→(E) )={ ( }SELECT(F→i)={ i }∴SELECT(E’→+TE’)∩SELECT(E’→−TE’)∩SELECT(E’→ε)=ΦSE LECT(T’→*FT’)∩SELECT(T’→∕FT’)∩SELECT(T’→ε)=ΦSELECT(F→(E) )∩SELECT(F→i)= Φ由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL (1)文法。
编译原理实验递归下降分析器的设计(含源代码和运行结果)
《编译原理》实验报告实验3 递归下降分析器的设计姓名学号班级计科1001班时间: 2012/4/15 地点:文波同组人:无指导教师:朱少林实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写递归下降语法分析程序的方法。
实验内容a.运用所学知识,编程实现递归下降语法分析程序。
使用递归下降分析算法分析表达式是否符合下文法:exp → exp addop term | termAddop →+ | -term→ term mulop factor | factormulop → * | /factor → (exp) | id | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到id 和number的值。
b.从数据文件中读出符号串,输出表达式并给出其正误评判。
实验数据文件中应该有多个表达式,可能有正确的也应该有错误的表达式;表达式有形式简单的也应该有复杂的。
每个表达式写在一行,以回车结束。
实验环境软件:VC++6.0实验前准备1、方案设计:①准备模拟数据:本实验中使用“work..cpp”②程序思想:为了使用递归向下的分析,为每个非终结符根据其产生式写一个分析程序,由于写入读出的操作频繁。
所以程序中还有一个match(char t)函数,该函数是将字符写入文件打印输出同时从文件中读取下一个字符,而由于id和number可能是多个字符构成,故写了number()和id()来分析数字和标识符,它们的功能仅仅是把整个number或id完整的读取出来并写入文件,打印输出。
由于分析的文件中可能出现非法字符,而一旦发现非法字符就无需再接着分析,所以在每次读取一个字符时调用islegal函数判断是否是合法字符,并返回0或1.在main()函数中,while((lookahead=='\n'||lookahead==' ')&&lookahead!=EOF) fscanf(resource,"%c",&lookahead);是为了忽略分析文件中的换行或空格,之后进入分析阶段,根据返回值判断是否是合法的表达式。
编译原理实验递归下降子程序
编译原理程序设计实验报告——表达式语法分析器的设计实现班级:计算机1306班姓名:王利达学号:20133959 实验目标:使用递归下降子程序法构造表达式语法分析器程序,分析并判别算术表达式,给出判别结果。
实验内容:一、概要设计算术表达式文法:E-> T | Eω0TT-> F | Tω1FF-> i | ( E )其中ω0:+ -ω1:* /i:数字或常数文法变换:E -> T E1E1 -> ω0 T E1 |εT -> F | T1T1 -> ω1 F T1 |εF -> i | ( E )其中ω0:+ -ω1:* /i:数字或常数二、数据结构输入表达式,存入一个大小为100、名为expstr的数组中,指针p指向数组expstr的首地址。
其中,数组内的表达式由用户输入,最后以字符“#”结束。
程序有subpE、subpE1、subpT、supbT1、supbF、i等子函数。
三、流程图E入口进入T进入E1E出口图1.E的子函数流程图 void subpE()E1入口进入T 进入E1E1出口当前字符是+或-?NY图2.E1子程序函数的流程图 void subpE1()图3.T 子程序函数的流程图 void subpT() T1入口进入F判断是否是*或/?读下一个字符进入T1T1出口N Y图4.T1的子程序流程图 void subpT1()F 入口E1出口判断是否是i ?NYch=( ?ch=) ?进入E读下一个字符读下一个字符读下一个字符YYError!NN图4.F 子程序的流程图 void subpF()四、关键函数函数int i()是一个能简单判断表达式中i 是否是常数或变量的函数,它还能对不符合算术表达式要求的i 报错。
int i(){char cn=*(p+1);//取数组中下一个字符if((ch>='0'&&ch<='9')&&((cn>='a'&&cn<='z')||(cn>='A'&&cn<='Z'))){cout<<"错误!i 的格式不正确!"<<endl;ch=0;return 0;}else if(ch!='('&&ch!='#'){if((cn>='a'&&cn<='z')||(cn>='A'&&cn<='Z')||(cn>='0'&&cn<='9')){p++;ch=*p;return i();}else if(cn=='.'){p++;ch=*p;return i();}}else if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) {return 1;}elsereturn 0;}源程序代码:(加入注释)//main.cpp#include<iostream>#include<stdio.h>#include<string.h>using namespace std;char ch;char expstr[100];//用户输入的数组char *p=expstr;//指向数组的指针void subpE();//E的子程序函数void subpE1();//E1的子程序函数void subpT();//T的子程序函数void subpT1();//T1的子程序函数void subpF();//F的子程序函数int i();//简易判断i元素的函数void subpE(){subpT();subpE1();}void subpE1(){if(ch=='+'||ch=='-'){p++; //指针指向下一个ch=*p;subpT();subpE1();}}void subpT(){subpF();subpT1();}void subpT1(){if(ch=='*'||ch=='/'){p++;ch=*p;subpF();subpT1();}}void subpF(){if(i()){p++;ch=*p;}else if(ch=='('){p++;ch=*p;if(ch==')'){p++;ch=*p;}else{cout<<"错误!括号不匹配!"<<endl;ch=0;}}else{cout<<"错误!括号不匹配!"<<endl;ch=0;}}int i(){char cn=*(p+1);//取数组中下一个字符if((ch>='0'&&ch<='9')&&((cn>='a'&&cn<='z')||(cn>='A'&&cn<='Z'))) {cout<<"错误!i的格式不正确!"<<endl;ch=0;return 0;}else if(ch!='('&&ch!='#'){if((cn>='a'&&cn<='z')||(cn>='A'&&cn<='Z')||(cn>='0'&&cn<='9')){p++;ch=*p;return i();}else if(cn=='.'){p++;ch=*p;return i();}}else if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) {}elsereturn 0;}int main(){cout<<"请输入一个表达式并以\"#\"结束:"<<endl;cin>>expstr;ch=*p;subpE();if(ch=='#')cout<<"正确!"<<endl;elsecout<<"错误!"<<endl;return 0;}程序运行结果:(截屏)图5. 正确的算术表达式判断((Aa+Bb)*((88.2)/3))思考问题回答:(如果有)。
编译原理-递归下降子程序-课程设计报告
编译原理课程设计报告2011 年 12 月 2 日设计题目 递归下降分析程序的实现 学号专业班级 计算机科学与技术学生姓名指导教师一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:递归下降分析程序的实现设计内容及要求:对文法 G: E→E+T|T构造出G的递归下降分析程序。
程序显示输出T→T*F|F匹配过程(即自上而下生成语法分析树的步骤,F→(E)|i 输出各匹配产生式序号即可)。
三、设计思路:(1)语法分析:语法分析是编译程序的核心部分,任务是分析一个文法的句子结构。
递归下降分析程序的实现的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。
(2)自上而下分析:从文法的开始符号出发,向下推导,推出句子。
可分为带“回溯”的和不带回溯的递归子程序(递归下降)分析方法。
它的主旨是对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下地为输入串建立一棵语法树。
或者说,为输入串寻找一个最左推导。
也即从文法的开始符号出发,反复使用各种产生式,寻找"匹配"的推导。
(3)递归下降分析法:对每一语法变量(非终结符)构造一个相应的子程序,每个子程序识别一定的语法单位,通过子程序间的信息反馈和联合作用实现对输入串的识别。
(4)分析过程中遇到的问题:a. 分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。
出错时,不得不“回溯”。
b.文法左递归问题。
含有左递归的文法将使自上而下的分析陷入无限循环。
(5)构造不带回溯的自上而下分析算法:a.要消除文法的左递归性:一个文法可以消除左递归的条件是①不含以 为右部的产生式②不含回路。
b.克服回溯,构造不带回溯的自上而下分析的文法条件(6)满足LL(1)文法的三个条件:①. 文法不含左递归,②. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。
实验三递归下降分析器设计与实现编译原理实验报告
实验三递归下降分析器设计与实现编译原理实验报告一、引言递归下降分析器是编译原理中常用的一种语法分析方法。
它根据文法规则和输入的源代码,递归地进行语法分析,判断源代码是否符合给定的文法规则。
本实验旨在通过设计与实现一个简单的递归下降分析器,加深对编译原理中语法分析的理解。
二、实验目的1.学习递归下降分析器的原理和设计方法;2.掌握使用递归下降分析器进行简单语法分析的过程;3.加深对编译原理中文法规则和语法分析的理解。
三、实验过程1.设计文法规则:根据实验要求,设计一个简单的算术表达式文法规则。
例如,我们可以采用以下文法规则:```E->E+T,E-T,TT->T*F,T/F,FF -> ( E ) , num```2.设计分析器:根据设计的文法规则,设计递归下降分析器的结构和算法。
我们可以使用编程语言实现一个类,其中包含递归下降分析器所需要的方法和数据结构。
3. 实现分析器:根据设计的分析器结构和算法,使用编程语言实现递归下降分析器的代码。
可以选择常用的编程语言,如C++、Java、Python等。
4.进行语法分析:编写测试代码,使用实现的递归下降分析器对输入的算术表达式进行语法分析。
根据分析结果,判断输入的算术表达式是否符合给定的文法规则。
五、实验结果实验结果根据设计的分析器的实现和测试代码的编写而定。
例如,对于以下输入的算术表达式:(3+4)*5-2,经过递归下降分析器的分析,应该能正确判断其是否符合给定的文法规则。
六、实验总结递归下降分析器是编译原理中常用的一种语法分析方法。
通过实验三,我深入理解了递归下降分析器的原理和设计方法,并通过实现一个简单的递归下降分析器,加深了我对编译原理中文法规则和语法分析的理解。
在实验过程中,我学会了如何根据设计的文法规则来设计递归下降分析器的结构和算法。
我使用了编程语言实现了递归下降分析器的代码,并编写了相应的测试代码进行语法分析。
通过测试,我验证了递归下降分析器的正确性。
递归下降分析课程设计
递归下降分析课程设计一、课程目标知识目标:1. 理解递归下降分析的基本概念,掌握其工作原理和应用场景。
2. 学会运用递归下降分析法对简单程序代码进行语法分析,识别语法错误。
3. 了解递归下降分析在编译原理中的应用,明确其在编程语言处理中的重要性。
技能目标:1. 能够运用递归下降分析法编写简单的语法分析程序,对给定程序进行语法检查。
2. 能够通过递归下降分析,识别并修复程序中的语法错误。
3. 能够运用所学知识,对实际编程问题进行递归下降分析,提高编程能力。
情感态度价值观目标:1. 培养学生对编译原理学科的兴趣,激发学习热情。
2. 培养学生的团队协作意识,学会与他人共同解决问题。
3. 培养学生的批判性思维,敢于质疑、勇于探索,形成积极向上的学习态度。
本课程针对高年级学生,课程性质为理论联系实际,注重培养学生的实际操作能力。
根据学生特点,课程设计力求深入浅出,通过实例分析,帮助学生更好地理解和掌握递归下降分析法的应用。
在教学过程中,关注学生的学习反馈,及时调整教学策略,确保课程目标的实现。
将课程目标分解为具体的学习成果,为后续教学设计和评估提供依据。
本章节教学内容主要包括以下三个方面:1. 递归下降分析基本概念:- 介绍语法分析的基本任务和递归下降分析法的原理。
- 解释递归下降分析在编译原理中的作用。
2. 递归下降分析法的应用:- 分析简单程序代码的语法结构,识别语法错误。
- 通过实例讲解递归下降分析法在实际编程中的应用。
教学大纲安排:- 第一节课:语法分析基本概念,递归下降分析法原理。
- 第二节课:简单程序代码的递归下降分析实例。
3. 编写递归下降分析程序:- 指导学生编写简单的递归下降分析程序,进行语法检查。
- 分析实际编程中遇到的语法问题,运用递归下降分析法进行解决。
教学大纲安排:- 第三节课:递归下降分析程序编写方法。
- 第四节课:递归下降分析在编程实践中的应用。
教材章节关联:本教学内容与教材中关于编译原理、语法分析以及递归下降分析的相关章节紧密关联。
递归下降课程设计
递归下降课程设计一、课程目标知识目标:1. 学生能理解递归下降算法的基本概念与原理,掌握其应用场景。
2. 学生能运用递归下降算法解决简单的数学问题,如求阶乘、斐波那契数列等。
3. 学生了解递归算法的时间复杂度和空间复杂度,并能够分析递归算法的效率。
技能目标:1. 学生能够编写简单的递归下降程序,具备调试和优化程序的能力。
2. 学生通过递归下降算法的学习,培养问题分析、抽象和解决的能力。
3. 学生能够运用递归思维解决实际问题,提高逻辑思维和编程能力。
情感态度价值观目标:1. 学生在学习过程中,培养对算法的热爱和探究精神,增强自信心和自主学习能力。
2. 学生通过团队协作解决问题,培养沟通、合作和共享的价值观。
3. 学生认识到递归算法在计算机科学和生活中的重要性,激发对科技发展的关注和责任感。
课程性质:本课程为计算机科学或算法相关课程的专题教学,旨在帮助学生深入理解递归下降算法,提高编程能力和问题解决能力。
学生特点:学生处于高中年级,已具备一定的数学基础和编程能力,对算法有一定的了解,但可能对递归算法的理解和应用尚不熟练。
教学要求:课程应注重理论与实践相结合,以案例驱动,引导学生通过实际操作和团队协作,掌握递归下降算法的核心知识,提高解决实际问题的能力。
教学过程中,注重培养学生的自主学习、沟通合作和创新能力。
通过本课程的学习,使学生在知识、技能和情感态度价值观方面得到全面提升。
二、教学内容1. 递归算法基本概念:介绍递归的定义、递归算法的组成部分,以及递归与循环的关系。
2. 递归下降算法原理:讲解递归下降算法的核心思想、递归调用的过程,以及递归终止条件。
- 以求解阶乘、斐波那契数列为例,分析递归下降算法的具体实现。
3. 递归算法的复杂度分析:介绍时间复杂度和空间复杂度概念,分析递归算法的性能特点。
4. 递归下降算法应用案例:结合实际应用场景,如分治算法、动态规划等,展示递归下降算法的优势。
- 通过案例引导学生运用递归思维解决问题。
编译原理递归下降分析
《编译原理》课程实验报告课程名称:递归下降分析专业:软件工程班级:.n e t112学号:201107082231学生姓名:陈亚东指导老师:陆筱霞2014年6月25日一、实验目的:根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验预习提示:1、递归下降分析法的功能词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。
2、递归下降分析法的前提改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法,3、递归下降分析法实验设计思想及算法为G的每个非终结符号U构造一个递归过程,不妨命名为U。
U的产生式的右边指出这个过程的代码结构:(1)若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
(2)若是非终结符号,则调用与此非终结符对应的过程。
当A的右部有多个产生式时,可用选择结构实现。
具体为:(1)对于每个非终结符号U->u1|u2|…|un处理的方法如下:U( ){ch=当前符号;if(ch可能是u1字的开头) 处理u1的程序部分;else if(ch可能是u2字的开头)处理u2的程序部分;…else error()}(2)对于每个右部u1->x1x2…xn的处理架构如下:处理x1的程序;处理x2的程序;…处理xn的程序;(3)如果右部为空,则不处理。
(4)对于右部中的每个符号xi①如果xi为终结符号:if(xi= = 当前的符号){NextChar();return;}else出错处理②如果xi为非终结符号,直接调用相应的过程xi()说明:NextChar为前进一个字符函数。
三、实验过程1、模块结构开始实例化对象输入符号串进行语法分析递归调用程序判断文法输出,结束图1-1 递归下降程序框架图2、设计步骤1)给定文法:E→E+T|TT→T*F|FF→(E)|i2)构造FIRST()集和FOLLOW()集表2-1 FIRST()集和FOLLOW()集FIRST FOLLOWE (,i #,+,)T (,i #,+,),*F (,i #,+,),*3、程序源代码using System;using System.Collections.Generic;using System.Text;namespace 递归下降语法分析{public class Program{public static char []a=new char[50];public static char []b=new char[50];public static char []d=new char[200];public static char []e=new char[10];public static char ch;public static int n1,i1=0,flag=1,n=5;public static int total=0;/*步骤计数器*/public static int E1(){int f,t;Console.Write(total);Console.Write("\tE-->TG\t");total++;flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}public static int E(){int f,t;Console.Write(total);Console.Write("\tE-->TG\t");total++;e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#'; output();flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}public static int T(){int f,t;Console.Write(total);Console.Write("\tT-->FS\t");total++;e[0]='T';e[1]='=';e[2]='>';e[3]='F';e[4]='S';e[5]='#';output();flag=1;input();input1();f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}public static int G(){int f;if(ch=='+') {b[i1]=ch;Console.Write(total);Console.Write("\tG-->+TG\t");total++;e[0]='G';e[1]='=';e[2]='>';e[3]='+';e[4]='T';e[5]='G';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0) return(0);G();return(1);}Console.Write(total);Console.Write("\tG-->^\t");total++;e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;input();input1();return(1);}public static int S(){int f,t;if(ch=='*') {b[i1]=ch;Console.Write(total);Console.Write("\tS-->*FS\t");total++;e[0]='S';e[1]='=';e[2]='>';e[3]='*';e[4]='F';e[5]='S';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}Console.Write(total);Console.Write("\tS-->^\t");total++;e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}public static int F(){int f;if(ch=='(') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->(E)\t");total++;e[0]='F';e[1]='=';e[2]='>';e[3]='(';e[4]='E';e[5]=')';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0);if(ch==')') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->(E)\t");total++;flag=0;input();input1();ch=a[++i1];}else {Console.Write("error\n");return(0);}}else if(ch=='i') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->i\t");total++;e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {Console.Write("error\n");return(0);}return(1);}public static void input(){int j=0;for (;j<=i1-flag;j++)Console.Write(b[j]); /*输出分析串*/Console.Write("\t\t");Console.Write("\t\t",ch); /*输出分析字符*/ }public static void input1(){int j;for (j=i1+1-flag;j<n1;j++)Console.Write(a[j]); /*输出剩余字符*/Console.Write("\n");}public static void output(){ /*推导式计算*/int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='#';n=n+2;i=n;i=i-2;while(d[i]!='>'&&i!=0) i=i-1;i=i+1;while(d[i]!=e[0]) i=i+1;q=i;m=q;k=q;while(d[m]!='>') m=m-1;m=m+1;while(m!=q) {d[n]=d[m];m=m+1;n=n+1;}d[n]='#';for(j=3;e[j]!='#';j++){d[n]=e[j];n=n+1;}k=k+1;while(d[k]!='=') {d[n]=d[k];n=n+1;k=k+1;}d[n]='#';//system("pause");}static void Main(string[] args){ /*递归分析*/int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';Console.Write("请输入字符串(长度<50,以#号结束)\n");do{ch=(char)Console.Read();a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];Console.Write("步骤\t文法\t分析串\t\t分析字符\t剩余串\n"); f=E1();if (f==0) return;if (ch=='#'){Console.Write("accept\n");p=0;x=d[p];while(x!='#') {Console.Write(x);p=p+1;x=d[p]; /*输出推导式*/ }}else {Console.Write("error\n");Console.Write("回车返回\n");Console.ReadLine();Console.ReadLine();return;}Console.Write("\n");Console.Write("回车返回\n");Console.ReadLine();Console.ReadLine();}}}4、程序输入输出举例1)输入“(i+i)*i”,分析如下图所示:2)输入“i+i#”,分析如下图所示:四、实验总结通过本次实验基本掌握了递归下降子程序分析方法,并且能将学到的知识学以致用,提高了对代码的分析能力,掌握了递归下降语法的构造,对自上再而下的语法分析模式有了更好的认识和理解。
编译原理用递归下降法进行表达式分析报告实验报告材料
《编译原理》课程实验报告一. 实验题目 用递归下降法进行语法分析的方法二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C 语言四. 实验内容(实验要求)词法分析程序和语法分析程序已经提供。
此语法分析程序能够实现:正确的输入可以给出结果。
例:输入表达式串为:(13+4)*3则应给出结果为51。
要求:(1)读懂源代码,理解内容写入实验报告(语法分析及语法分析程序和词法分析程序的接口)(2)把语法分析中使用的yyval ,用yytext 实现。
(3)在语法分析程序用加入出错处理(尽量完整,包括出错的位置,出错的原题目 用递归下降法进行表达式分析 专业 班级学号 姓名因,错误的重定位)五. 实验步骤1.生成lex.yy.c文件:将已给的mylexer.l文件打开,先理解,然后再在DOS环境下用flex运行此文件,这时会生成一个lex.yy.c文件。
2.创建工程:打开C-Free 5.0(注:用C-Free 4.0会出错),在菜单栏中的“工程(project)”菜单下选择“新建”;在新建工程中选择“控制台程序”,添加工程名字为“myleb”和保存位置后点“确定”;第1步选择“空的程序”点“下一步”;第2步再点“下一步”;最后点击“完成”。
3.在创建的工程中添加文件:在Source files文件夹中添加之前生成的lex.yy.c文件和syn.c文件,然后找到parser.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
如图:4.理解并修改syn.c文件:首先,将num = yyval.intval修改成num = atoi(yytext);将num = yyval.fval修改成num = atof(yytext)。
可以这样修改的原因:在.l文件中所写的规则中,有{DIGIT}+ { yyval.intval = atoi(yytext);return INTEGER; }和{DIGIT}+"."{DIGIT}* {yyval.fval = atof(yytext); return DOUBLE; } 这两句代码,其中yyval.intval = atoi(yytext)和yyval.fval = atof(yytext)就说明两者可以相互替代。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程设计报告2011 年 12 月 2 日设计题目 递归下降分析程序的实现 学号专业班级 计算机科学与技术学生姓名指导教师一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:递归下降分析程序的实现设计内容及要求:对文法 G: E→E+T|T构造出G的递归下降分析程序。
程序显示输出T→T*F|F匹配过程(即自上而下生成语法分析树的步骤,F→(E)|i 输出各匹配产生式序号即可)。
三、设计思路:(1)语法分析:语法分析是编译程序的核心部分,任务是分析一个文法的句子结构。
递归下降分析程序的实现的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。
(2)自上而下分析:从文法的开始符号出发,向下推导,推出句子。
可分为带“回溯”的和不带回溯的递归子程序(递归下降)分析方法。
它的主旨是对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下地为输入串建立一棵语法树。
或者说,为输入串寻找一个最左推导。
也即从文法的开始符号出发,反复使用各种产生式,寻找"匹配"的推导。
(3)递归下降分析法:对每一语法变量(非终结符)构造一个相应的子程序,每个子程序识别一定的语法单位,通过子程序间的信息反馈和联合作用实现对输入串的识别。
(4)分析过程中遇到的问题:a. 分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。
出错时,不得不“回溯”。
b.文法左递归问题。
含有左递归的文法将使自上而下的分析陷入无限循环。
(5)构造不带回溯的自上而下分析算法:a.要消除文法的左递归性:一个文法可以消除左递归的条件是①不含以 为右部的产生式②不含回路。
b.克服回溯,构造不带回溯的自上而下分析的文法条件(6)满足LL(1)文法的三个条件:①. 文法不含左递归,②. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。
即,若A→α 1|α2|…|α n 则 FIRST(αi)∩FIRST(αj)=f(i≠j)③. 对文法中的每个非终结符A,若它存在某个候选首符集包含ε,则FIRST(α i)∩FOLLOW(A)=f i=1,2,...,n(7)因此我们可以把设计要求的文法首先改写为LL(1)文法E→TE'E'→+TE' | εT→FT'T'→*FT' | εF→(E) | iﻩ然后构造每个非终结符的FIRST和FOLLOW集合:FIRST(E) ={ ( ,i } FIRST(E')={ + , e }FIRST(T)={ ( ,I }FIRST(T')={ * ,ε} FIRST(F) ={ ( , I } FOLLOW(E)={ ) ,# }FOLLOW(E')={) , # }FOLLOW(T) ={ + , ) , # }FOLLOW(T')={+, ) , # } FOLLOW(F) ={ *, + , ) , # }确定改写后的文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。
然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。
(8)编写C++代码用到的变量和几个功能识别函数:①.advance=0; //字符串小标,表示使IP指向下一输入符号。
②. void E(); // 功能识别函数,表示规则E->TE'void E1(); // 功能识别函数,表示规则E'->+TE'/εvoid T(); // 功能识别函数,表示规则T->FT'void T1(); //功能识别函数,表示规则T'->*FT'/εvoidF(); // 功能识别函数,表示规则F->(E)/i 因为每个非终结符有对应的子程序的定义,功能识别函数的编写过程中,当需要从某个非终结符出发进行展开(推导)时,就调用这个非终结符对应的子程序。
功能识别函数的设计与编写:(1)当遇到终结符a时,则编写语句If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到非终结符A时,则编写语句调用A()。
(3)当遇到A-->ε规则时,则编写语句If(当前读到的输入符号不属于Follow(A))error()(4)当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能唯一地选择一个候选式进行推导.四、结果截图:1、输入一个正确的句子:2、输入一个错误句子3、输入一个无#结束的错误句子:五、代码:#include<iostream>#include<fstream>usingnamespace std;ifstream import("input sentence.txt");ofstream export("output rule.txt");#include<string>chara[10]; // 字符串的存入int advance=0; // 字符串小标,表示使IP指向下一输入符号void E(); // 功能识别函数,表示规则E->TE'void E1(); //功能识别函数,表示规则E'->+TE'/εvoid T(); // 功能识别函数,表示规则T->FT'void T1(); //功能识别函数,表示规则T'->*FT'/εvoid F(); // 功能识别函数,表示规则F->(E)/iint main() // 主函数{ﻩﻩexport<<"please input theright sentence(end with #):";//输入提示import>>a;E(); //从首个推导式E开始if((a[advance]=='#'))export<<"The sentence isright,success!\n";elseexport<<"No the signal of #,fail!\n";ﻩﻩreturn 0;}void E() // 功能识别函数{export<<"E->TE'\n";T();E1();}void E1(){if(a[advance]=='+'){export<<"E'->+TE'\n";//输出使用E'规则ﻩ advance++; //如果是“+”,则读取下一字符T(); //根据E'->+TE规则右部符号串的顺序,调用其他非终结符的规则ﻩE1();ﻩ}elseexport<<"E'->ε\n";}void T(){export<<"T->FT'\n";F(); //根据T->FT'规则右部符号串的顺序,调用其他非终结符的规则T1();}void T1(){if(a[advance]=='*') //如果是“*”,则读取下一字符{export<<"T'->*FT'\n";advance++;F();//根据T'->*FT'规则右部符号串的顺序,调用其他非终结符的规则ﻩﻩT1();}elseexport<<"T'->ε\n";}voidF(){if(a[advance]=='i') //如果是“i”,则读取下一字符{export<<"F->i\n";advance++;}else if(a[advance]=='(') //如果是“(”,则读取下一字符{ﻩadvance++;E(); //根据F->(E)规则右部符号串的顺序,调用非终结符E的规则if(a[advance]==')'){ﻩ export<<"F->(E)\n";advance++;ﻩﻩﻩ}ﻩﻩﻩelse{ﻩexport<<"\n ()isnot matching,error! \n";exit (0); //正常结束程序运行}}else{export<<"\n ()is not matching, error!\n";exit(0);//正常结束程序运行}}六、心得体会:(1)一个星期的课程设计,当中有苦也有乐,但从苦乐中我学到了很多东西。
通过这次课程设计我看到了自己的与别人的差距,有很多我自己不明白的地方别人都会。
当我自己一开始进行递归下降分析程序的课程设计时,我发现我有好多相关的小知识点还不太熟悉,于是我在结合书本和图书馆相关资料基础上,将课堂学习的知识予以真正的吸收和应用,功夫不负有心人,我最终琢磨出了解决该设计题的基本思路和方法。
(2)这次课程设计,不仅巩固了课堂知识,很好的复习了一下编译原理所学的内容,而且提高了自己的上机实践能力,有效的和实际结合在了一起,加强了我的动手、思考、解决问题的能力,并扩展了所学知识。
同时在设计过程中也发现了我的许多不足之处,比如对以前所学的知识理解的不够深刻,掌握的不够牢固。
此外,因为设计程序的各项流程需要心静下来慢慢思考,所以克服了最近比较浮躁的心态,同时也让自己充实了很多。
(3)在设计过程中也遇到了一些问题,比如编写程序时,每读入一个字符,要执行相应的递归函数,因为调用过程中有再次调用,我有好几次把函数的调用搞混,导致得出的结果不是我想要的。
所以要在草稿纸上先画出程序的流程图,理顺各子程序之间的调用关系,才能避免程序出错。
还有不仅要知道文法要改为LL(1)文法,还要明白为什么要改,修改后有哪些好处以及LL(1)文法的具体定义与判定方法。
在最后进行程序的功能和结果的测试当中,我采用了文件输入输出流,把文件作为输入输出对象的流,实现结果的可视化,从而告别黑白屏界面,但如果能用MFC平台实现可视化界面就更好了,那样更有技术含量,更简洁美观。
(4)既然是上机实践就会遇到各种问题,不畏艰难,不怕繁复,就是我们解决问题的方法。
通过这次的设计,我发现只要不放弃,在最困难的时候坚持下去,那么所有的事情都能迎刃而解。