基于YACC的TINY语法分析器的构建
实验要求
运用YACC,针对TINY语言,构造一个语法分析器。
实验方案
1.文法:
exp → exp addop term|term
addop → +|-
term → term mulop factor|factor
mulop → *
factor → (exp)|number
2.设计输入文件内容:
(注:无换行)
3.设计应有的输出:
4.Lex与Yacc的数据传递原理与方法
首先,在设计程序中,由于定义了自己的main()函数,它在某个点上调用了yyparse()。YACC会创建相应的yyparse()函数,并在y.tab.c中结束该函数。
yyparse()函数读取一个『标识符/值对』(token/value pairs)流,这些流需要事先就提供,这些流可以是手写的代码提供的,也可以是lex生成的。而在lex与Yacc的联合使用中,把这个工作丢给了lex。
每次yylex()调用都会返回一个整数值,该值代表了一个标识符类型(token type)。它告诉Yacc,已经读取了这种标识符。该标识符可以有一个值,它应该存放在yylval变量中。
但是在该文法中,yylval的变量类型并不是始终都是同一种类型,可以看到主要有int类型的number和char类型的’+’,’-’,’*’。
所以在这里为yylval定义了%union来解决这个问题,通过
%union{char chr;int integer;
}
让yylval包含了一个char型的变量与一个int型的变量来获取从lex中得到的数据,之后再利用
%token <integer> number
%type <integer> exp
%type <chr> term factor
来标识number、exp、term、factor的类型,%token表示这是一个终结符的类型,而%type只是标注类型。
之后,在lex语句中也需要修改,通过类似于从结构体中获取变量的
yylval.integer=atoi(yytext);
来控制返回的变量。
%left 表示左结合,%right 表示右结合。最后列出的定义拥有最高的优先权。因此在这个例子中乘法拥有比加法和减法更高的优先权。+ - * 所有这三个算术符都是左结合的。运用这个简单的技术,我们可以消除文法的歧义。
%left '+' '-'%left '*'
分析表parsing table
理论和设计(描述parsing table在实验方案中的作用,观察并输出parsing table)
分析表:
分析表包含action动作表以及goto转移表,action表的每一列,对应文法中的终结符号或者$,每一项表示一个语法分析动作,goto表中的每一列对应着文法中的非终结符,每一项表示某一项遇到的每一个状态遇到某一非终结符进入的状态。
sn:将符号a、状态n压入栈
rn:用第n个产生式进行规约
利用win_bison -v test_yacc.y生成分析表
生成test_yacc.output文件
分析表:
四、内容和步骤
1、针对TINY语言给出 yacc的y文件的代码:
test_yacc.y
%{#include <stdio.h>
#include<ctype.h>
%}%union{char chr;int integer;
}%token <integer> number
%type <integer> exp
%type <chr> term factor
%left '+' '-'
%left '*'%%
command : exp { printf("the end of this calculation is %d\n",$1); };/*允许打印结果*/ exp : exp '+' term { $$ = $1 + $3; }| exp '-' term { $$ = $1 - $3; }| term { $$ = $1; };term : term '*' factor { $$ = $1 * $3; }| factor { $$ = $1; };factor : number { $$ = $1; }| '(' exp ')' { $$ = $2; };
%%int yyerror(char *s)
{fprintf(stderr,"error:%s\n",s);return 0;
}
2、给出.l文件的代码:
test_lex.l
%{#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define false 0
#define ture 1
#include "test_yacc.tab.h"
%}digit [0-9]%%
{digit}+ {yylval.integer=atoi(yytext);printf("number:%d\n",yylval.integer);return(number);
}\+ {yylval.chr=yytext[0];printf("opterator:%c\n",yylval.chr);return('+');
}\- {yylval.chr=yytext[0];printf("oprator:%c\n",yylval.chr);return('-');
}\* {yylval.chr=yytext[0];printf("oprator:%c\n",yylval.chr);return('*');
}"(" {yylval.chr=yytext[0];printf("separator:%c\n",yylval.chr);return('(');
}")" {yylval.chr=yytext[0];printf("separtor:%c\n",yylval.chr);return(')');
}; {return(';');
}[ \t]+ {printf("lexical analyzer error\n");/*忽略空格*/
}quit {printf("Bye!\n");exit(0);
}%%
int yywrap()
{return(1);
}
3.main函数代码:
main2.c
#include"lex.yy.c"
#include"test_yacc.tab.c"
#include <stdlib.h>
#include <stdio.h>
extern int yyparse();int main(int argc, char* argv[]){extern FILE *yyin;if((yyin=fopen("test.txt","rt"))==NULL){perror("无法打开文件test.txt\n") ;exit(1);}if (yyparse()==1){fprintf(stderr,"parser error\n");exit(1);}printf("yyparse() completed successfully!\n");return 0;
}
3、实验具体步骤
安装flex和bison。flex和 bison 是两个用来生成程序的工具,它们用来词法和语法分析器。flex 和 bison 本身不是词法或语法分析器,利用它们生成的程序才是。
新建文本文件,更改名称为test_lex.l,敲入代码,新建文本文件,更改名称为test_yacc.y,敲入代码(后缀不能改,名称自己取,但是要注意不同名字下#include”test_yacc.tab.c”不一样,需要更改)
打开控制台,进入到刚才所建立文件所在的文件夹,输入:
得到:
之后加入test.txt文件并写入算式文本,并对主函数文件main2.c进行编译运行
五、实验结果:
截图
六、实验结论:
分析和总结
利用工具的可以在实现语法分析和词法分析的时候,只需要根据lex和yacc工具给出的格式进行编写就可以很轻松的完成词法分析和语法分析,不用考虑整个程序的流程,等琐碎的细节,并且可以使用工具轻松输出分析表。
手写编程程序来进行词法分析和语法分析,可以较为全面的把控所有的细节,对于输入,输出,token的定义,等等方面可以进行更加详细的设计。但缺点也很明显,对于初学者来说需要更大的学习成本,并且在手写编程的过程中若对原理不熟练会出现各种各样的问题,整个过程相对更耗时,需要更多时间才能体会到语法分析器的妙用。
实验中出现的冲突及解决过程描述
使用%union之后,%token number语句中,%token是用来描述终结符,而%type才是非终结符的类型描述。
使用%left语句需要确定’+’、’-’和’*’的优先级
需要确定编译的顺序,确保顺序正确,按步骤执行,才能正确
基于YACC的TINY语法分析器的构建相关推荐
- 《编译原理》实验报告——基于YACC的TINY语法分析器的构建
一.实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验方案 (1)设计基于LEX的TINY词法分析器 (2)设计基于YACC的TINY语法分析器 ( ...
- 编译原理——实验叁——基于YACC的TINY语法分析器的构建
一. 实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二. 实验方案 (1)设计基于YACC的TINY词法分析器 (2)设计基于LEX的TINY语法分析器 ...
- 编译原理——实验叁预习报告——基于YACC的TINY语法分析器的构建
一.实验目的: 运用YACC,针对给定的文法,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验预习提示 1.表达:针对5.5节中的calculator文法,设计输入和输出 2.观察:观察p ...
- 《编译原理》实验预习报告——基于YACC的TINY语法分析器的构建
一.实验目的 运用YACC,针对给定的文法,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验预习提示 1.表达:针对5.5节中的calculator文法,设计输入和输出 2.观察:观察pa ...
- 《编译原理》实验报告——递归下降语法分析器的构建
一.实验要求 运用递归下降法,针对给定的上下文无关文法,给出实验方案.预估实验中可能出现的问题. 二.实验方案 1.构造LL(1),通过设计.编制.调试递归下降语法分析程序,对输入的符号串进行分析匹配 ...
- 递归下降语法分析器的构建_一文了解函数式查询优化器Spark SQL Catalyst
大数据技术与架构点击右侧关注,大数据开发领域最强公众号! 暴走大数据点击右侧关注,暴走大数据!记录一下个人对sparkSql的catalyst这个函数式的可扩展的查询优化器的理解,目录如下: 0. O ...
- yacc语法分析minipascal_语法分析器 YACC实验报告
课程名称 编译原理课程设计 实验课时 实验项目 基于 YACC 的语法分析器 实验时间 实验目的 1 . 学习基于 YACC 的语法分析器的构造方法. 2 . 学习 C- 的语法结构. 实验环境 Pa ...
- 基于Java语言的语法分析器
LR(0)语法分析器 实验目的: 根据LR(0)语法分析的原理,编写.调试一个语法分析代码程序,对输入的句子进行分析. 实验工具: 使用了Java语言进行编写 ,使用Java开发工具IntelliJ ...
- 基于c语言的语法分析器的实现
一. 总体实现思想 我采用自顶向下的预测分析技术来实现,其基本方法如下: 从文法开始符号出发,在每一步推导过程中根据当前句型的最左非终结符A和当前输入符号a,选择正确的A-产生式.为保证分析的确定性, ...
- 编译原理实验-递归下降语法分析器的构建
实验目的: 针对给定的上下文无关文法,编制一个递归下降分析程序. 分析: 递归下降语法分析的前提是保证LL(1)文法 递归下降的思路就是暴力dfs.对每个程序直接不管三七二十一搜进去,只要能搜到就继续 ...
最新文章
- I/O多路转接之 select
- lda主题模型应用java_主题模型LDA及在推荐系统中的应用
- c 调用易语言dll字节集,总结VC与易语言DLL互相调用的方法
- AI繁荣下的隐忧——Google Tensorflow安全风险剖析
- C#基础第三天-作业-集合-冒泡排序-模拟名片
- 一台linux上运行多个mysql_linux下同时运行多个mysql
- MVC中@Html.DisPlayFor(model=model.newsName)和 @Model.newsName的区别
- XOS 源码详解2: os_s_xxxx.s 汇编代码的段定义AREA,程序入口ENTRY,程序结尾END.
- Hibernate读书笔记---继承映射
- 【PetShop 4.0学习】1.技术特点
- Array类filter方法实例--查找功能.
- OpenCV(二)OpenCV的介绍和发展
- 《变革中的思索》连载九:放飞的爱——母亲和我
- 【Vulnhub靶场】NOOB: 1
- CCS中的linked resource
- 网页中视频在线播放脚本
- 概率论---古典概型
- Java学习:从入门到精通week4
- Jenkins自动化部署阿里云K8s
- 网页版白噪声A Soft Murmur