实验5 LL(1)语法分析程序的设计与实现(C语言)
编译原理实验报告5-语法分析程序的设计

实验5 语法分析程序的设计(2)一、实验目的通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中算法优先分析方法。
二、实验内容设计一个文法的算法优先分析程序,判断特定表达式的正确性。
三、实验要求1、给出文法如下:G[E]E->T|E+T;T->F|T*F;F->i|(E);2、计算机中表示上述优先关系,优先关系的机内存放方式有两种1)直接存放,2)为优先关系建立优先函数,这里由学生自己选择一种方式;1、给出算符优先分析算法如下:k:=1; S[k]:=‘#’;REPEAT把下一个输入符号读进a中;IF S[k]∈V T THEN j:=k ELSE j:=k-1;WHILE S[j] a DOBEGINREPEATQ:=S[j];IF S[j-1]∈V T THEN j:=j-1 ELSE j:=j-2UNTIL S[j] Q把S[j+1]…S[k]归约为某个N;k:=j+1;S[k]:=N;END OF WHILE;IF S[j] a OR S[j] a THENBEGINk:=k+1;S[k]:=aENDELSE ERRORUNTIL a=‘#’1、根据给出算法,利用适当的数据结构实现算符优先分析程序;2、利用算符优先分析程序完成下列功能:1)手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束;2)读入文本文件中的表达式;3)调用实验2中的词法分析程序搜索单词;4)把单词送入算法优先分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息;5)完成上述功能,有余力的同学可以对正确的表达式计算出结果。
四、实验环境PC微机DOS操作系统或 Windows 操作系统Turbo C 程序集成环境或 Visual C++ 程序集成环境五、实验步骤1、分析文法中终结符号的优先关系;2、存放优先关系或构造优先函数;3、利用算符优先分析的算法编写分析程序;4、写测试程序,包括表达式的读入和结果的输出;5、程序运行效果,测试数据可以参考下列给出的数据。
语法分析程序的设计与实现

◆词法分析 用户必须提供一个词法分析器来读取输入流并把记号(带有值, 如果需要的话)传达到解析器。词法分析器使叫做 yylex 的整数值的 函数。这个函数返回一个整数的记号编号,它表示读取的记号的种类。 如果这个记号关联着一个值,应当把它赋予外部变量 yylval。 为使通信得以发生,解析器和词法分析器必须在记号编号上达成 一致。编号可以由 Yacc 或用户来选择。在这两种情况下,使用 C 语 言的“# define”机制允许词法分析器使用符号来返回这些编号。例如, 假定在 Yacc 规定文件的声明段中已经定义记号名字 DIGIT。 它的意图是返回一个 DIGIT 记号编号,和等于这个数字的数值 的一个值。倘若词法分析器代码位于规定文件的程序段,标识符 DIGIT 将被定义为与记号 DIGIT 关联的记号编号。 这种机制导致清晰的、易于修改的词法分析器;唯一的缺点是在 文法中需要避免使用任何在 C 语言或解析器中保留的或有意义的记 号名字;例如,使用记号名字 if 或 while 就一定会导致编译词法分 析器时出现严峻的困难。记号名字 error 保留给错误处理,不应该随 便使用。 同上所述,记号编号可以由 Yacc 或用户来选择。在缺省的条件 下,编号由 Yacc 选择。文字字符的缺省记号编号是它在本地字符集 中的字符数值。其他名字赋予从 257 开始的记号编号。 要把一个记号编号赋予一个记号(包括文字),可以在声明段中记 号或文字的第一次出现时直接跟随着一个非负整数。这个整数被接受
第四:YACC 内部名称: ................................................................................................ 7 第五:运行结果(源代码见附录).............................................................................. 8 第六:实验总结 ............................................................................................................... 8 第七:附录 ..................................................................................................................... 10
实验5LL(1)语法分析程序的设计与实现(C语言)

