词法分析flex 语法分析bison
好久没更了,现在公司边学习边做一个项目可能后面的写文章的时间也不会很多,今天想记录的这个知识点也是目前做的项目所需的一个简单框架,学的不是很深入简单记录一下。
词法&语法
词法即一个词一个词的检测,如我说“我想你”,如果拆分的话有“我”、“想、“你”,我们将其统计即为词法分析。语法分析则是在词法拆分后进行判断“我想你”很显然是对的,但如果是“我你想”那么就有问题。其中词法分析用的是flex实现,语法分析使用的是bison实现的。
Flex
flex用于生成词法程序(注意flex不能做词法分析,它生成的程序才能),它是一个自动化工具,可以按照定义好的规则自动生成一个C函数yylex(),也称为扫描器(Scanner)。这个C函数yylex()把文本串作为输入,按照定义好的规则分析文本串中的字符,找到符合规则的一些字符序列后,就执行在规则中定义好的动作。
也可以理解为这个函数其实是一个入口,当调用这个函数时我们会自动进入flex的布局中正则匹配从键盘上输入的字符串,如果成功就执行动作(说着可能有点懵,下面会用代码演示便于理解)。
/*flex-wc.l*/
%option noyywrap
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[a-zA-z]+ { words++; chars += strlen(yytext); }
\n { lines++; chars++; }
. { chars++; }
%%
int main() {yylex();printf("%8d %8d %8d\n", lines, words, chars);return 0;
}
输入:hello world输出:1 2 10
flex程序是用flex语法与C代码混合组成的,包括三部分:
①%option……%{……%} 包含第一行的选项 和 后面百分号+括号内的声明,其中括号内的声明是纯C语法。这里声明了一些全局变量来统计词、字和行。
②%%……%%包括模式和动作,可以看到模式其实就是一种匹配机制,上面用的是正则匹配,其实大部分用的也是正则匹配,后面的动作即要执行的代码。其中yytext是匹配到的数据(如果匹配到多次就执行动作多次)。
③后面的就是纯C代码,目的是用于生成一个flex的入口。
在Linux下编译的指令为:
flex flex-wc.lgcc lex.yy.c -lfl./a.out
继续温习flex的一个代码
%{enum {NUMBER = 258,ADD = 259,};int yylval = 0;
%}
%%
"+" { return ADD; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
%%
int main()
{int token;while((token = yylex()) != 0) {printf("%d", token);if (token == NUMBER)printf(" = %d", yylval);printf("\n");}return 0;
}
输入:
13 + 14输出:
258=13
259
258=14
上面的代码为什么要用258、289?其他的0 1 2 3不行吗?这里要提一下在与bison联合使用时,标记编号的0值意味着文件结束;而为了防止与ASCII码和内定值冲突,其他的标记编号要从258开始定义。而且从输出结果中我们可以知道yylex()的返回值就是flex的return。
Bison
Bison用于生成语法分析器程序,在flex&bison中flex是作为辅助一方,主导核心位在bsion,bison要做的事也会是比较难的,如计算器中乘除法与加减法的优先级的设计,以及上下文无关的设计等等。而且也不太好理解。
bison的语法分析有两种:一种是LALR(1),自左向右前看一个记号;另一种是GLR,通用的自左向右。大多数语法分析器使用LALR(1),它不如GLR强大但被认为比GLR更块和更容易使用。bison程序包括与flex程序相同的三个部分结构:声明部分、规则部分、C代码部分,三个部分两两之用%%隔开,yyparse()可以理解为语法分析的入口。
直接看一串语法分析的代码(别的师傅那借用的,下面会附上链接):
/* simplest version of calculator */%{
#include <stdio.h>
int yyerror(const char *, ...);
extern int yylex();
extern int yyparse();
%}/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL%%calclist: /* nothing */| calclist exp EOL { printf("= %d\n> ", $2); }| calclist EOL { printf("> "); } /* blank line or a comment */
;exp: factor| exp ADD exp { $$ = $1 + $3; }| exp SUB factor { $$ = $1 - $3; }| exp ABS factor { $$ = $1 | $3; }
;factor: term| factor MUL term { $$ = $1 * $3; }| factor DIV term { $$ = $1 / $3; }
;term: NUMBER| ABS term { $$ = $2 >= 0? $2 : - $2; }| OP exp CP { $$ = $2; }
;
%%
int main()
{printf("> "); yyparse();return 0;
}
int yyerror(const char *s, ...)
{int ret;va_list va;va_start(va, s);ret = vfprintf(stderr, s, va);va_end(va);return ret;
}
光有语法分析是不够的,语法分析是建立在词法分析的基础上,所以再附上师傅的词法分析,
/* recognize tokens for the calculator and print them out */%{
# include "fb1-5.tab.h"
extern int yyerror(const char *, ...);
%}%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP; }
")" { return CP; }
[-+]?[0-9]+ { yylval = atoi(yytext); return NUMBER; }\n { return EOL; }
"//".*
[ \t] { /* ignore white space */ }
. { yyerror("Mystery character %c\n", *yytext); }
%%
直接过一遍语法分析,可以看到有一种写法
term: NUMBER| ABS term { $$ = $2 >= 0? $2 : - $2; }
这个写法我个人觉得比较难理解。term为目标符号为后面动作$$的值,NUMBER是一个限制,一开始默认会$$=$1即将NUMBER赋给term,后面的操作得看NUMBER是否符合条件,当term有值过后在一步一步往后推进,其实说白了这就可以用递归的思想来理解。
①声明部分:
%{到%}部分会被拷贝到目标分析程序的开头。
%token后接一个大写的变量,可以理解为词法分析器得到的结果,用于传入语法分析器进行分析。② 规则部分:
1、冒号 : 用于定义规则。分号 ; 表示一个规则的结束。
2、在每个规则之后,使用{}括起,表明如何处理。
3、规则按照语法树从上到下定义规则,第一条规则为语法起始符号,必须与输入匹配。
4、目标符号(冒号左边的语法符号)的值在动作中代码用$$代替,右边(准确来说是一个限制,后面才算)语法符号的语义值依次为$1,$2,直到这条规则的结束。
5、如果一个规则缺少现实的动作,语法分析器将把$1赋予$$,这是一个内部设定。
返回记号的时候,记号对应的值是存储在yylval变量中。③纯 C部分:
主程序,负责调用yyparse(),并输出结果。
上面的代码有一段代码很有意思,就是如下
exp: factor| exp ADD exp { $$ = $1 + $3; }| exp SUB factor { $$ = $1 - $3; }| exp ABS factor { $$ = $1 | $3; }
;
可以看到执行先后顺序相同的加减法一个是exp ADD exp 另一个是 exp SUB factor,这是为什么呢?这里需要提到一个二义性的问题,啥叫二义性?就是执行一个相同的东西会出现两种不同结果的可能。正如上述如果出现了
3 - 5 + 4 = ?
如果是exp SUB exp那么存在的二义性为
(3-5)+ 4 = 2
3-(5+4)=-6
相反如果是加法就不会出现这种二义性的情况,所以加法使用exp SUB exp。
而减法不行,因此用factor代替,为啥factor可以?看最低NUMBER那一条其中可以添加括号,所以用factor就可以避免这种二义性的结果产生。
参考:flex与bison_德阳凯子哥的博客-CSDN博客_flex和bison
二. 初识Bison:写一个简单计算器 - 简书
3.01 bison基本概念及语法介绍_ronnie88597的博客-CSDN博客_bison语法
词法分析flex 语法分析bison相关推荐
- Bison^Flex=语法分析生成中
上古时代的时候(前一段时间参加了些些小竞赛,状态有点迷糊,五一又浪里个浪,所以-虽迟但到!),我们有讲解过借助Flex实现SysY词法分析.词法分析是编译的第一阶段,仅仅只是将代码进行切块归类,得到的 ...
- flex和bison实例分析
最近在学习编译原理,利用flex和bison编写一个基于文本识别的简单计算器程序,参考<flex于bison>中内容,对程序进行一些简单的修改,加入Makefile.该计算器程序主要实现识 ...
- Flex和Bison简介和Windows下使用入门
flex用作词法分析,而bison用作语法分析.词法分析把输入分解成一个个有意义的词块,称作token:语法分析则确定这些词块彼此之间如何关联(使用语法树表达). Flex可生成词法分析器:Bison ...
- Linux:编译flex、bison总结
编译flex.bison总结 step1.安装bison step2.安装flex 第一种方式: 第二种方式: END 这个做了很久了,一直没总结,今天以Ubuntu18.04为例,总结一下步骤,没有 ...
- 自制编译器学习3:Flex和Bison简介
Flex和Bison安装 Ubuntu环境下直接安装即可: apt-get install flex bison 第一个Flex程序 首先给出代码(fb1-1.l): /* Companion sou ...
- 手把手教程-lex与yacc/flex与bison入门(一)(使用windows环境)
前言 1.文章诞生的契机 在计算机学习中,我们有时可能会想到自制一门属于自己的编程语言,此时选择lex与yacc来生成词法分析器与语法分析器是非常不错的选择.然而,这两个工具虽然用起来简单,但对于新手 ...
- 关于《利用LexYacc进行词法分析和语法分析并生成语法树》
利用Lex&Yacc进行词法分析和语法分析 写在前面 利用Lex进行词法分析的流程在前面已经讲过,接下来是利用Lex&Yacc进行语法分析,最后可视化生成语法树.具体的操作视频:htt ...
- flex与bison
flex与bison flex与bison简介 词法分析与语法分析 flex用作词法分析,而bison用作语法分析.词法分析把输入分解成一个个有意义的词块,称作token:语法分析则确定这些词块彼此之 ...
- ubuntu下安装flex和bison
做编译原理作业时需要用到flex和bison,于是在Linux下安装了flex和bison apt install flex bison 新建一个文件,名为test.l %% [0-9]+ print ...
- lex(flex)yacc(bison)
初始配置 文法分析用Flex(Lex):将数据分隔成一个个的标记token (标示符identifiers,关键字keywords,数字numbers, 中括号brackets, 大括号braces, ...
最新文章
- 我去字节跳动面试,“偷”回来的面试题,题真难...
- Swift的数组与OC中数组的区别
- Leetcode226. 翻转二叉树(递归、迭代、层序三种解法)
- uos20专业版是linux哪个版本,WPS Office 2019 for Linux 专业版已与统一操作系统 UOS 完成适配...
- 普通人买得到国债吗?
- 记载abp中Dbcontext的疑问
- QT tableWidget的使用及其实例
- 收藏啦~ Github上 10 个开源免费且优秀的后台控制面板
- 水晶报表中的主从表结构
- mapper的更多细节,日志配置、核心文件的配置等
- Matlab SVPWM仿真模型
- 大华海康等摄像头、录像机通过GB28181注册LiveGBS国标流媒体实现网页直播的注册流程解析...
- python利用百度翻译器,爬取需要翻译的关键字
- 计算机管理即插即用服务,意外终止Plug and Play(即插即用)服务开启方法
- 笔记本超频会烧吗_笔记本cpu可以超频吗。有什么危害。怎么超频
- 今日发现:BlueJ和MenuetOS
- 网络安全系列-VIII: 什么是渗透测试 Penetration Test?
- USACO_Wormholes
- EOS智能合约开发系列(一)
- java 对 Map的遍历
热门文章
- 部队计算机操作使用教案,计算机基础教案2(键盘鼠标操作).doc
- 射频功放学习之ADS原理图版图联合仿真
- EasyCamera开源摄像机接入海康威视摄像机PS流转ES流
- 会计计算机二级考试试题,计算机二级考试真题-Word-小刘-会计电算化节节高升...
- 现代密码学常用符号总结
- shadowgun_SHADOWGUN在Unite上的演讲
- 免费建站网站分享,最好的自助建站
- 自动升级系统的设计与实现(源码)
- iframe标签用法详解
- python总结与思考_学Python很久但是一直无法提升!你有思考过究竟是为什么吗?...