编译原理课程设计题目 (1)
编译原理试题及答案

编译原理试题及答案一、选择题1. 编译器的主要功能是什么?A. 程序设计B. 程序翻译C. 程序调试D. 数据处理答案:B2. 下列哪一项不是编译器的前端处理过程?A. 词法分析B. 语法分析C. 语义分析D. 代码生成答案:D3. 在编译原理中,词法分析器的主要作用是什么?A. 识别程序中的关键字和标识符B. 将源代码转换为中间代码C. 检查程序的语法结构D. 确定程序的运行环境答案:A4. 语法分析通常采用哪种方法?A. 自顶向下分析B. 自底向上分析C. 正则表达式匹配D. 直接解释执行答案:B5. 语义分析的主要任务是什么?A. 检查程序的语法结构B. 检查程序的类型安全C. 识别程序中的变量和常量D. 将源代码转换为机器代码答案:B二、简答题1. 简述编译器的工作原理。
答案:编译器的工作原理主要包括以下几个步骤:词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成。
词法分析器将源代码分解成一系列的词素;语法分析器根据语法规则检查词素序列是否合法;语义分析器检查程序的语义正确性;中间代码生成器将源代码转换为中间代码;代码优化器对中间代码进行优化;最后,目标代码生成器将优化后的中间代码转换为目标机器代码。
2. 什么是词法分析器,它在编译过程中的作用是什么?答案:词法分析器是编译器前端的一个组成部分,负责将源代码分解成一个个的词素(tokens),如关键字、标识符、常量、运算符等。
它在编译过程中的作用是为语法分析器提供输入,是编译过程的基础。
三、论述题1. 论述编译器中的代码优化技术及其重要性。
答案:代码优化是编译过程中的一个重要环节,它旨在提高程序的执行效率,减少资源消耗。
常见的代码优化技术包括:常量折叠、死代码消除、公共子表达式消除、循环不变代码外提、数组边界检查消除等。
代码优化的重要性在于,它可以显著提高程序的运行速度和性能,同时降低程序对内存和处理器资源的需求。
四、计算题1. 给定一个简单的四则运算表达式,请写出其对应的逆波兰表达式。
编译原理设计题目

编译原理设计题目设计原则:1.使用了《编译原理》中的某些内容,如原理、概念等;2.具有完整性,表现或演示了某种完整的功能;3.实用性,有一定的应用价值。
设计目的:花了足够的时间,做了一定量的工作,从而使得水平提高。
设计语言:任意熟悉的开发环境。
设计步骤:1.选好题目2.思考你将要把软件编成什么模样?3.写出需求分析4.开始设计5.测试第一大类:充分利用《编译原理》1.与表达式有关的内容:●表达式计算器:这是一款算术表达式计算程序,用户通过输入表达式达到计算的目的,可代替目前普遍使用的计算器。
使用了编译原理中的词法分析、算符优先分析等。
根据功能的不同可分为:⏹无符号整数表达式计算器:输入无符号整数表达式,输出结果。
难度:较难。
工作量:中等。
⏹整数表达式计算器:考虑负数。
难度:较难。
工作量:中等。
⏹定点实数表达式计算器:难度:较难。
工作量:中等。
⏹通用表达式计算器:考虑1.23e-2的形式输入。
难度:难。
工作量:中等。
●函数表达式计算程序:这是一款能计算函数值的实用程序,用户输入含有自变量x的函数表达式被电脑接受后,可接着输入自变量x的值,电脑输出函数值y的值。
用户可以是数学、物理等教师,他们可以在上课教授与函数有关的课程时进行课堂演算,也可以在备课时验证数据;用户也可以是工程技术人员和学生。
使用了词法分析、算符优先分析。
根据功能的不同可以分为:⏹多项式函数计算程序:只处理多项式函数,如f(x)=x^3+x^2+5等。
难度:较难。
也可设计成其他专用函数计算程序,如幂函数计算、三角函数计算等。
但要避免出现不同用,如不要设计成仅能处理f(x)=2^x的幂函数,因为这样的函数利用普通编程就能实现,无法体现编译原理。
工作量:中等。
⏹通用初等函数计算程序:能处理所有的初等函数的计算。
如f(x)=3*sin(x/2+3.1415)+x^2等。
难度:难(因为涉及到函数名称和参数的识别问题)。
工作量:较大。
⏹二元或多元函数的计算:请参考立体解析几何中相关方程。
编译原理课程设计LL(1)文法