实验五LL(1)文法识别程序设计之宇文皓月创作一、实验目的通过LL(1)文法识别程序的设计理解自顶向下的语法分析思想。
二、实验重难点FIRST集合、FOLLOW集合、SELECT集合元素的求解,预测分析表的构造。
三、实验内容与要求实验内容:1.阅读并理解实验案例中LL(1)文法判此外程序实现;2.参考实验案例,完成简单的LL(1)文法判别程序设计。
四、实验学时4课时五、实验设备与环境C语言编译环境六、实验案例1.实验要求参考教材93页预测分析方法,94页图5.11 预测分析程序框图,编写表达式文法的识别程序。
要求对输入的LL(1)文法字符串,程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
表达式文法为:E→E+T|TT→T*F|FF→i|(E)2.参考代码为了更好的理解代码,建议将图5.11做如下标注:/* 程序名称: LL(1)语法分析程序 *//* E->E+T|T *//* T->T*F|F *//* F->(E)|i *//*目的: 对输入LL(1)文法字符串,本程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
/********************************************//* 程序相关说明 *//* A=E' B=T' *//* 预测分析表中列号、行号 *//* 0=E 1=E' 2=T 3=T' 4=F *//* 0=i 1=+ 2=* 3=( 4=) 5=# *//************************************/#include"iostream"#include "stdio.h"#include "malloc.h"#include "conio.h"/*定义链表这种数据类型拜见:http://wenku.百度.com/link?url=_owQzf8PRZOt9H-5oXIReh4X0ClHo6zXtRdWrdSO5YBLpKlNvkCk0qWqvFFxjgO0KzueVwEQcv9aZtVKEEH8XWSQCeVTjXvy9lxLQ_mZXeS###*/struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;/*p指向终结符线性链表的头结点,h指向动态建成的终结符线性链表节点,top和base分别指向非终结符堆栈的顶和底*/ char curchar; //存放当前待比较的字符:终结符char curtocmp; //存放当前栈顶的字符:非终结符int right;int table[5][6]={{1,0,0,1,0,0},{0,1,0,0,1,1},{1,0,0,1,0,0},{0,1,1,0,1,1},{1,0,0,1,0,0}};/*存放预测分析表,1暗示有发生式,0暗示无发生式。
编译原理实验报告《ll(1)语法分析器构造》

规则右部首符号是终结
符
.
.
{ first[r].append(1,a); break;// 添加并结束
}
if(U.find(P[i][j])!=string::npos)// 规则右部首符号是非终结符 ,形如 X:: =Y1Y2...Yk
{
s=U.find(P[i][ j]);
//cout<<P[i][ j]<<":\n";
arfa=beta=""; for( j=0;j<100&&P[j][0]!=' ';j++) {
if(P[ j][0]==U[i]) {
if(P[ j][4]==U[i])// 产生式 j 有左递归 {
flagg=1;
.
.
for(temp=5;P[j][temp]!=' ';temp++) arfa.append(1,P[
{
int i,j,r,s,tmp;
string* first=new string[n];
char a;
int step=100;// 最大推导步数
while(step--){
// cout<<"step"<<100-step<<endl;
for(i=0;i<k;i++)
{
//cout<<P[i]<<endl;
j][temp]);
if(P[ j+1][4]==U[i]) arfa.append("|");//
实验5LL语法分析程序的设计与实现

实验5LL语法分析程序的设计与实现引言:LL语法分析器是一种自顶向下的语法分析方法,它从语法开始符号开始,通过向前看的一个或者多个输入符号预测产生式的选择,并且通过栈来保存未处理的非终结符。
本实验将设计并实现一个LL语法分析器,包括设计程序的数据结构,算法以及实现细节,并进行相应的测试。
设计概述:1. 实验环境:本实验采用Java编程语言进行实现。
2.数据结构:本实验的数据结构包括文法集合、FIRST集合和FOLLOW 集合、预测分析表等。
3.算法:a)根据给定的文法,构建文法集合和FIRST集合和FOLLOW集合。
b)根据构建的文法集合、FIRST集合和FOLLOW集合,构建预测分析表。
c)根据预测分析表,进行语法分析,实现LL语法分析器。
4.实现细节:本实验实现的LL语法分析器具备错误恢复和语法错误报告的功能。
具体设计与实现:1.构建文法集合:读取给定的文法文件,将每条文法规则分解成产生式的推导式,构建文法集合。
2.构建FIRST集合和FOLLOW集合:遍历文法集合,根据FIRST集合和FOLLOW集合的定义,递归计算每个非终结符的FIRST集合和FOLLOW集合。
3.构建预测分析表:根据构建的文法集合、FIRST集合和FOLLOW集合,生成预测分析表。
4.语法分析过程:根据预测分析表,进行语法分析。
具体过程如下:a)初始化分析栈和输入串,将开始符号和输入串的结束符号入栈;b)重复以下步骤:i)如果栈顶元素是终结符且与输入符号相同,则将栈顶元素出栈,输入串指针前移;ii) 如果栈顶元素是非终结符,则根据预测分析表,选择产生式进行推导,并将该产生式右侧的符号逆序入栈;iii) 如果栈顶元素是结束符号且输入指针也指向结束符号,分析成功;iv) 如果输入指针指向错误的终结符,进行错误恢复处理;v)如果预测分析表中没有对应的产生式,进行错误恢复处理。
5.错误恢复:错误恢复是语法分析器中一个重要的功能,它通过跳过错误符号,继续进行下一步分析来恢复错误。
LL语法分析设计原理与实现技术实验报告文档

