编译原理实验教程2015

合集下载

编译原理 实验

编译原理 实验

编译原理实验编译原理实验。

编译原理是计算机科学中的一个重要领域,它研究的是编译器的设计和实现原理。

编译器是将高级语言代码转换成机器语言代码的程序,它在软件开发过程中起着至关重要的作用。

而编译原理实验则是帮助学生深入理解编译原理的重要手段之一,通过实际操作来加深对编译原理知识的理解和掌握。

在编译原理实验中,我们需要掌握以下几个关键点:1. 词法分析,词法分析是编译过程中的第一步,它负责将源代码分割成一个个的单词(Token)。

在词法分析实验中,我们需要实现一个词法分析器,能够正确地识别出源代码中的各种单词,并进行分类和标记。

2. 语法分析,语法分析是编译过程中的第二步,它负责将词法分析得到的单词序列转换成抽象语法树。

在语法分析实验中,我们需要实现一个语法分析器,能够根据给定的文法规则,将单词序列转换成抽象语法树,并进行语法检查。

3. 语义分析,语义分析是编译过程中的第三步,它负责对抽象语法树进行语义检查和翻译。

在语义分析实验中,我们需要实现一个语义分析器,能够对抽象语法树进行类型检查、作用域分析等,并生成中间代码。

4. 代码生成,代码生成是编译过程中的最后一步,它负责将中间代码转换成目标机器代码。

在代码生成实验中,我们需要实现一个代码生成器,能够将中间代码转换成目标机器代码,并进行优化。

通过以上实验,我们可以深入理解编译原理的各个环节,并掌握编译器的设计和实现原理。

同时,实验过程中还能培养我们的动手能力和解决问题的能力,为今后的软件开发打下坚实的基础。

总之,编译原理实验是非常重要的,它能够帮助我们深入理解编译原理知识,提高我们的动手能力和解决问题的能力。

希望大家能够认真对待编译原理实验,从中获得更多的收获和成长。

《编译原理(实验部分)》实验3_PL0语法分析

《编译原理(实验部分)》实验3_PL0语法分析

《编译原理(实验部分)》实验3_PL0语法分析《编译原理》(实验部分)实验3_PL0语法分析一、实验目的加深和巩固对于语法分析的了解和掌握;给出PL/0文法规范,要求编写PL/0语言的语法分析程序。

二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。

2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。

三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。

整个编译过程是由一些嵌套及并列的过程或函数完成。

语法分析是由过程BLOCK完成。

采用自顶向下的递归子程序法。

所产生的目标程序为假象栈式计算机的汇编语言。

对目标程序的执行是由PASCAL语言书写的解释程序进行的。

四、实验步骤实验代码int lp=0;int rp=0;#define getsymdo if(-1==getsym()) return -1#define expressiondo() if(-1==expression()) return -1#define termdo() if(-1==term()) return -1#define factordo() if(-1==factor()) return -1int expression();//语法分析int factor(){if(sym!=ident &&sym!=number&&sym!=lparen){err++;if(err==1) printf("语法错误: \n");printf("error----Factor Needs Ident or Number or Lparen\n");}if ((sym == ident) || (sym == number) || (sym == lparen)){if (sym == ident){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("变量后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == number){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("数字后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == lparen){WordAnalyse();lp++;if(getsym()==-1){lp--;err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");return -1;}expressiondo();if (sym == rparen){WordAnalyse();lp--;if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus) {err++;if(err==1) printf("语法错误: \n");printf("括号后没有跟上+-*\\ \n");}}else{err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");}}}return 0;}int term(){factordo();if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == times) || (sym == slash)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("* \\ 后缺项\n");return -1;}factordo();}return 0;}int expression(){if ((sym == plus) || (sym == minus)){//cout<<strlen(id)<<endl;< p="">if (sym==minus&&2==strlen(ID)+1)flg=1;else{flg=0;WordAnalyse();}getsymdo;termdo();}else{//WordAnalyse();termdo();}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == plus) || (sym == minus)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("+ - 后缺项\n");return -1;}termdo();}return 0;}int main(int argc, char* argv[]){init();err=0;ifstream fin("in.txt");ofstream fout("out.txt");ch=' ';lp=0;getsymdo;expression();if(err==0) cout<<"语法正确"<<endl;< p="">elsecout<<"语法错误,错误个数: "<<err<<=""></err< </endl;<></strlen(id)<<endl;<>。

《编译原理》实验3_PL0语法分析

《编译原理》实验3_PL0语法分析

《编译原理》实验3_PL0语法分析编译原理是计算机科学中的重要课程,它涉及了程序语言的设计、编译器的构建以及编程语言的解释和执行等方面。

在编译原理的实验部分中,PL0语法分析是一个重要的实验项目。

PL0语法分析是基于PL0语言的语法规则来构建语法分析器,实现对PL0代码的分析和解释。

在这个实验中,我们将完成PL0语法分析器的设计和实现,并对其进行测试。

首先,我们需要了解PL0语言的语法规则。

PL0语言是一种过程型语言,类似于Pascal语言。

它有一套严格的语法规则,包括声明语句、赋值语句、条件语句、循环语句等。

我们需要先从PL0语言文法中提取出规则,然后将其转化为一个语法分析器。

接下来,我们需要设计和实现语法分析器。

语法分析器的主要任务是根据PL0语言的文法规则来分析和解释PL0代码。

我们可以选择使用自顶向下的语法分析方法,如递归下降分析法。

递归下降分析法是一种简单直观的语法分析方法,它通过递归调用子程序来分析和解释代码。

在设计语法分析器时,我们需要根据PL0语言的文法规则来设计相应的文法产生式和语法分析程序。

文法产生式描述了PL0语言的句子结构,它由非终结符和终结符组成,并用箭头“->”来表示产生关系。

语法分析程序则是根据产生式来解释和分析代码。

最后,我们需要编写测试代码来验证语法分析器的正确性。

测试代码应该包含PL0语言的各种语法结构和语法错误,从而验证语法分析器在不同情况下的正确性和鲁棒性。

通过完成这个实验项目,我们能够深入了解编译原理中的语法分析技术,并提升我们的编程能力和问题解决能力。

