概述
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%8dn", 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("PLUSn"); }
"-" { printf("MINUSn"); }
"*" { printf("TIMESn"); }
"/" { printf("DIVIDEn"); }
"|" { printf("ABSn"); }
[0-9]+ { printf("NUMBER %sn", yytext); }
n { printf("NEWLINEn"); }
[ t] { }
. { printf("Mystery character %sn", 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 %cn", *yytext); }
%%
main()
{
int tok;
while(tok = yylex()) {
printf("%d", tok);
if(tok == NUMBER) printf(" = %dn", 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("= %dn> ", $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: %sn", 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 %cn", *yytext); }
%%
我们专门写一个Makefile文件:
fb1-5: fb1-5.l fb1-5.y
bison -d fb1-5.y
flex -o fb1-5.c fb1-5.l
gcc -o $@ fb1-5.tab.c fb1-5.c -lfl
clean:
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简介Flex和Bison安装第一个Flex程序 flex和bison协同工作语法分析器联合编译flex和bison程序的全部内容,希望文章能够帮你解决自制编译器学习3:Flex和Bison简介Flex和Bison安装第一个Flex程序 flex和bison协同工作语法分析器联合编译flex和bison程序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复