Flex和Bison安装

Ubuntu环境下直接安装即可:

apt-get install flex bison

第一个Flex程序

首先给出代码(fb1-1.l)

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-1.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* fb1-1 just like unix wc */
%{
int chars = 0;
int words = 0;
int lines = 0;
%}%%[a-zA-Z]+  { words++; chars += strlen(yytext); }
\n      { chars++; lines++; }
.       { chars++; }%%main()
{yylex();printf("%8d%8d%8d\n", lines, words, chars);
}

flex程序分为3部分,每一部分通过符号%%来分割,第一部分包含声明和选项设置,第二部分是一系列的模式和动作,第三部分是会被拷贝到词法生成器里面的C代码。

第一部分,%{%}之间的代码会被照抄到生成C文件的头部,可以看到在这个实例中只是定义了3个整型变量。

第二部分,每一个模式匹配位于一行的开始,接着是匹配时要执行的的C代码,C代码为{}之间的一行或者多行代码。[a-zA-Z]+用来匹配一个单词,大括号内表示可以匹配任意大小写字母,+表示匹配一个或多个前面的字符,即一串字母或者一个单词,flex中,yytext总是被指定为本次匹配的输入文本,.表示匹配任意一个字符。

第三部分,主程序,调用flex的词法分析例程,并输出结果。

执行flex

flex -o fb1-1.c fb1-1.l

词法生成器翻译成c程序,c文件为:fb1-1.c

使用gcc编译生成可执行文件:

gcc fb1-1.c -lfl -o fb1-1

注意编译时需要链接库(-lfl),执行该程序,输入3个字符串后按ctrl+d退出,输出结果如下:

flex和bison协同工作

来看第二段代码:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-3.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%%
"+"  { printf("PLUS\n"); }
"-"   { printf("MINUS\n"); }
"*"   { printf("TIMES\n"); }
"/"   { printf("DIVIDE\n"); }
"|"     { printf("ABS\n"); }
[0-9]+ { printf("NUMBER %s\n", yytext); }
\n      { printf("NEWLINE\n"); }
[ \t] { }
.   { printf("Mystery character %s\n", yytext); }
%%

这里只给出了模式匹配,flex的lfl库提供了极小的主程序来调用词法分析器,这里已经足够,词法分析器的生成和编译与之前相同,生成可执行词法分析程序,执行后输入12+34和13/34做词法分析,执行结果如下:

考虑一个更完成的计算器词分析器:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-4.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%{enum yytokentype {NUMBER = 258,ADD = 259,SUB = 260,MUL = 261,DIV = 262,ABS = 263,EOL = 264 /* end of line */};int yylval;%}%%
"+"  { return ADD; }
"-"   { return SUB; }
"*"   { return MUL; }
"/"   { return DIV; }
"|"     { return ABS; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n      { return EOL; }
[ \t]   { /* ignore white space */ }
.   { printf("Mystery character %c\n", *yytext); }
%%
main()
{int tok;while(tok = yylex()) {printf("%d", tok);if(tok == NUMBER) printf(" = %d\n", yylval);else printf("\n");}
}

输出结果如下:

我们来分析下代码,flex做词分析返回记号流时,每个记号记号编号(token number)和记号值(token's value)组成,其中记号编号为一个小的整数,bison自动从258开始编号,并且创建一个编号定义的.h文件,这里为了方便理解通过enum进行了手工定义。主程序调用yylex()返回记号值,对于NUMBER转换为int。

语法分析器

下面基于flex和bison来设计一个基本的语法分析器,bison遵循BNF(BackusNaur Form)语法,

在BNF里,::=(:)是被定义为的意思,|表示其左右两边任选一项, 左边的名称是语法符号(symbol),有效的BNF是具有递归性的,例如处理 1×5+2×3这种简单的算术表达式:

<exp> ::= <factor>| <exp> + <factor>
<factor> ::= NUMBER| <factor> * NUMBER

exp被定义为一个factor 或者 factor + exp,而facotr被定义为NUMBER或者factor×NUMBER,每个规则最左边是非终结符,冒号右边是非终结符的推导规则,如果推导规则是多个那么通过|隔开。

我们给出bison代码的示例(fb1-5.y):

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-5.y,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* simplest version of calculator */%{
#  include <stdio.h>
%}/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL%%calclist: /* nothing 空规则 从输入开头开始匹配*/  | calclist exp EOL { printf("= %d\n> ", $2); } /*EOL代表一个表达式的结束*/| 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; };
%%
main()
{printf("> "); yyparse();
}yyerror(char *s)
{fprintf(stderr, "error: %s\n", s);
}

bison程序同样包含三部分:声明部分,规则匹配部分和C代码部分。

声明部分同样是用%{%}包括且要原样拷贝到C代码,随后%token记号声明,便于告诉bison在语法分析程序中记号的名称,记号通常总是大写,未声明为记号的语法符号必须出现在至少一条规则的左边。

规则部分通过简单的BNF定义规则,bison使用单一的冒号而不是::=,同时由于行间隔并不明显,用分号来表示规则的结束,C的动作代码在每条规则之后用花括号括起来。

我们来详细看下匹配规则,第一个语法符号calclist,第一个匹配是空值,第二个是表达式(exp)+结束符(EOL),第三个是只有结束符的情况。

接下来的语法符号是term->factor->exp,匹配规则:

term: NUMBER 或者 绝对值的 term或者 加括号的 exp;

factor: term 或者 factor和term的乘法(左递归) 或者factor和term(左递归)的除法 或者 绝对值;

exp: factor 或者 exp和exp的加法 或者 exp和factor的乘法(左递归) 或者 exp和factor(左递归)的除法。

显然是由小到大组成的(并不是绝对的,term也会匹配exp),并且优先级越高的越靠前,由于BNF语法具有递归性,这样的顺序可以保证运算优先级的正确性。

目标符号(冒号左边的语法符号)的值在动作代码中用$$代替,右边语法符号的语义值依次为$1 $2 $3 ......。当词法分析器返回记号时,记号值总是存储在yyval中。

联合编译flex和bison程序

flex代码(fb1-5.l)如下:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-5.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%{
# include "fb1-5.tab.h"
%}%%
"+"  { 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); }
%%