同时,我们也能够加深对PL0语言的理解,为以后的编程工作打下坚实的基础。

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理》(实验部分)实验2_PL0 词法分析一、实验目的加深和巩固对于词法分析的了解和掌握;初步认识PL/0 语言的基础和简单的程序编写;通过本实验能够初步的了解和掌握程序词法分析的整个过程;提高自己上机和编程过程中处理具体问题的能力。

二、实验设备1、P C兼容机一台;操作系统为WindowsWindowsX P2、Visual C++ 6.0 或以上版本,Windows 2000 或以上版本,汇编工具 (在Software 子目录下)。

三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。

整个编译过程是由一些嵌套及并列的过程或函数完成。

词法分析程序是独立的过程GETSY完成,供语法分析读单词时使用。

四、实验步骤阅读所给出的词法分析程序( pl0_lexical.c ),搞懂程序中每一个变量的含义,以及每一个过程的作用,并在该过程中进行中文注释;阅读完程序后,画出各过程的流程图;给出的程序包含两处输入错误,利用所给的pl/0 源程序(test.pl0) 对程序进行调试,使其能正确对所给文件进行分析并能够解释运行;在阅读懂所给出的词法分析程序后,将你对词法分析的理解写在实验报告上。

实验代码#include<stdio.h>main(){ printf ("my name is 08061118 yuchaofeng ");}主程序:#include <stdio.h>#include <ctype.h>#include <alloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char *key[8]={"DO","BEGIN","ELSE","END","IF","THEN","VAR","WHILE"}; char *border[6]={",",";",":=",".","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[20];char *label[20];int constnum=0,labelnum=0;int search(char searchchar[],int wordtype){int i=0;switch (wordtype) {case 1:for (i=0;i<=7;i++){if (strcmp(key[i],searchchar)==0)return(i+1);};case 2:{for (i=0;i<=5;i++){if (strcmp(border[i],searchchar)==0)return(i+1);};return(0);}case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){};};return(0);};case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){return(i+1);};};return(0);};case 5:{for (i=0;i<=constnum;i++){ if (strcmp(consts[i],searchchar)==0){return(i+1);};}consts[i-1]=(char *)malloc(sizeof(searchchar));strcpy(consts[i-1],searchchar);constnum++;return(i);};case 6:{for (i=0;i<=labelnum;i++){ if (strcmp(label[i],searchchar)==0){ return(i+1);};}label[i-1]=(char *)malloc(sizeof(searchchar)); strcpy(label[i-1],searchchar);return(i);};}}char alphaprocess(char buffer){int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer; buffer=fgetc(fp);}; alphatp[i+1]='\0';if (atype=search(alphatp,1)) printf("%s (1,%d)\n",alphatp,atype-1); else { atype=search(alphatp,6);printf("%s (6,%d)\n",alphatp,atype-1); };return(buffer);char digitprocess(char buffer){int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);printf("%s (5,%d)\n",digittp,dtype-1); return(buffer);}char otherprocess(char buffer){int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){printf("%s (3,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;};if (otype=search(othertp,4)){buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)){printf("%s (4,%d)\n",othertp,otypetp-1); goto out;}elseothertp[1]='\0';printf("%s (4,%d)\n",othertp,otype-1);goto out;};if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= (2,2)\n");buffer=fgetc(fp);goto out;}else{if (otype=search(othertp,2)){ printf("%s (2,%d)\n",othertp,otype-1); buffer=fgetc(fp); goto out;}};if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer); buffer=fgetc(fp);out: return(buffer);} void main(){ int i;for (i=0;i<=20;i++){label[i]=NULL; consts[i]=NULL;};if ((fp=fopen("skh.c","r"))==NULL) printf("error");else{ cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer)) cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer); else cbuffer=otherprocess(cbuffer); };printf("over\n");};}。

编译原理实验指导书

编译原理实验指导书

陕西理工学院数学与计算机科学学院《编译原理》实验指导班级网络10级指导教师曹阳计算机工程教研室2012年8月25日编译原理实验指导书一、实验的目的《编译原理》是针对计算机专业的学生开设的一门专业基础课程,对引导学生进行科学思维和提高学生解决实际问题的能力有重要的作用。

开设“编译原理实验”的主要目的是让学生加深理解编译原理的基本理论、方法、词法分析、语法分析、中间代码的生成直到最后的代码生成,了解编译器原理,从而提高学生分析问、题解决问题的能力。

通过实验实现以下基本目标:1.深化已学的知识,完成从理论到实践的转化通过实验,进一步加深对编译原理基本思想、原理的了解。

2. 提高分析和解决实际问题的能力实验不仅是编译原理的一次模拟训练,同时通过实验,积累经验,提高分析和解决问题的能力。

3.培养“开拓创新”能力大力提倡和鼓励在程序中使用新方法,新技术。

激发学生实践的积极性与创造性,开拓思路,设计新算法,进行新创意,培养创造性能力。

二、参加实验的学生应具备的条件参加实验的学生应当具备计算机程序设计的一些基础的知识。

即学生应当熟练掌握和使用一种计算机操作系统(windows操作系统等)、一种程序设计语言(vb、vc、c、delphi等)。

三、实验要求实验的要求体现于整个工作的各个阶段中,可根据所选课题的特点而有所侧重,但应达到如下的基本要求:(1) 根据课题任务制定合理、可行的工作计划任务;(2) 制定适当的技术方案;(3) 学生在老师的指导下独立完成设计过程;(4) 撰写实验报告(包括实验内容中各个阶段所要求的文字材料);(5) 通过实验检查评定;四、实验项目与内容提要五、实验课程考核办法1、该实验课程考核成绩按百分制计算,满分为100分,60分为及格,60分以上者可获取该学分。

2、该实验课考核由三部分组成:实验课前预习(20%),实验操作(60%),实验报告(20%)。

3、各部分成绩由实验指导教师在每个实验项目完成后分别给出,在学期结束后或完成全部实验项目后综合给出该门实验课的成绩。

编译原理-LL(1)文法源代码(实验三)

编译原理-LL(1)文法源代码(实验三)