本次课程设计主要是介绍LL(1)文法的一般原理,根据给定的一文法编制调试LL(1)文法语法分析程序,以便对任意输入的符号串进行分析。
本次课程设计的目的主要是加深对预测分析LL(1)文法语法分析的理解,加深对自顶向下语法分析方法的认识。
具体如下:1、对语法规则有明确的定义;2、编写的分析程序能够对给定文法进行正确的语法分析;3、对输入给定的文法,手工计算First、Follow集合以及各产生式的Select 集合,再根据Select集合构造出预测分析表;4、对于输入串,应能根据预测分析表判断识别该输入串是否为给定文法的句子;5、对于遇到的错误,给出简单的错误信息提示,保证能够顺利完成语法分析过程。
前言------------------------------------------------------------- Ⅰ目录------------------------------------------------------------- Ⅱ一、系统分析------------------------------------------------------ 11.1 判断LL(1)文法---------------------------------------------- 11.2 构造预测分析表---------------------------------------------- 1二、系统设计------------------------------------------------------ 22.1 基本设计---------------------------------------------------- 22.2 程序流程图-------------------------------------------------- 2三、系统实现------------------------------------------------------ 33.1 程序主要函数------------------------------------------------ 33.2 程序主要代码------------------------------------------------ 3四、系统测试------------------------------------------------------ 7五、总结---------------------------------------------------------- 8 参考文献---------------------------------------------------------- 9一、系统分析有文法G[E]:E->TG T->FSG->+TG|ε S->*FS|ε F->(E)|i 1.1 判断LL(1)文法当我们需选用自顶向下分析技术时,首先必须判别所给文法是否是LL(1)文法,分析所给文法可知文法中不含左公因子,也不存在左递归,因而再对给定文法计算First 集、Follow 集以及Select 集,对于求出的每个产生式的Select 集,看对于同一个左部非终结符是否存在交集,如果它们的交为空则表示所给文法是LL(1)文法,否则不是L(1)文法。
编译原理课程实验题目

