好久没更了,现在公司边学习边做一个项目可能后面的写文章的时间也不会很多,今天想记录的这个知识点也是目前做的项目所需的一个简单框架,学的不是很深入简单记录一下。

词法&语法

词法即一个词一个词的检测,如我说“我想你”,如果拆分的话有“我”、“想、“你”,我们将其统计即为词法分析。语法分析则是在词法拆分后进行判断“我想你”很显然是对的,但如果是“我你想”那么就有问题。其中词法分析用的是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&bisonflex是作为辅助一方,主导核心位在bsionbison要做的事也会是比较难的,如计算器中乘除法与加减法的优先级的设计,以及上下文无关的设计等等。而且也不太好理解。

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相关推荐

  1. Bison^Flex=语法分析生成中

    上古时代的时候(前一段时间参加了些些小竞赛,状态有点迷糊,五一又浪里个浪,所以-虽迟但到!),我们有讲解过借助Flex实现SysY词法分析.词法分析是编译的第一阶段,仅仅只是将代码进行切块归类,得到的 ...

  2. flex和bison实例分析

    最近在学习编译原理,利用flex和bison编写一个基于文本识别的简单计算器程序,参考<flex于bison>中内容,对程序进行一些简单的修改,加入Makefile.该计算器程序主要实现识 ...

  3. Flex和Bison简介和Windows下使用入门

    flex用作词法分析,而bison用作语法分析.词法分析把输入分解成一个个有意义的词块,称作token:语法分析则确定这些词块彼此之间如何关联(使用语法树表达). Flex可生成词法分析器:Bison ...

  4. Linux:编译flex、bison总结

    编译flex.bison总结 step1.安装bison step2.安装flex 第一种方式: 第二种方式: END 这个做了很久了,一直没总结,今天以Ubuntu18.04为例,总结一下步骤,没有 ...

  5. 自制编译器学习3:Flex和Bison简介

    Flex和Bison安装 Ubuntu环境下直接安装即可: apt-get install flex bison 第一个Flex程序 首先给出代码(fb1-1.l): /* Companion sou ...

  6. 手把手教程-lex与yacc/flex与bison入门(一)(使用windows环境)

    前言 1.文章诞生的契机 在计算机学习中,我们有时可能会想到自制一门属于自己的编程语言,此时选择lex与yacc来生成词法分析器与语法分析器是非常不错的选择.然而,这两个工具虽然用起来简单,但对于新手 ...

  7. 关于《利用LexYacc进行词法分析和语法分析并生成语法树》

    利用Lex&Yacc进行词法分析和语法分析 写在前面 利用Lex进行词法分析的流程在前面已经讲过,接下来是利用Lex&Yacc进行语法分析,最后可视化生成语法树.具体的操作视频:htt ...

  8. flex与bison

    flex与bison flex与bison简介 词法分析与语法分析 flex用作词法分析,而bison用作语法分析.词法分析把输入分解成一个个有意义的词块,称作token:语法分析则确定这些词块彼此之 ...

  9. ubuntu下安装flex和bison

    做编译原理作业时需要用到flex和bison,于是在Linux下安装了flex和bison apt install flex bison 新建一个文件,名为test.l %% [0-9]+ print ...

  10. lex(flex)yacc(bison)

    初始配置 文法分析用Flex(Lex):将数据分隔成一个个的标记token (标示符identifiers,关键字keywords,数字numbers, 中括号brackets, 大括号braces, ...

最新文章

  1. 我去字节跳动面试,“偷”回来的面试题,题真难...
  2. Swift的数组与OC中数组的区别
  3. Leetcode226. 翻转二叉树(递归、迭代、层序三种解法)
  4. uos20专业版是linux哪个版本,WPS Office 2019 for Linux 专业版已与统一操作系统 UOS 完成适配...
  5. 普通人买得到国债吗?
  6. 记载abp中Dbcontext的疑问
  7. QT tableWidget的使用及其实例
  8. 收藏啦~ Github上 10 个开源免费且优秀的后台控制面板
  9. 水晶报表中的主从表结构
  10. mapper的更多细节,日志配置、核心文件的配置等
  11. Matlab SVPWM仿真模型
  12. 大华海康等摄像头、录像机通过GB28181注册LiveGBS国标流媒体实现网页直播的注册流程解析...
  13. python利用百度翻译器,爬取需要翻译的关键字
  14. 计算机管理即插即用服务,意外终止Plug and Play(即插即用)服务开启方法
  15. 笔记本超频会烧吗_笔记本cpu可以超频吗。有什么危害。怎么超频
  16. 今日发现:BlueJ和MenuetOS
  17. 网络安全系列-VIII: 什么是渗透测试 Penetration Test?
  18. USACO_Wormholes
  19. EOS智能合约开发系列(一)
  20. java 对 Map的遍历

热门文章

  1. 部队计算机操作使用教案,计算机基础教案2(键盘鼠标操作).doc
  2. 射频功放学习之ADS原理图版图联合仿真
  3. EasyCamera开源摄像机接入海康威视摄像机PS流转ES流
  4. 会计计算机二级考试试题,计算机二级考试真题-Word-小刘-会计电算化节节高升...
  5. 现代密码学常用符号总结
  6. shadowgun_SHADOWGUN在Unite上的演讲
  7. 免费建站网站分享,最好的自助建站
  8. 自动升级系统的设计与实现(源码)
  9. iframe标签用法详解
  10. python总结与思考_学Python很久但是一直无法提升!你有思考过究竟是为什么吗?...