一、实验目的及要求1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.用LL(1)分析法分析高级语言表达式。

4、了解LL(1)分析器的工作过程。

文法:无二义性的算术表达式的文法(1)把词法分析作为语法分析的子程序实现(5分)(2)独立的语法分析程序(4分)(3)对表达式文法消除左递归、构造LL(1)分析表(4)LL(1)分析表可以直接输入(4分),也可以用程序实现(5分)(5)给一个表达式,给出分析过程(分析栈、输入串、所用规则)(4分)(6)生成一个棵语法树(5分)用二叉树的形式表示出来二、实验内容及原理1、实验原理(1)、LL(1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。

LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。

LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。

需要预测分析器对所给句型进行识别。

即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。

LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。

若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。

编译原理实验(递归向下语法分析法实验)

编译原理实验(递归向下语法分析法实验)

//定义一个数组大小常量
char string[N];
//定义一个用于存储算式字符串的数组
char *p;
//定义一个全局字符指针变量
函数说明:
1) 非终结符函数 E()
函数功能描述:根据以上文法要求 E->TG,所以从主函数开始调入第一个非终结符函数
执行,显示调用产生式,依次嵌套调用非终结符函数 T()和 G(),进行递归向下分析。
void E(){printf("E--->TG..............%c\n",ch);
T();
G();}
2) 非终结符函数 T()
函数功能描述:根据以上文法要求 T->FS,首先显示算式匹配所用的显示调用的产生式,
依次嵌套调用非终结符函数 F()和 S(),进行递归向下分析。
void T(){
(3)G->ε
(4)T->FS
(5)S->*FS| / FS
(6)S->ε
(7)F->(E)
(8)F->i
输入出的格式如下:
(1)E 盘建立一个文本文档" 222.txt"存储一个以#结束的符号串(包括+—*/()i#),在此
位置输入符号串例如:i+i*i#
(2)输出结果:i+i*i#为合法符号串
备注:输入一符号串如 i+i*#,要求输出为“非法的符号串”
此法分析,通过实验我对本章的语法分析也有了深刻的认识。同时通过本次编程,让我深刻
认识编程应该注重细节,编程之前首先要做好分析准备。
五、程序源代码
#include<stdio.h>
#include<stdlib.h>

编译原理及实践教程(黄贤英 王柯柯 编著) 习题答案

编译原理及实践教程(黄贤英 王柯柯 编著) 习题答案

第2章参考答案:1,2,3:解答:略!4. 解答:A:① B:③ C:① D:②5. 解答:用E表示<表达式>,T表示<项>,F表示<因子>,上述文法可以写为:E → T | E+TT → F | T*FF → (E) | i最左推导:E=>E+T=>E+T+T=>T+T+T=>F+T+T=>i+T+T=>i+F+T=>i+i+T=>i+i+F=>i+i+iE=>E+T=>T+T=>F+T=>i+T=>i+T*F=>i+F*F=>i+i*F=>i+i*i 最右推导:E=>E+T=>E+F=>E+i=>E+T+i=>E+F+i=>E+i+i=>T+i+i=>F+i+i=>i+i+iE=>E+T=>E+T*F=>E+T*i=>E+F*i=>E+i*i=>T+i*i=>F+i*i =>i+i*ii+i+i和i+i*i的语法树如下图所示。

i+i+i、i+i*i的语法树6. 解答:(1) 终结符号为:{or,and,not,(,),true,false}非终结符号为:{bexpr,bterm,bfactor}开始符号为:bexpr(2) 句子not(true or false)的语法树为:7. 解答:(1) 把a n b n c i分成a n b n和c i两部分,分别由两个非终结符号生成,因此,生成此文法的产生式为:S → ABA → aAb|abB → cB|ε(2) 令S为开始符号,产生的w中a的个数恰好比b多一个,令E为一个非终结符号,产生含相同个数的a和b的所有串,则产生式如下:S → aE|Ea|bSS|SbS|SSbE → aEbE|bEaE|ε(3) 设文法开始符号为S,产生的w中满足|a|≤|b|≤2|a|。

编译原理实验指导书(2015)资料

编译原理实验指导书(2015)资料

LIAOCHENG UNIVERSITY编译原理实验指导书聊城大学计算机学院2011年3月目录《编译原理》课程实验教学大纲 (1)实验一词法分析器的设计 (3)基本信息 (3)实验目的 (3)实验内容 (3)实验扩充 (5)555101010101010111919《编译原理》课程实验教学大纲课程名称:编译原理英文名称:Compile principles设置形式:非独立设课课程模块:专业方向课实验课性质:专业实验课程编号:509615课程负责人:姜华大纲主撰人:姜华大纲审核人:左风朝一、学时、学分课程总学时:72实验学时:8课程学分:4二、适用专业及年级六、考核方式及成绩评定根据学生实验出勤情况、实验态度、实验报告成绩等方面评定实验成绩。

实验报告平均成绩(含实验理论)占实验成绩的50%,实验技能平均成绩(含实验态度)占实验成绩的50%。

实验成绩占该课程考试总成绩的10%—20%。

在机器上将程序及运行结果上传至服务器,由实习教师给出优、良、中、及格、不及格。

七、实验教科书、参考书1.实验教科书自编实验指导书。

2.实验参考书实验一词法分析器的设计基本信息实验课程:编译原理设课形式:非独立课程学分:4 实验项目:词法分析器的设计项目类型:设计项目学时:4实验目的1. 掌握词法分析的原理;2. 熟悉符号表的建立与单词的分类方法;3. 掌握词法分析器的设计与调试;实验内容1. 分析如表1所定义的PASCAL语言子集的语法,找出所有单词的组成及类别;2. 完成单词的分类及其编码;3. 完成保留字表、变量名表和常数表的结构设计;4. 建立识别单词符号集合的DFA;5. 由DFA设计词法分析程序;6. 调试并运行词法分析程序;7. 实验结果分析。

分析结果含义并写出自己的心得体会。

表1.PASCAL语言子集的语法定义提示:(1) 单词的分类。

可将所有标识符归为一类;将常数归为另一类;保留字和分隔符则可采取一词一类。

编译原理实验手册1.5版

编译原理实验手册1.5版

兰州大学计算机科学与技术专业编译原理实验手册(V1.5)第一节概述 (2)一、实验目的 (2)二、实验内容 (2)三、PASCAL语言子集的文法 (3)四、实验要求: (6)第二节词法分析 (7)一、目的与要求 (7)二、设计步骤 (7)三、扩充 (8)第三节语法分析 (9)一、目的与要求 (9)二、设计步骤 (9)三、程序流程示例: (10)四、扩充 (12)第四节语义分析和翻译 (13)一、目的与要求 (13)二、设计步骤 (13)三、算法示例 (14)四、建议生成的四元式统一采用如下的形式: (15)五、扩充 (16)附录一算符优先分析算法示例 (17)附录二递归下降分析算法示例 (18)附录三Pascal程序示例 (20)第一节概述一、实验目的编译原理是一门实践性很强的课程,但由于课时所限,只能在课堂上讲授一些通用的原理和方法。

而为了真正学好这门课程,必须自己动手构造出一个编译器,才能对书里讲到的原理、方法和技术有较全面的体会,才能对学生以后的程序设计和解决实际问题的能力有所帮助。

实际的编译程序是十分复杂的,有时由多达十几万条指令组成。

为此,编译原理的实践教学,采用简化编译过程的办法,选择最关键的三个环节──词法分析、语法分析、语义分析和中间代码产生,每个环节作为一个实践课题,逐步深入,扩展功能,直至得到一个简单实用的编译器。

本实验不涉及到优化。

二、实验内容任何一个实用的高级语言,其语法都比较复杂,如选其作为源语言,很难实践全过程。

故本试验将定义一个简化的语言──PASCAL语言的一个子集作为源语言,分三个课题、一步步地构造出它的编译程序。

所有试验项目前后贯穿这一条主线进行。

本实验共进行6周,每周3学时,共18学时。

本实验主要包括以下三个课题: 词法分析:以源程序为输入,输出单词符号流;语法分析:以源语言的文法为依据,调用词法分析器,使用递归下降分析法或算符优先分析法或SLR(1)分析法,构造能识别源语言各种语法结构的语法分析器;语义分析和中间代码产生:使用语法制导翻译技术,对源语言程序进行简单的翻译,输出四元式序列。

《编译原理》课程实验指导书(2015)

《编译原理》课程实验指导书(2015)

编译原理实验指导书上海大学计算机学院《编译原理》课程组2014年2月目录一、课程简介 (2)二、实验目的 (2)三、实验环境 (2)四、实验任务 (2)五、PL0语言简介 (2)1.PL/0语言文法的EBNF (3)2.PL/0语言的词汇表 (4)六、实验项目 (5)实验一识别标识符 (5)实验二词法分析 (7)实验三语法分析 (10)实验四语义分析 (12)实验五中间代码生成 (13)实验六代码优化 (14)七、参考文献 (16)八、附录——PL0语言编译源程序清单(部分) (17)编译原理实验指导书一、课程简介1.课程名称:编译原理(Principle of Compiler)2.课程编码:083050133.课程总学时:60学时[理论:30学时;研讨:10学时;实验:20学时]4.课程总学分:5学分二、实验目的编译原理是计算机类专业特别是计算机软件专业的一门重要专业课。

设置该课程的目的在于系统地向学生讲述编译系统的结构、工作流程及编译程序各组成部分的设计原理和实现技术,使学生通过学习既掌握编译理论和方法方面的基本知识,也具有设计、实现、分析和维护编译程序等方面的初步能力。

编译原理是一门理论性和实践性都比较强的课程。

进行上机实验的目的是使学生通过完成上机实验题目加深对课堂教学内容的理解。

同时培养学生实际动手能力。

三、实验环境微机CPU P4以上,256M以上内存,安装好C语言,或C++,或Visual C++开发环境。

四、实验任务用C/C++/Visual C++语言编写PL/0语言的词法分析程序、语法分析程序、语义分析程序、中间代码生成程序。

五、PL0语言简介PL/0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL/0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。

1.PL/0语言文法的EBNF<程序>::=<分程序>.<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句><常量说明> ::=CONST<常量定义>{,<常量定义>};<常量定义> ::=<标识符>=<无符号整数><无符号整数> ::= <数字>{<数字>}<变量说明> ::=V AR <标识符>{, <标识符>};<标识符> ::=<字母>{<字母>|<数字>}<过程说明> ::=<过程首部><分程序>{; <过程说明> };<过程首部> ::=PROCEDURE <标识符>;<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句><写语句>|<空> <赋值语句> ::=<标识符>:=<表达式><复合语句> ::=BEGIN <语句> {;<语句> }END<条件表达式> ::= <表达式> <关系运算符> <表达式> |ODD<表达式> <表达式> ::= [+|-]<项>{<加法运算符> <项>}<项> ::= <因子>{<乘法运算符> <因子>}<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’<加法运算符> ::= +|-<乘法运算符> ::= *|/<关系运算符> ::= =|#|<|<=|>|>=<条件语句> ::= IF <条件表达式> THEN <语句><过程调用语句> ::= CALL 标识符<当循环语句> ::= WHILE <条件表达式> DO <语句> <读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’<写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’<字母> ::= a|b|…|X|Y|Z<数字> ::= 0|1|…|8|92.PL/0语言的词汇表六、实验项目实验一识别标识符1.实验目的●根据PL/0语言的文法规范,编写PL/0语言的标识符识别程序。

编译原理教程实验报告

编译原理教程实验报告

一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。

二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。

2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。

3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。

4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。

5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。

6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。

四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。

2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。

3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。

4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。

5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。

6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。

五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。

编译原理实验 LL(1)分析

编译原理实验 LL(1)分析

实验三语法分析---LL(1)分析器目录一. 实验的目的与思路 (2)(1)目的 (2)(2)思路 (2)二. 基本的功能 (3)三.总体设计 (4)四.详细设计 (5)五.源程序清单 (6)六.源代码 (6)....................................................................................................................................................一. 实验的目的与思路(1)目的1. 用程序的方法实现语法分析的LL(1)方法。

(2)思路本程序是采用的LL(1)方法进行的语法分析,而LL(1)的分析方法是属于自上而下的方法。

自上而下分析的基本思想是:对任意输入串,试图用一切可能的方法,从文法开始符号(根结点)出发,自上而下为输入串建立一棵语法树。

从推导的角度看,它是从文法的开始符号出发,反复使用各种产生式,寻找与输入串匹配的推导。

在输入之前必须要进行该文法是不是LL(1)文法的判断,然后再构造相应的LL(1)分析表来用预测分析方法进行语法分析,依据下面的文法及分析表来设计程序实现预测分析的分析过程。

1.文法G[E]:E --> E+T|TT --> T*F|FF --> (E) | i2.通过观察可知道该文法是一个左递归文法,要进行语法分析就必须消除左递归才能继续判断它是不是LL(1)文法,然后才能用预测分析方法进行语法分析。

3.消除左递归:E -->TMM --> +TM|uT --> FQQ --> *FQ|uF --> (E) | i4.在进行LL(1)文法的判断:(1.)各非终结符的FIRST集如下:FIRST(E)= FIRST(TM)= {(,i }FIRST(M)= { + }FIRST(T)= {(,i }FIRST(Q)= { * }FIRST(F)= { (,i }(2.)各非终结符的FOLLOW集如下:FOLLOW(E)= { ),# }FOLLOW(M)= { ),# }FOLLOW(T)= { + ,),# }FOLLOW(Q)= { + ,),# }FOLLOW(F)= { * ,+ ,),# }(3.)各产生式的SELECT集如下:SELECT(E→TM)={ ( ,i }SELECT(M→+TM)={+}SELECT(M→u)={ }, #}SELECT(T→FQ)={ ( ,i }SELECT(Q→*FQ)={ *}SELECT(Q→u)={ +,), # }SELECT(F→(E))={ ( )SELECT(F→i)={ i }因为:SELECT(M→+TM)∩SELECT(M→u)=ФSELECT(Q→*FQ)∩SELECT(Q→u)=ФSELECT(F→(E))∩SELECT(F→i)=Ф因此可以判断该文法是一个LL(1)文法可以构造预测分析表。

《编译原理》科学实验指导说明书

《编译原理》科学实验指导说明书

《编译原理》实验指导书实验一词法分析器的设计一、实验目的和要求加深对状态转换图的实现及词法分析器的理解。

熟悉词法分析器的主要算法及实现过程。

要求学生掌握词法分析器的设计过程,并实现词法分析。

二、实验基本内容给出一个简单语言的词法规则,画出状态转换图,并依据状态转换图编制出词法分析程序,能从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单Error”,然后跳过错误部分继续显示)词法规则如下:三、实验时间:上机三次。

第一次按照自己的思路设计一个程序。

第二、三次在理论课学习后修改程序,使得程序结构更加合理。

四、实验过程和指导:(一)准备:1.阅读课本有关章节(c/c++,数据结构),花一周时间明确语言的语法,写出基本算法以及采用的数据结构和要测试的程序例。

2.初步编制好程序。

3.准备好多组测试数据。

(二)上课上机:将源代码拷贝到机上调试,发现错误,再修改完善。

(三)程序要求:程序输入/输出示例:输入如下一段:main(){/*一个简单的c++程序*/int a,b; //定义变量a = 10;b = a + 20;}要求输出如右图。

要求:(1) 剔除注解符(2) 常数为无符号整数(可增加实型数,字符型数等)(四)练习该实验的目的和思路:程序开始变得复杂起来,可能是大家以前编过的程序中最复杂的,但相对于以后的程序来说还是简单的。

因此要认真把握这个过渡期的练习。

程序规模大概为200行及以上。

通过练习,掌握对字符进行灵活处理的方法。

(五)为了能设计好程序,注意以下事情:1.模块设计:将程序分成合理的多个模块(函数/类),每个模块(类)做具体的同一事情。

2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。

3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

4.程序设计语言不限,建议使用面向对象技术及可视化编程语言,如C++,VC,JA V A,VJ++等。

《编译原理实验》实验指导书

《编译原理实验》实验指导书

广州大学实验课程建设项目《编译原理实验》实验指导书广州大学信息与机电工程学院计算机系2006年10月目录实验1 Pascal 语言的编译器的使用 3 实验2 词法分析(一) 13 (调试一个词法分析程序)实验3 词法分析(二) 16 (设计、编制并调试一个词法分析程序)实验4 语法分析(一) 19 (调试一个语法分析程序,了解编译程序中LR分析表的作用)实验5 语法分析(二) 22(设计、编制并调试一个语法分析程序)实验6 语义分析 24实验7 编译原理综合实验 26 实验报告示例:词法分析程序 47考试考核方式 53实验一:Pascal 语言的编译器的使用实验目的:调试一个Pascal 语言的编译器,加深对语言编译器的理解实验内容:此程序为Pascal 语言的编译器,支持Proc ,Repeat,If,While,For,Fun函数结构代码的编译,能生成变量表、常量表和汇编程序。

界面如下:图1 Pascal 语言的编译器的使用界面下面给出软件所能编译的代码和编译出的结果。

―――――――――――――――――――――――――――――――――――Proc函数结构代码:vara, b, i: integer;procedure p1(arg1: integer; arg2: integer);begina := arg1 * arg2;end;beginb := 123;p1(3, b);――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]b = unsigned[静], OffPos = 0[3]i = unsigned[静], OffPos = 0[4]arg1 = unsigned[参], OffPos = 0[5]arg2 = unsigned[参], OffPos = 1常量[0]Number = 123[静], OffPos = 0[1]Number = 3[静], OffPos = 0方法ID = 1, Name = p1, MethodType = 过程, ParamList = (4, 5), DynaV arList = (), Addr = 2 ++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 369[静], OffPos = 0[2]b = 123[静], OffPos = 0[3]i = unsigned[静], OffPos = 0[4]arg1 = unsigned[参], OffPos = 0[5]arg2 = unsigned[参], OffPos = 1汇编语句:0:Goto 0, 71:Return 0, 02:Mov 0, 43:Mov 0, 54:Mul 0, 05:Sto 1, 16:Return 0, 07:LoadConst 0, 08:Sto 0, 29:LoadConst 0, 110:Mov 0, 211:Call 0, 1 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――For结构代码:vara, b, i: integer;a := 0;for i := 0 to 100 dobegina := a + i;end;end;――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]b = unsigned[静], OffPos = 0[3]i = unsigned[静], OffPos = 0常量[0]Number = 0[静], OffPos = 0[1]Number = 0[静], OffPos = 0[2]Number = 100[静], OffPos = 0方法ID = 0, Name = ShowMessage, MethodType = 过程, ParamList = (0), DynaV arList = (), Addr = 1++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 5050[静], OffPos = 0[2]b = unsigned[静], OffPos = 0[3]i = 101[静], OffPos = 0汇编语句:0:Goto 0, 21:Return 0, 02:LoadConst 0, 03:Sto 0, 14:LoadConst 0, 15:Sto 0, 36:LoadConst 0, 27:Mov 0, 38:>=? 0, 09:IfFalseGoto 0, 1810:Mov 0, 111:Mov 0, 312:Add 0, 013:Sto 0, 114:Mov 0, 315:IncV ar 0, 116:Sto 0, 317:Goto 0, 6 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――While函数结构代码:vara, i: integer;begini := 0;a := 0;while i <= 100 dobegina := a +i;i := i +1;end;end;――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]i = unsigned[静], OffPos = 0常量[0]Number = 0[静], OffPos = 0[1]Number = 0[静], OffPos = 0[2]Number = 100[静], OffPos = 0[3]Number = 1[静], OffPos = 0方法ID = 0, Name = ShowMessage, MethodType = 过程, ParamList = (0), DynaV arList = (), Addr = 1++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 5050[静], OffPos = 0[2]i = 101[静], OffPos = 0汇编语句:0:Goto 0, 21:Return 0, 02:LoadConst 0, 03:Sto 0, 24:LoadConst 0, 15:Sto 0, 16:Mov 0, 27:LoadConst 0, 28:<=? 0, 09:IfFalseGoto 0, 1910:Mov 0, 111:Mov 0, 212:Add 0, 013:Sto 0, 114:Mov 0, 215:LoadConst 0, 316:Add 0, 017:Sto 0, 218:Goto 0, 6 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――Repeat函数结构代码:vara, i: integer;begina := 0;i := 0;repeata := a + i;i := i + 1;until i > 100;end; ――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]i = unsigned[静], OffPos = 0常量[0]Number = 0[静], OffPos = 0[1]Number = 0[静], OffPos = 0[2]Number = 1[静], OffPos = 0[3]Number = 100[静], OffPos = 0方法ID = 0, Name = ShowMessage, MethodType = 过程, ParamList = (0), DynaV arList = (), Addr = 1++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 5050[静], OffPos = 0[2]i = 101[静], OffPos = 0汇编语句:0:Goto 0, 21:Return 0, 02:LoadConst 0, 03:Sto 0, 14:LoadConst 0, 15:Sto 0, 26:Mov 0, 17:Mov 0, 28:Add 0, 09:Sto 0, 110:Mov 0, 211:LoadConst 0, 212:Add 0, 013:Sto 0, 214:Mov 0, 215:LoadConst 0, 316:>? 0, 017:IfFalseGoto 0, 6 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――Fun函数结构代码:vara, i: integer;function fun1(arg1, arg2: integer): integer;beginResult := arg1 + arg2;end;begina := 0;for i := 1 to 100 dobegina := fun1(a, i);end;end;――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]i = unsigned[静], OffPos = 0[3]arg1 = unsigned[参], OffPos = 0[4]arg2 = unsigned[参], OffPos = 1[5]Result = unsigned[动], OffPos = 2常量[0]Number = 0[静], OffPos = 0[1]Number = 1[静], OffPos = 0[2]Number = 100[静], OffPos = 0方法ID = 1, Name = fun1, MethodType = 函数, ParamList = (3, 4), DynaV arList = (5), Addr = 2 ++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 5050[静], OffPos = 0[2]i = 101[静], OffPos = 0[3]arg1 = unsigned[参], OffPos = 0[4]arg2 = unsigned[参], OffPos = 1[5]Result = unsigned[动], OffPos = 2汇编语句:0:Goto 0, 71:Return 0, 02:Mov 0, 33:Mov 0, 44:Add 0, 05:Sto 0, 56:Return 0, 07:LoadConst 0, 08:Sto 0, 19:LoadConst 0, 110:Sto 0, 211:LoadConst 0, 212:Mov 0, 213:>=? 0, 014:IfFalseGoto 0, 2315:Mov 0, 116:Mov 0, 217:Call 0, 118:Sto 0, 119:Mov 0, 220:IncV ar 0, 121:Sto 0, 222:Goto 0, 11 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――If 结构代码:vara, i: integer;begina := 2;if a = 1 thenbegini := 10;endelse begini := 100;end;end;――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]i = unsigned[静], OffPos = 0常量[0]Number = 2[静], OffPos = 0[1]Number = 1[静], OffPos = 0[2]Number = 10[静], OffPos = 0[3]Number = 100[静], OffPos = 0方法ID = 0, Name = ShowMessage, MethodType = 过程, ParamList = (0), DynaV arList = (), Addr = 1 ++++++++++++++++++++++++++++++++++++运行状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = 2[静], OffPos = 0[2]i = 100[静], OffPos = 0汇编语句:0:Goto 0, 21:Return 0, 02:LoadConst 0, 03:Sto 0, 14:Mov 0, 15:LoadConst 0, 16:=? 0, 07:IfFalseGoto 0, 118:LoadConst 0, 29:Sto 0, 210:Goto 0, 1311:LoadConst 0, 312:Sto 0, 2 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――递归结构代码:vara, b: integer;function f1(arg: integer): integer;beginif arg <= 1 thenbeginResult := 1;endelse beginResult := arg * f1(arg - 1);end;end;begina := 10;b := f1(a);ShowMessage(b);end; ――――――――――――――――――――――――――――――――――-编译状态下:变量[0]str = unsigned[参], OffPos = 0[1]a = unsigned[静], OffPos = 0[2]b = unsigned[静], OffPos = 0[3]arg = unsigned[参], OffPos = 0[4]Result = unsigned[动], OffPos = 1常量[0]Number = 1[静], OffPos = 0[1]Number = 1[静], OffPos = 0[2]Number = 1[静], OffPos = 0[3]Number = 10[静], OffPos = 0方法ID = 1, Name = f1, MethodType = 函数, ParamList = (3), DynaV arList = (4), Addr = 2 ++++++++++++++++++++++++++++++++++++运行状态下:变量:无汇编语句:Goto 0, 171:Return 0, 02:Mov 0, 33:LoadConst 0, 04:<=? 0, 05:IfFalseGoto 0, 96:LoadConst 0, 17:Sto 0, 48:Goto 0, 169:Mov 0, 310:Mov 0, 311:LoadConst 0, 212:Sub 0, 013:Call 0, 114:Mul 0, 015:Sto 0, 416:Return 0, 017:LoadConst 0, 318:Sto 0, 119:Mov 0, 120:Call 0, 121:Sto 0, 222:Mov 0, 223:Call 0, 0 ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――实验二:词法分析(一)实验目的:调试一个词法分析程序,加深对词法分析原理的理解实验内容:(1)设一小型编译程序关于高级语言有如下的规定:高级语言程序具有四种基本结构:顺序结构﹑选择结构﹑循环结构和过程。