编译原理实验题目编译原理的课程实验既是培养学生理论联系实际的必要手段也是检验我们教学理念的贯彻与实现、检查教学效果、让学生展示能力的重要途径。
为了达到上述目的,作为编译原理课程的上机实验,最好是能完成一个小型语言的基本编译系统,但这需要有较好的实验条件特别是较多的实验学时(理想的情形是专门配置一个两到三周的课程设计)的支撑。
对于一个只有56学时的编译原理课程的上机实验(仅为12学时),构造一个小型语言的完整的编译系统显然是不现实的;为最大程度达到教学目的,经由课程组的认真研究,将本课程实验分解为两个上机实验:1、词法分析器编制实验;2、语法制导的三地址代码生成器编制实验(第2个实验又可分解为自顶向下的语法分析器的设计与实现和三地址代码生成器的设计与实现两个实验)。
通过这两个程序的编制,使学生学会和体验构造一个微型编译系统的基本框架的主要工作。
实验一:词法分析程序的设计与实现一.实验目的基本掌握计算机语言的词法分析程序的开发方法。
二.实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三.实验要求1.根据以下的正规式,编制正规文法,画出状态图;标识符<字母>(<字母>|<数字字符>)*十进制整数0 | (1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和分隔符+ - * / > < = ( ) ;关键字if then else while do2.根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从键盘读入数据,分析出一个单词。
2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。
编译原理课程设计选题

编译原理课程设计选题一、教学目标本节课的教学目标是使学生掌握编译原理的基本概念、原理和方法,培养学生运用编译原理解决实际问题的能力。
具体目标如下:1.知识目标:(1)了解编译原理的基本概念,如编译器、解释器、源程序等;(2)掌握编译过程的各个阶段,如词法分析、语法分析、语义分析、中间代码生成、目标代码生成等;(3)熟悉常见编程语言的编译原理及其特点。
2.技能目标:(1)能够使用编译器或解释器对简单程序进行编译或解释;(2)能够运用编译原理分析程序的正确性和性能问题;(3)具备编写简单的编译器或解释器的能力。
3.情感态度价值观目标:(1)培养学生对编译原理的兴趣和好奇心,激发学生主动学习的动力;(2)培养学生团队协作、沟通交流的能力,提高学生解决实际问题的能力;(3)培养学生追求真理、勇于创新的精神风貌。
二、教学内容本节课的教学内容主要包括以下几个部分:1.编译原理概述:介绍编译器、解释器、源程序等基本概念,使学生了解编译原理的应用范围和重要性。
2.编译过程及其各个阶段:详细讲解编译过程的词法分析、语法分析、语义分析、中间代码生成、目标代码生成等阶段,使学生掌握编译过程的基本方法。
3.常见编程语言的编译原理:分析C、Java、Python等常见编程语言的编译原理及其特点,使学生了解不同编程语言的编译机制。
4.编译器设计实例:以一个简单的编译器为例,讲解编译器的实现方法和技巧,让学生具备编写简单编译器的能力。
三、教学方法为了提高教学效果,本节课将采用以下教学方法:1.讲授法:教师讲解编译原理的基本概念、原理和方法,引导学生掌握知识要点。
2.案例分析法:通过分析具体编程语言的编译实例,使学生了解编译原理在实际应用中的作用。
3.实验法:安排课后实验,让学生动手编写简单的编译器或解释器,提高学生的实践能力。
4.讨论法:学生分组讨论,鼓励学生提出问题、分享心得,培养学生的团队协作和沟通能力。
四、教学资源为了支持教学内容和教学方法的实施,本节课将采用以下教学资源:1.教材:《编译原理》(作者: Alfred V. Aho et al.);2.参考书:《计算机编译原理》(作者:陈意云);3.多媒体资料:PPT课件、视频教程等;4.实验设备:计算机、编程环境等。
编译原理课程设计-LL1文法分析器设计C++语言实现

集美大学计算机工程学院编译原理课程设计报告选题名称:LL(1)文法分析院(系):计算机工程学院专业:计算机科学与技术班级:计算1412指导教师:付永刚学年学期:2016 ~ 2017 学年第 2 学期2017 年06 月29 日摘要:选题要求:根据某一文法编制调试LL(1) 文法语法分分析程序,以便对任意输入的符号串进行分析。
本次课程设计的目的主要是加深对预测分析LL(1)文法语法分析法的理解。
具体如下:1、对语法规则有明确的定义;2、编写的分析程序能够对给定文法进行正确的语法分析;3、对输入给定的文法,手工计算FIRST、FOLLOW集合和select集合,应能判断识别是否为给定文法的句子,并给出推导过程。
4、对输入给定的文法,由程序自动构造FIRST、FOLLOW集合。
5、对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程。
关键词:语法分析;FIRST集合;FOLLOW集合;分析表一、设计内容及要求(1) 基于PL/0语言,通过编程判断该文法是否为LL(1)文法;(2)计算出文法的First() Follow()(3)构造相应文法的预测分析表(4)对某个输入句子进行语法分析二、实现原理1.LL(1)文法LL(1)文法是一类可以进行确定的自顶向下语法分析的文法。
就是要求描述语言的文法是无左递归的和无回溯的。
根据LL(1)文法的定义,对于同一非终结符A的任意两个产生式A:=a和A:=b,都要满足:SELECT(A:=a )∩SELECT(A:=b)=Ø。
(1)文法的左递归当一个文法是左递归文法时,采用自顶向下分析法会使分析过程进入无穷循环之中。
所以采用自顶向下语法分析需要消除文法的左递归性。
文法的左递归是指若文法中对任一非终结符A有推导AÞA…,则称该文法是左递归的。
左递归又可以分为直接左递归和间接左递归。
●直接左递归若文法中的某一产生式形如A→Aα,α∈V*,则称该文法是直接左递归的。
编译原理试题及答案

编译原理试题及答案
试题:
1. 解释编译原理的定义,同时给出编译器的作用。
2. 简要描述编译过程中的四个基本步骤。
3. 解释词法分析器的功能和作用。
4. 解释语法分析器的功能和作用。
答案:
1. 编译原理是研究如何将高级语言程序转化为等价机器语言程序的一门学科。
编译器是将高级语言文本转换成等价的机器语言的软件工具。
它负责将源代码转化为目标代码,以便计算机能够理解和执行。
2. (1) 词法分析:将源代码分解成一系列单词或标记。
(2) 语法分析:根据语法规则组织单词或标记形成语法树。
(3) 语义分析:分析语法树以检测语义错误。
(4) 代码生成:根据语法树生成目标代码。
3. 词法分析器的功能是将源代码分解成一系列单词或标记。
它将源代码读取为字符流,然后将这些字符组成单词,同时可以去除空格、注释等不具有实际意义的内容。
词法分析器的作用是为语法分析器提供正确的单词序列,为后续的语义分析和代
码生成步骤建立基础。
4. 语法分析器的功能是根据语法规则组织单词或标记形成语法树。
它通过构建语法树来分析源代码的语法结构,同时可以检测语法错误。
语法分析器的作用是为后续的语义分析和代码生成步骤提供一个结构化的表示形式,便于后续的处理和转换。
编译原理课程设计-LL(1)文法的判定

课程设计报告课程:编译原理课程设计学号:姓名:班级:教师:时间:计算机科学与技术系结果与分析(可以加页):1、输入一个LL(1)进行测试,测试文法,测试结果如下图所示G(Z):Z->dAZ | bAcA->aA|ε图4 输入LL(1)文法并测试2、输入上述文法的一个句型进行测试,测试结果如下图所示待测试的句型1: bac图5 测试满足指定文法的句型待测试句型2:abc图6 测试不满足指定文法的句型3、测试一个非LL(1)文法图7 测试非LL(1)文法设计体会与建议:近一个月的设计过程,虽然题目早已经布下,但当时正在学习中,看到题目仅是一头雾水,没有一点头绪。
刚拿到题目的时候,乍看很简单,但当真正入手做的时候,觉得设计一个合理的数据结构不是一件很容易的事。
因为一个好的软件设计,应该考虑到它的健壮性和可扩充性,而且能够做的比较完善,对于系统运行中可能遇到的问题能够给出人性化的提示。
这需要在问题分析和题目设计的过程中逐渐改进。
就本次设计而言,要构造预测分析表,就要考虑输入的文法是否是LL(1)文法,对检测的结果应该给予适当的处理。
经过查找资料和他人的耐心答疑,我终于设计处理较为合理的程序,达到了预期的课程设计目的。
随着课程的深入,逐渐了解到一点解题的方法,但对于上机实践还是没有什么想法,后来到图书馆和网上找了很多资料,才了解到大致的实现方法,有根据以前的一点编程经验,于是开始一个模块一个模块的去实现,然后在进行整合,合并成一个完整的程序。
通过本次课程设计,使学到的理论知识得到了实践,清晰地看到了LL(1)分析的全过程,掌握了first,follow,select的机上实现方法,掌握了分析表的构造过程和方法,但遗憾的是,对于一些实现方法,例如句型分析的跟踪过程,仍是参考的网上的源程序,感到了自己的不足,还需更加努力!附录:程序代码#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]){char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘ ^ ’一并并入目串;type=2,源串中的‘ ^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘ ^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘ ^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘ ^ ’,报错*/printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;char ch='^';c=v[i];emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/ void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("词法错误!");return;}}if(M[i][k]==-1){printf("语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("S:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" \n");}}/*******************************************一个用户调用函数********************************************/ void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);menu();}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程设计
一、课程设计的基本要求和方法
(一)、目的
进一步培养学生编译器设计的思想,加深对编译原理和应用程序的理解,针对编译过程的重点和难点内容进行编程,独立完成有一定工作量的程序设计任务,同时强调好的程序设计风格,并综合使用程序设计语言、数据结构和编译原理的知识,熟悉使用开发工具VC /JA V A/C#/.NET 。
(二)、课程设计步骤
1、问题理解和分析
充分地分析和理解问题本身,弄清要求做什么。
2、确定解决问题的方法(设计)
主要是找到解决问题的主要思路,是怎么做。
在此阶段可考虑系统的功
能和模块划分等。
3、详细设计和编码
确定算法的主要流程,再进行编程。
在此阶段应提醒学生程序可先在纸上写,尽量想清楚了再动手上机,在编程过程中注意程序结构的清晰性,避免出现很多明显的程序逻辑错误和语法错误,提高后面程序调试效率。
4、程序调试和运行
使学生掌握程序调试和排错的基本方法,增加编程的感觉和解决问题的成就感。
5、完成课程设计报告(使用华东交通大学课程设计报告,需学生自己购买)
1)问题描述
题目要解决的问题是什么
2)分析、设计、实现
解决问题的基本方法说明,包括主要算法思想,算法的流程图。
程序中主要函数或过程的功能说明。
3)运行结果分析。
4)总结
遇到的主要问题是如何解决的、对设计和编码的回顾讨论和分析、进一步改进设想、经验和体会等。
5)附录,包括源程序关键代码和运行结果。
(三)、考核评估
通过程序实现、总结报告和学习态度综合考评,并结合学生的动手能力,独立分析解决问题的能力和创新精神。
成绩分优、良、中、及格和不及格五等。
考核标准包括:
(1)编译器思想的正确性,包括是否采用了合适的数据存储结构等。
(2)程序实现的正确性,包括程序整体结构是否合理、编程风格是否规范等。
(3)程序功能的完善程度,包括功能的基本实现、基本完善、完全实现(4)学生的工作态度、独立工作能力。
(5)课程设计报告。
以上五项考核内容,每项占的权重均为20% 。
二、 编译原理设计题目
以下有六个课程设计题目,要求学生从中选择一个题目做本次课程设计。
(一) First 集和Follow 集生成算法模拟
【问题描述】
设计一个由正规文法生成First 集和Follow 集并进行简化的算法动态模拟。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是: (1) 输入一个文法G ;
(2) 输出由文法G 构造FIRST 集的算法; (3) 输出First 集;
(4) 输出由文法G 构造FOLLOW 集的算法; (5) 输出FOLLOW 集。
【测试数据】
输入文法: E->TE ’
E ’->+TE ’|ε T->FT ’
T ’->*FT ’|εF->(E)|i
【实现提示】
用数据库存储多行文法,用LIST 控件显示算法,用GRID 类依据算法进行作图。
并实现算法与生成过程的关联。
(二)LL(1)分析过程模拟
【问题描述】
设计一个给定LL (1)分析表,输入一个句子,能由依据LL (1)分析表输出与句子对应i )
(
*
+
F 的f i r s t 集
T 的f i r s t 集 E 的f i r s t 集 1
1
1
1 1
1
1 1 1
的语法树。
能对语法树生成过程进行模拟。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是:
(1) 输入LL (1)分析表和一个句子; (2) 输出LL (1)总控程序;
(3) 输出依据句子构成的对应语法树的过程;
【测试数据】
输入句子:i*i+i
输入LL (1)分析表
【实现提示】
用结构体数组存储多行正规式,用LIST 控件显示算法,用CDC 类依据进行算法进行
作图。
并实现算法与生成过程的关联。
(三)FirstVT 集和LastVT 集生成算法模拟
【问题描述】
设计一个由正规文法生成FirstVT 集和LastVT 集的算法动态模拟。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是: (1) 输入一个文法G ;
(2) 输出由文法G 构造FIRSTVT 集的算法; (3) 输出FirstVT 集;
(4) 输出由文法G 构造LastVT 集的算法; (5) 输出LastVT 集。
→(E )
→i
F →ε → ε →*F T '
→ ε
T ' →F T ' →F T '
T →ε → ε →+T E ' E ' →T E '
→T E '
E
#
) (
* + i
【测试数据】
输入文法: E->TE ’
E ’->+TE ’|ε T->FT ’
T ’->*FT ’|εF->(E)|i
【实现提示】
用数据库存储多行文法,用LIST 控件显示算法,用GRID 类依据算法进行作图。
并实现算法与生成过程的关联。
(四) 算符优先分析表生成模拟
【问题描述】
设计一个给定文法和对应的FIRSTVT 和LASTVT 集,能依据依据文法和FIRSTVT 和LASTVT 生成算符优先分析表。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是:
(1) 输入一个给定文法,及FIRSTVT 和LASTVT 集; (2) 输出算符优先分析表生成算法;
(3) 输出算法优先分析表构造过程的过程;
【测试数据】
输入文法: E->TE ’
E ’->+TE ’|ε T->FT ’
T ’->*FT ’|εF->(E)|i
【实现提示】
用结构体数组存储多行正规式,用LIST 控件显示算法,用CDC 类依据进行算法进行作图。
并实现算法与生成过程的关联。
i )
(
*
+
F 的f i r s t V T
T 的f i r s t V T E 的f i r s t V T 1
1
1
1 1
1
1 1 1
(五)算符优先分析过程模拟
【问题描述】
设计一个给定算符优先分析表,输入一个句子,能由依据算符优先分析表输出与句子对应的语法树。
能对语法树生成过程进行模拟。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是:
(1)输入算符优先分析表和一个句子;
(2)输出算符优先分析总控程序;
(3)输出依据句子构对应的语法树的过程;
【测试数据】
输入句子:i*i+i
输入算符优先分析表
【实现提示】
用结构体数组存储多行正规式,用LIST控件显示算法,用CDC类依据进行算法进行作图。
并实现算法与生成过程的关联。
(六)L R分析过程模拟
【问题描述】
设计一个给定LR分析表,输入一个句子,能由依据LR分析表输出与句子对应的语法树。
能对语法树生成过程进行模拟。
(算法参见教材)
【基本要求】
动态模拟算法的基本功能是:
(1)输入LR分析表和一个句子;
(2)输出LR总控程序;
(3)输出依据句子构对应的语法树的过程;
【测试数据】
输入句子:i*i+i
输入LR分析表
【实现提示】 用结构体数组存储多行正规式,用LIST 控件显示算法,用CDC 类依据进行算法进行作图。
并实现算法与生成过程的关联。
【注释】
本次课程设计共6道题目,各同学的选题可自由选择,也可自己结合感兴趣知识点自行命题,鼓励创新性设计。
r 5
r 5
r 5
r 5
11
r 1 r 1 S 7 r 1 9 r 3 r 3 r 3 r 3 10
S 11 S 6 8 10 S 4
S 5
7 3 3
3 F S
4 S 4
S 4 ( r 6 r 4
r 2 ) 9 r 1
S 5 6 r 6 r 6 r 6
5 2 8
S 5
4
r 4
r 4
r 4
3
r 2 S 7 r 2 2 a c c S 6 1
2 1
S 5 0
T E # * +
i
G o T o
A C T I O N 状态。