LL(1)语法分析设计原理与实现技术实验报告变更说明一、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
二、实验内容:[实验项目]实现LL(1)分析中控制程序(表驱动程序);完成以下描述算术表达式的LL(1)文法的LL(1)分析程序。
G[E]: E→TE′E′→ATE′|εT→FT′T′→MFT′|εF→ (E)|iA→+|-M→*|/[实验说明]终结符号i 为用户定义的简单变量,即标识符的定义。
[设计要求](1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串是否为该文法定义的算术表达式的判断结果;(2)LL(1)分析过程应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
三、实验环境:操作系统:Windows 7软件:VC++四、程序功能描述:提供了文件输入方式,且输入的内容为二元式序列;能够对输入的字符串做出正确的LL(1)分析判断,并给出判断结果,判断结果输出到文件,并显示在屏幕;能发现输入串中的错误,包含非法字符,输入不匹配等;能够处理一些可预见性的错误,如文件不存在,输入非法等。
五、数据结构设计:全局:局部(main()中):六、程序结构描述:设计方法:本程序采用从文件读取的输入方式,输入的内容需为二元式序列,然后按照LL(1)分析的方法对输入的字符串进行分析判断,并输出判断结果,程序通过对输入串的检查能够发现输入串中的错误。
程序规定的单词符号及其种别码见下表:单词符号种别码单词符号种别码(1*5)2/6+3i7-4#8i+-*/()#E E→TG E→TGG G→ATG G→ATG G→εG→εT T→FH T→FHH H→εH→εH→MFH H→MFH H→εH→εF F→i F→(E)A A→+A→-M M→*M→/主要函数说明:check_VT(char ch):bool型函数,检查ch是否为终结字符,是则返回true;create_analyseTable():构建分析表函数,无返回值;error(FILE *fp):输出错误,表示不是该文法的句子,参数fp用于退出前将打开的文件关闭;getnum_VN(char ch):int型函数,查找ch在非终结字符中的位置并返回;getnum_VT(char ch):int型函数,查找ch在终结字符中的位置并返回;justify():bool型函数,判断文件读取内容是否合法,包括检查非法字符和不匹配现象,出错返回false,否则返回true;main():主函数。
实验5---语法分析器(自下而上):LR(1)分析法

实验5---语法分析器(自下而上):LR(1)分析法一、实验目的构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、实验内容程序输入/输出示例(以下仅供参考):对下列文法,用LR(1)分析法对任意输入的符号串进行分析:(1)E->E+T(2)E->E—T(3)T->T*F(4)T->T/F(5)F-> (E)(6)F->i输出的格式如下:(1)LR(1)分析程序,编制人:姓名,学号,班级(2)输入一个以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照。
三、实验方法1.实验采用C++程序语言进行设计,文法写入程序中,用户可以自定义输入语句;2.实验开发工具为DEV C++。
四、实验步骤1.定义LR(1)分析法实验设计思想及算法①若ACTION[sm , ai] = s则将s移进状态栈,并把输入符号加入符号栈,则三元式变成为:(s0s1…sm s , #X1X2…Xm ai , ai+1…an#);②若ACTION[sm , ai] = rj则将第j个产生式A->β进行归约。
此时三元式变为(s0s1…sm-r s , #X1X2…Xm-rA , aiai+1…an#);③若ACTION[sm , ai]为“接收”,则三元式不再变化,变化过程终止,宣布分析成功;④若ACTION[sm , ai]为“报错”,则三元式的变化过程终止,报告错误。
2.定义语法构造的代码,与主代码分离,写为头文件LR.h。
3.编写主程序利用上文描述算法实现本实验要求。
五、实验结果1. 实验文法为程序既定的文法,写在头文件LR.h中,运行程序,用户可以自由输入测试语句。
语法分析程序的设计与实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h> //全局变量
int i=0; char *lookahead;
//用于数组 str 的下标 //用于存放所取到的单词(向前看单词)
//声明函数
char *getnexttoken();
match("-"); T(); EE(); //递归调用 } } void T() { F(); TT(); } void TT() { if(lookahead=="*") { match("*"); F(); TT(); //递归调用 } else if(lookahead=="/") { match("/"); F(); TT(); } } void F() { if(lookahead=="(") { match("("); E(); if(lookahead==")") match(")"); else error(); } else if(lookahead=="i") match("i"); else if(lookahead=="n") match("n");
//递归调用
}
}
void A()
{
if(lookahead=="i:=")
{ match("i:=");
//匹配成功
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验五LL(1)文法识别程序设计一、实验目的通过LL(1)文法识别程序的设计理解自顶向下的语法分析思想。
二、实验重难点FIRST集合、FOLLOW集合、SELECT集合元素的求解,预测分析表的构造。
三、实验内容与要求实验内容:1.阅读并理解实验案例中LL(1)文法判别的程序实现;2.参考实验案例,完成简单的LL(1)文法判别程序设计。
四、实验学时4课时五、实验设备与环境C语言编译环境六、实验案例1.实验要求参考教材93页预测分析方法,94页图5.11 预测分析程序框图,编写表达式文法的识别程序。
要求对输入的LL(1)文法字符串,程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
表达式文法为:E→E+T|TT→T*F|FF→i|(E)2.参考代码为了更好的理解代码,建议将图5.11做如下标注:/* 程序名称:LL(1)语法分析程序*//* E->E+T|T *//* T->T*F|F *//* F->(E)|i *//*目的: 对输入LL(1)文法字符串,本程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
/********************************************//* 程序相关说明*//* A=E' B=T' *//* 预测分析表中列号、行号*//* 0=E 1=E' 2=T 3=T' 4=F *//* 0=i 1=+ 2=* 3=( 4=) 5=# *//************************************/#include"iostream"#include "stdio.h"#include "malloc.h"#include "conio.h"/*定义链表这种数据类型参见:/link?url=_owQzf8PRZOt9H-5oXIReh4X0ClHo6zXtRdWrdSO5YBLpKl NvkCk0qWqvFFxjgO0KzueVwEQcv9aZtVKEEH8XWSQCeVTjXvy9lxLQ_mZXeS###*/ struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;/*p指向终结符线性链表的头结点,h指向动态建成的终结符线性链表节点,top和base分别指向非终结符堆栈的顶和底*/char curchar; //存放当前待比较的字符:终结符char curtocmp; //存放当前栈顶的字符:非终结符int right;int table[5][6]={{1,0,0,1,0,0},{0,1,0,0,1,1},{1,0,0,1,0,0},{0,1,1,0,1,1},{1,0,0,1,0,0}};/*存放预测分析表,1表示有产生式,0表示无产生式。
*/ int i,j;void push(char pchar) /*入栈函数*/{temp=(struct Lchar*)malloc(sizeof(Lchar));temp->char_ch=pchar;temp->next=top;top=temp;}void pop(void) /*出栈函数*/{curtocmp=top->char_ch;if(top->char_ch!='#')top=top->next;}void doforpush(int t) /*根据数组下标计算的值找对应的产生式,并入栈*/ {switch(t){case 0:push('A');push('T');break;case 3:push('A');push('T');break;case 11:push('A');push('T');push('+');break;case 20:push('B');push('F');break;case 23:push('B');push('F');break;case 32:push('B');push('F');push('*');break;case 40:push('i');break;case 43:push(')');push('E');push('(');}}/*根据curchar和curtocmp转为数字以判断是否有产生式*/void changchartoint(){switch(curtocmp) /*非终结符:栈顶*/{case 'E':i=0;break;case 'A':i=1;break;case 'T':i=2;break;case 'B':i=3;break;case 'F':i=4;}switch(curchar) /*终结符:待识别的表达式中*/{case 'i':j=0;break;case '+':j=1;break;case '*':j=2;break;case '(':j=3;break;case ')':j=4;break;case '#':j=5;}}/*识别算法*/void dosome(void){int t;for(;;){pop();/*读取栈顶的字符存curtocmp中*/curchar=h->char_ch; /*读取输入字符链表h中一个字符存入curchar*/printf("\n%c\t%c",curchar,curtocmp);if(curtocmp=='#' && curchar=='#') /*如果都是终结符P94 图5.11圈1、圈5、圈7*/ break;if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F') /*如果curtocmp不是终结符P94 图5.11圈1*/{if(curtocmp!='#') /*如果curtocmp不是终结符,也不是结束符,则根据预测分析表找到产生式并入栈P94 图5.11圈1*/{changchartoint();if(table[i][j]) /*[1.1]有产生式P94 图5.11圈2*/{t=10*i+j; /*计算产生式在数组中的位置*/doforpush(t); /*找对应t的产生式并入栈P94 图5.11圈3*/continue;}else/*[1.2]没有产生式P94 图5.11圈4*/{right=0; /*出错*/break;}}else if(curtocmp!=curchar) /*如果curtocmp不是终结符,并且是结束符,判断终结符链表字符是否也为终结符P94 图5.11圈1、1、5、6*/{right=0; /*出错*/break;}elsebreak; /*正确P94 图5.11圈1、1、5、7*/}else if(curtocmp!=curchar) /* 如果curtocmp是终结符,并且不等于当前终结符链表中的终结符,则出错。
P94 图5.11圈1、8、9*/{right=0; /*出错*/break;}else /*如果curtocmp是终结符,并且等于当前终结符链表中的终结符,则匹配成功,可以读取下一个链表头的终结符P94 图5.11圈10*/{h=h->next; /*读取下一字符*/continue;}}}int main(void){char ch;right=1;base=(struct Lchar*)malloc(sizeof(Lchar)); /*初始化非终结符堆栈,栈底为#,栈顶为文法开始符号*/base->next=NULL;base->char_ch='#';temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=base;temp->char_ch='E';top=temp; /*初始化非终结符堆栈,栈底为#,栈顶为文法开始符号E*//*初始化存放待识别的表达式(终结符)的线性链表头*/h=(struct Lchar*)malloc(sizeof(Lchar));h->next=NULL;p=h; /*开辟了一个空的链表空间,p和h同时指向该空间,该空间将作为终结符链表的头部。
*/printf("请输入要分析的字符串(#号结束)\n");do{ /*输入待识别的表达式*/ch=getch();putch(ch); //在屏幕上输出一个字符if(ch=='i'||ch=='+'||ch=='*'||ch=='('||ch==')'||ch=='#'){ /*将输入的ch存入链表*/temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=ch;h->next=temp;h=h->next;/*如果输入正确,h不断的指向新输入的字符,而p始终指向输入终结符字符串的头位置,即前面开辟的空的链表空间。
*/}else{temp=p->next; /*如果输入错误,提示输入有错,请重新输入,让temp指向输入字符串的头部,并将前面正确输出的字符串再次输出*/printf("\nInput a wrong char!Input again:\n");for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsebreak;temp=temp->next;}}}while(ch!='#');p=p->next; /*消去第一个空头节点,并使头结点指向非空线性链表表头*//*如果输入正确,h 不断的指向新输入的字符,而输入字符串的头位置被记录在p里面。