2015编译原理复习详解

2015编译原理复习详解
3型文法。其中2型文法又叫做()文法,3型文法又叫做( ) 文法。 高级程序设计语言源程序有两种执行方式,即____和____。 什么是编译器? 什么是遍。 什么是扫描器?扫描器的功能是什么?
第一章
以下对编译器(compiler)描述错误的是( )。
A. 编译器是将一种语言翻译成另一种语言的计算机 部件,包括软件部分和硬件部分;
语言、对某个串的推导。 二义性文法
概念及消除二义性的方法(1、2) 常见产生原因及消除的方法
第三章
在一般的编译器中,语法分析基于( )文 法进行,即识别的单词串是该类文法的句子。
分析器(parser)的主要功能是进行( ) 。
第三章
以下对于文法二义性的描述正确的是( )。
A LL(1)文法是无二义性文法; B 二义性文法会对所有的符号串产生多个语法 树; C 通过相应算法可以判断文法的二义性; D 在语法分析中,二义性文法是不被允许的, 必须通过修改文法来消除。
第二章
以下对扫描器(scanner)描述正确的是( )。
A 扫描器是编译器的一个功能模块,其功能是进行语 义分析;
B 扫描器的输入是语法树,输出是注释树; C 扫描器需要分析哪些字符组成了“词”; D 扫描器无需提示任何错误,而是由其它编译器模块 来完成。
第二章
下面不属于正则表达式(regular expression)的 基本操作的是( )。
复习
2015.7.1
第一章要点
编译器的概念。其输入和输出。 机器语言->汇编语言->高级语言。 乔姆斯基分层结构。
0型-无限制文法 1型-上下文相关文法 2型-上下文无关文法 3型-正则文法
第一章要点
相关程序和概念