我们专门写一个Makefile文件:

fb1-5:   fb1-5.l fb1-5.ybison -d fb1-5.yflex -o fb1-5.c fb1-5.lgcc -o $@ fb1-5.tab.c fb1-5.c -lflclean:rm -f fb1-5 \fb1-5.c fb1-5.tab.c fb1-5.tab.h

执行

bison -d fb1-5.y

会生成文件:fb1-5.tab.h 和 fb1-5.tab.c,在flex文件中调用该头文件即可以实现联合编译,最后生成可执行程序fb1-5,测试结果如下:

可以看到,由于缺少对负数的支持,所以输入负数会报错。先讲到这里,本节介绍了如何设计最基本的词法分析器和语法分析器,后面会对flex和bison做更详细介绍。

end

自制编译器学习3:Flex和Bison简介相关推荐

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

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

  2. flex与bison

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

  3. 方舟编译器学习笔记分类与导读

    方舟学习笔记系列,从方舟开源到现在,已经写了50多篇,保证了每天一篇的更新频率.篇数增加之后,文章的分类以及文章之间的关系,逐渐变得复杂起来.本文将对已发表的学习笔记系列进行分类和导读,方便读者更好的 ...

  4. 编译器(汇编器)开发工具Flex和Bison的使用方法之Flex

    点击打开链接 编译器和汇编器在工作过程中,往往完成如下的任务: (1) 读取源代码并且获得程序的结构描述: (2) 分析程序结构,并且生成相应的目标代码. Flex和Bison就是为可以帮助完成以上任 ...

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

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

  6. 自己写编译器学习总结

    如何写一个简单的编译器? https://www.zhihu.com/question/36756224 初学编译原理,想写一个简单的编译器. 是时候亮出我的 LL 语言了,全称:Lambda Lit ...

  7. flex和bison实例分析

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

  8. ubuntu下安装flex和bison

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

  9. 在windows下安装flex和bison、GCC

    学习Stellar-core 需要依赖项flex .bison .gcc三个依赖项 下载得网址: 链接: https://pan.baidu.com/s/1mitCLcs 密码: 3jaj   通过 ...

最新文章

  1. IIS8 添加配置 WCF服务
  2. pytorch多维筛选
  3. Day 3: Flask —— 使用Python和OpenShift进行即时Web开发
  4. android jni 调用java_Android JNI开发系列(九)JNI调用Java的静态方法实例方法
  5. 1、Locust压力测试环境搭建
  6. java js base64_java与js转base64编码格式
  7. Nginx连接池实现,源码阅读
  8. java界面跳转代码_java软件里面的跳转页面代码实现
  9. 虚拟光驱xp版32位_Windows 32位系统将成历史,勾起了我对Windows XP满满的回忆
  10. 【STM32】标准库 菜鸟入门教程(1)初识最小系统
  11. 【图解版】B2C电商平台解决方案
  12. 做产品路线图规划用什么工具?
  13. 全面屏下的沉浸式状态栏的返回键、home键、菜单键的显示。
  14. Python编程PTA题解大全——索引
  15. android视频用什么组件,一个简单的移动端视频组件的实现
  16. C语言——百钱百鸡问题分析(最优解法)
  17. 数组.列表.集合.应用
  18. Zeus源码解读之定时任务执行与手动执行任务的过程分析
  19. 点击table中的某一个td,获得这个tr的所有数据
  20. [摘录]知彼解己—同理心交流的原则

热门文章

  1. RISC-V嵌入式开发准备篇1:编译过程简介
  2. [Java] 用java来突破一下人类极限
  3. google chrome卸载之后无法安装成功
  4. python时间序列如何拟合曲线_【Python】keras使用LSTM拟合曲线
  5. 实战Intel MKL(Math Kernel Library)
  6. Boss直聘数据采集及分析
  7. zeek(bro) 脚本学习 三
  8. 如何用PHP实现图片与视频合成,照片如何插入视频中|照片与视频合并
  9. DOS经典软件,落下帷幕,新型国产平台,蓬勃发展
  10. CentOS常用仓库