编译原理实验报告FIRST集和FOLLOW集

编译原理实验报告FIRST集和FOLLOW集

编译原理实验报告实验名称计算first集合和follow集合实验时间院系计算机科学和技术班级软件工程1班学号姓名输入:任意的上下文无关文法。

输出:所输入的上下文无关文法一切非终结符的first 集合和follow 集合。

2. 实验原理设文法G[S]=(V N ,V T ,P ,S ),则首字符集为: FIRST (α)={a | α⇒*a β,a ∈V T ,α,β∈V *}。

若α⇒*ε,ε∈FIRST (α)。

由定义可以看出,FIRST (α)是指符号串α能够推导出的所有符号串中处于串首的终结符号组成的集合。

所以FIRST 集也称为首符号集。

设α=x 1x 2…x n ,FIRST (α)可按下列方法求得:令FIRST (α)=Φ,i =1;(1) 若x i ∈V T ,则x i ∈FIRST (α);(2) 若x i ∈V N ;① 若ε∉FIRST (x i ),则FIRST (x i )∈FIRST (α);② 若ε∈FIRST (x i ),则FIRST (x i )-{ε}∈FIRST (α);(3) i =i+1,重复(1)、(2),直到x i ∈V T ,(i =2,3,…,n )或x i∈V N 且若ε∉FIRST (x i )或i>n 为止。

当一个文法中存在ε产生式时,例如,存在A →ε,只有知道哪些符号可以合法地出现在非终结符A 之后,才能知道是否选择A →ε产生式。

这些合法地出现在非终结符A 之后的符号组成的集合被称为FOLLOW 集合。

下面我们给出文法的FOLLOW 集的定义。

设文法G[S]=(V N ,V T ,P ,S ),则FOLLOW (A )={a | S ⇒… Aa …,a ∈V T }。

若S ⇒*…A ,#∈FOLLOW (A )。

由定义可以看出,FOLLOW (A )是指在文法G[S]的所有句型中,紧跟在非终结符A 后的终结符号的集合。

FOLLOW 集可按下列方法求得:(1) 对于文法G[S]的开始符号S ,有#∈FOLLOW (S );(2) 若文法G[S]中有形如B →xAy 的规则,其中x ,y ∈V *,则FIRST(y )-{ε}∈FOLLOW (A );(3) 若文法G[S]中有形如B →xA 的规则,或形如B →xAy 的规则且ε∈FIRST (y ),其中x ,y ∈V *,则FOLLOW (B )∈FOLLOW (A );计算first集合和follow集合4.实验心得通过上机实验我对文法符号的FIRST集和FOLLOW集有了更深刻的理解,已经熟练的掌握了求解的思想和方法,同时也锻炼了自己的动手解决问题的能力,对编程能力也有所提高。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
0 0 0 1 0 0 38 0 5 33 8 8 29
8 12 13
主程序
S
Q
R
R
21 call 2,1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
}
8
分程序
const ,
; var
, ;
ident ident
=
number
procedure ;
ident
;
分程序
语句
Int block(int lev,int tx,bool* fsys) {
int i; int dx; int tx0; int cx0;
/*名字分配到的相对地址*/ /*保留初始 tx*/ /*保留初始 cx*/
end end.
<变量说明部分> ::=VAR<标识符>{,<标识符>}; <标识符>::=<字母>{<字母>|<数字>} var b,c;
<过程说明部分> ::=<过程首部><分程序>{;<过程说明部分>};
<过程首部>::=PROCEDURE<标识符>;
procedure p; begin c:=b+a end;
break;
case variable:
/*变量名字*/
table[(*ptx)].level=lev;
table[(*ptx)].adr=(*pdx);
(*pdx)++;
break;
/*过程名字*/
case procedur:
table[(*ptx)].level=lev;
break;
}
}
4
动态存储分配策略
(
表达式
)
/* *因子处理 */ factor {
switch (sym){
case ident :
i=position(id,*ptx);
/*查找名字*/
if a>0 then call r end; procedure s; call q; begin a:=1; call s end.
0 jmp 0,34 1 jmp 0,32 2 jmp 0,3 3 int 0 5 4 lod 2 3 5 lit 0 1 6 opr 0 8 7 jpc 0 13 8 lod 2 3 9 lit 0 1 10 opr 0 3 11 sto 2 3 12 cal 1 3 13 lod 2 3 14 lit 0 0 15 opr 0 8 16 jpc 0 22 17 lod 2 3 18 lit 0 1 19 opr 0 3 20 sto 2 3 21 cal 2 1 22 opr 0 0 23 int 0 4 24 lod 1 3 25 lit 0 0 26 opr 0 12 27 jpc 0 29 28 cal 0 3 29 opr 0 0 31 int 0 3 32 cal 1 23 33 opr 0 0 34 int 0 5 35 lit 0 1 36 sto 0 3 37 cal 0 31 38 opr 0 0
经结束,dx 就是当前过程数据的 size*/
cx0=cx;
gendo(inte,0,dx);
/*生成分配内存代码*/
statementdo(nxtlev,&tx,lev);
gendo(opr,0,0); /*每个过程出口都要使用的释放数据段命令*/
return 0;
}
10
因子
ident
number
编译原理实验
实验一 PL/0 语言及其编译器的分析
实验内容
1. PL0 的语法描述图与 EBNF; 2. PL0 编译程序的结构; 3. PCODE 指令系统; 4. PL0 的运行环境;
实验要求
1. 理解 BNF、语法描述图,掌握 PL0 语言的语法描述图; 2. 阅读 PL0 编译器源代码,掌握其总体结构; 3. 掌握 PCODE 指令代码的功能; 4. 掌握指令代码的执行和存储分配; 5. 编写一个 PL0 源程序并编译,掌握 PCODE 指令的执行及存储分配情况;
码生成有关),特别是 cx,在哪儿被改变; 7. 全局变量 ch 有什么作用(ch 在 getch()和 getsym()中使用); 8. 在 getsym()中,重要全局变量 sym, id 都有什么作用; 9. getsym()与 getch()各有什么作用,getsym()与 getch()之间如何交互以完成读取一个符号
<语句>::=
<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>
|<复合语句>|<空>
<复合语句>::=BEGIN<语句>{;<语句>}END <赋值语句>::=<标识符>∶=<表达式>
<表达式>::=[+|-]<项>{<加法运算符><项>} <项>::=<因子>{<乘法运算符><因子>}
5
0层
1层
var a,x; procedure q; 2 层
var i; procedure r;
var c,d; begin
if a=1 then begin a:=a-1; call r end;
if a=0 then begin a:=a-1; call q end
end; begin
if a>0 then call r end; procedure s; call q; begin a:=1; call s end.
/*数值,仅 const 使用*/
int level;
/*所处层,仅 const 不使用*/
int adr;
/*地址,仅 const 不使用*/
int size;
/*需要分配的数据区空间,仅 procedure 使用*/
};
struct tablestruct table[txmax];
/*名字表*/
编译至此,符号表的内 容是?
编译至此,符号表的内 容是?
编译至此,符号表的内 容是?
符号表管理涉及到的数据结构
struct tablestruct
{
char name[al];
/*名字*/
enum object kind; /*类型:const,var,array or procedure*/
int val;
重点理解如何访问非局部变量。
var a,x; procedure q;
var i; procedure r;
var c,d; begin
if a=1 then begin a:=a-1; call r end;
if a=0 then begin a:=a-1; call q end
end; begin
/*收到过程声明符号,开始处理过程声明*/ …… block(lev+1,tx,nxtlev)); …… }
code[table[tx0].adr].a=cx; /*开始生成当前过程代码*/
table[tx0].adr=cx;
/*当前过程代码地址*/
table[tx0].size=dx;
/*声明部分中每增加一条声明都会给 dx 增加 1,声明部分已
主程序
S
Q
29 opr 0,0
b
t
012345678
0 0 0 -1 0 0 38
主程序
S
33 opr 0,0
b
t
012345 0 0 0 -1 0
主程序
38 opr 0,0 最终 b=0; t=0; p=0; 退出主程序。
7
递归下降分析法
程序
分程序
.
main(){ getsym(); block(); if(sym!=period){ error(9); } return;
(token)的任务; 10. getsym()如何被 block()等语法分析程序调用,何时调用;
1
EBNF
程序
分程序
.
<程序>::=<分程序>.
<分程序> ::=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>
<常量说明部分> ::=CONST<常量定义> {, <常量定义>};
8 12 13
主程序
S
Q
R
R
22 opr 0,0
b
t
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
0 0 0 -1 0 0 38 0 5 33 8 8 29
主程序
S
Q
R
22 opr 0,0
b
t
0 1 2 3 4 5 6 7 8 9 10 11 12
0 0 0 -1 0 0 38 0 5 33
填符号表的过程 /* *在名字表中加入一项
3
*
*k:名字种类 const,var or procedure
*ptx:名字表尾指针的指针,为了可以改变名字表尾指针的数值
相关文档
最新文档