Bison功能很强大,可以加参数-v可以生成可阅读的.output文件,还可以生成dot转换图
本文以lex
yacc 创建一个桌面计算器为例子研究bison生成代码
所有介绍都以bison生成为准,通过-v生成*.output文件,通过设置#define YYDEBUG 1以及yydebug=1进行调制
文法
0 ACCEPT : OVER
1 OVER : E '\n'
2 E : E + T
3 E : T
4 T : T * F
5 T : F
6 F : ( E )
7 F : NUM
状态图
|
|
NUM |
+ |
* |
( |
) |
$ |
\n |
E |
F |
T |
OUT |
def |
0 |
ACC->.OVER |
s1 |
|
|
s2 |
|
|
|
4 |
6 |
5 |
3 |
|
1 |
F->NUM. |
|
|
|
|
|
|
|
|
|
|
|
r7 |
2 |
F->(.E) |
s1 |
|
|
s2 |
|
|
|
7 |
6 |
5 |
|
|
3 |
ACC->OVER. |
|
|
|
|
|
acc |
|
|
|
|
|
|
4 |
OUT->e.'\n'
E->E.+T |
|
s10 |
|
|
|
|
s9 |
|
|
|
|
|
5 |
E->T.
T->T.*F |
|
|
s11 |
|
|
|
|
|
|
|
|
r3 |
6 |
T->F. |
|
|
|
|
|
|
|
|
|
|
|
r5 |
7 |
E->E.+T
F->(E.) |
|
s10 |
|
|
s12 |
|
|
|
|
|
|
|
8 |
ACC->OVER end. |
|
|
|
|
|
|
|
|
|
|
|
acc |
9 |
OVER->E'\n'. |
|
|
|
|
|
|
|
|
|
|
|
r1 |
10 |
E->E+.T |
s1 |
|
|
s2 |
|
|
|
|
6 |
13 |
|
|
11 |
T->T*.F |
s1 |
|
|
s2 |
|
|
|
|
14 |
|
|
|
12 |
F->(E). |
|
|
|
|
|
|
|
|
|
|
|
r6 |
13 |
E->E+T.
T->T.*F |
|
|
s11 |
|
|
|
|
|
|
|
|
r2 |
14 |
T->T*F. |
|
|
|
|
|
|
|
|
|
|
|
r4 |
3+2*5规约过程
|
栈 |
符号 |
输入 |
动作 |
0 |
0 |
$ |
3+2*5\n$ |
shift1 |
1 |
0 1 |
$3 |
+2*5\n$ |
r7 |
2 |
0 6 |
$F |
+2*5\n$ |
r5 |
3 |
0 5 |
$T |
+2*5\n$ |
read->r3 |
4 |
0 4 |
$E |
+2*5\n$ |
shift10 |
5 |
0 4 10 |
$E+ |
2*5\n$ |
shift1 |
6 |
0 4 10 1 |
$E+2 |
*5\n$ |
r7 |
7 |
0 4 10 6 |
$E+F |
*5\n$ |
r5 |
8 |
0 4 10 13 |
$E+T |
*5\n$ |
shift11 |
9 |
0 4 10 13 11 |
$E+T* |
5\n$ |
shift1 |
10 |
0 4 10 13 11 1 |
$E+T*5 |
\n$ |
r7 |
11 |
0 4 10 13 11 14 |
$E+T*F |
\n$ |
r4 |
12 |
0 4 10 13 |
$E+T |
\n$ |
r2 |
13 |
0 4 |
$E |
\n$ |
shift9 |
14 |
0 4 9 |
$E\n |
$ |
r1 |
15 |
0 3 |
$OVER |
$ |
over |
源代码分析
yyprhs[] { } 产生式右端文法串在yyrhs中的开始位置
yyrhs[] { } 以-1隔开的产生式右端串
yyrline[] { 0, 8, 8, 9 } .y文件中产生式定义所在的行号,调试信息用
yyname[] {{0:$end}, {1:error}, {2:$undefined}, {3:NUM}, {4:'\n'}, {5:+}, {6:*}, {7:(}, {8:)}, {9:acc}, {10:OUT}, {11:E}, {12:T}, {13:F}, '\0' }
yytoknum[] { 0, 256, 257, 258, 10, 43, 42, 40, 41 }功能与yytranslate相同,token转化为标示符
yy1[] {}产生式左端符号的编号,阅读Bison生成的.output文件开头即可明白
yyr2[] { } 产生式右端长度,阅读Bison生成的.output文件开头即可明白,规约的时候从栈中弹出多少个状态用到
yydefact[] { } 对于每个状态的缺省规约表达式,对应于状态图中def这一列+1
yydefgoto[] { } 对于每个非终结符号,状态0情况下GOTO状态
yypact[] { } 如果某个状态只有默认动作,则为设置默认操作值,这儿是-6, 没有向前看token的情况下执行判断
yypgoto[] { }
yytable[] { }
yycheck[] { }
yystos[] { }
如果yypact值不为默认值,则yypact、yytoken、yytable、yycheck来确定状态转移,应该是用了某种压缩算法
规约以后状态转移根据yypgoto,判断采用yytable还是yydefgoto计算新的state
参考资源
以下是网上找到的资源,太不容易了
bison的实现中用到的表格:
- yyrhs 和yyprhs一起表示产生式右端文法串,是一个用-1隔开的索引串大数组,串的内容是文法符号的编号
- yyr1 产生式左端文法符号的编号
- yyr2 产生式右端长度
- yyrline 产生式的定义行
- yyprhs 和yyrhs一起表示产生式右端文法串,内容为右端在yyrhs中的起始位置
- yytname 文法符号的名称,必须用YYDEBUG条件编译
- yytranslate 把flex返回的token编号翻译成bison的文法编号
- yytoknum flex返回的token编号翻译成bison的token编号
- yytable DFA状态转移表
- yycheck 和yycheck等长的数组
- yypgoto 非终结符号上的goto下个状态
- yypact Index in YYTABLE of the portion describing STATE-NUM.
- yydefact 缺省动作,长度为DFA的状态个数
- yydefgoto 缺省goto,长度为非终结符号
实 际上BISON就是给我们造表,至于怎么用这个表是我们的事,这些好比是个瓤子,在这个瓤子外头套个毛衣,一个翻译程序就出来了。当然一般来说都是直接用 嵌在BISON里头的毛衣,这样就得到一个LALR(1)分析程序,BISON程序多半支持一个``-S''参数可以用来切换毛衣。
想 了想,明白为什么昨天搞的那个parse tree那么庞大了,因为那个语法是从c99手册扒出来的一点都没有改造过。c99为了严谨用的是优先级级联的无二义性的文法(所以c99里头用不着说明 什么优先级了),这个文法的毛病就是实现太不方便,太多的单一产生式(右端只有一个文法符号的产生式),所以parse tree打印出来就成了一个个很大的锯齿。反观gcc的语法文件就很不一样,引入优先级说明之后,文法变的很简单,所以分析树也得到了简化。
http://www.docin.com/p-483435351.html
介绍了gcc语法分析
yyprhs[] { 0, 0, 3, 7 } 产生式右端文法串在yyrhs中的开始位置,表示从第3、7项开始
yyrhs[] { 6, 0, -1, 6, 4, 3, -1, 3, -1 } 以-1隔开的产生式右端串
yydefact[] { 0, 3, 0, 1, 0, 2 } 对于每个状态的缺省规约表达式,0表示默认出错
yydefgoto[] { -1, 2 } 对于每个非终结符号的缺省GOTO
yypact[] { -2, -3, 0, -3, -1, -3 } -3:默认 没有向前看token的情况下执行判断
yypgoto[] { -3, -3 }
yytable[] { 3, 1, 5, 0, 4 }
yycheck[] { 0, 3, 3, -1, 4 }
yystos[] { 0, 3, 6, 0, 4, 3 }
Bison功能很强大,可以加参数-v可以生成可阅读的.output文件,还可以生成dot转换图
本文以lex
yacc 创建一个桌面计算器为例子研究bison生成代码
所有介绍都以bison生成为准,通过-v生成*.output文件,通过设置#define YYDEBUG 1以及yydebug=1进行调制
文法
0 ACCEPT : OVER
1 OVER : E '\n'
2 E : E + T
3 E : T
4 T : T * F
5 T : F
6 F : ( E )
7 F : NUM
状态图
|
|
NUM |
+ |
* |
( |
) |
$ |
\n |
E |
F |
T |
OUT |
def |
0 |
ACC->.OVER |
s1 |
|
|
s2 |
|
|
|
4 |
6 |
5 |
3 |
|
1 |
F->NUM. |
|
|
|
|
|
|
|
|
|
|
|
r7 |
2 |
F->(.E) |
s1 |
|
|
s2 |
|
|
|
7 |
6 |
5 |
|
|
3 |
ACC->OVER. |
|
|
|
|
|
acc |
|
|
|
|
|
|
4 |
OUT->e.'\n'
E->E.+T |
|
s10 |
|
|
|
|
s9 |
|
|
|
|
|
5 |
E->T.
T->T.*F |
|
|
s11 |
|
|
|
|
|
|
|
|
r3 |
6 |
T->F. |
|
|
|
|
|
|
|
|
|
|
|
r5 |
7 |
E->E.+T
F->(E.) |
|
s10 |
|
|
s12 |
|
|
|
|
|
|
|
8 |
ACC->OVER end. |
|
|
|
|
|
|
|
|
|
|
|
acc |
9 |
OVER->E'\n'. |
|
|
|
|
|
|
|
|
|
|
|
r1 |
10 |
E->E+.T |
s1 |
|
|
s2 |
|
|
|
|
6 |
13 |
|
|
11 |
T->T*.F |
s1 |
|
|
s2 |
|
|
|
|
14 |
|
|
|
12 |
F->(E). |
|
|
|
|
|
|
|
|
|
|
|
r6 |
13 |
E->E+T.
T->T.*F |
|
|
s11 |
|
|
|
|
|
|
|
|
r2 |
14 |
T->T*F. |
|
|
|
|
|
|
|
|
|
|
|
r4 |
3+2*5规约过程
|
栈 |
符号 |
输入 |
动作 |
0 |
0 |
$ |
3+2*5\n$ |
shift1 |
1 |
0 1 |
$3 |
+2*5\n$ |
r7 |
2 |
0 6 |
$F |
+2*5\n$ |
r5 |
3 |
0 5 |
$T |
+2*5\n$ |
read->r3 |
4 |
0 4 |
$E |
+2*5\n$ |
shift10 |
5 |
0 4 10 |
$E+ |
2*5\n$ |
shift1 |
6 |
0 4 10 1 |
$E+2 |
*5\n$ |
r7 |
7 |
0 4 10 6 |
$E+F |
*5\n$ |
r5 |
8 |
0 4 10 13 |
$E+T |
*5\n$ |
shift11 |
9 |
0 4 10 13 11 |
$E+T* |
5\n$ |
shift1 |
10 |
0 4 10 13 11 1 |
$E+T*5 |
\n$ |
r7 |
11 |
0 4 10 13 11 14 |
$E+T*F |
\n$ |
r4 |
12 |
0 4 10 13 |
$E+T |
\n$ |
r2 |
13 |
0 4 |
$E |
\n$ |
shift9 |
14 |
0 4 9 |
$E\n |
$ |
r1 |
15 |
0 3 |
$OVER |
$ |
over |
源代码分析
yyprhs[] { } 产生式右端文法串在yyrhs中的开始位置
yyrhs[] { } 以-1隔开的产生式右端串
yyrline[] { 0, 8, 8, 9 } .y文件中产生式定义所在的行号,调试信息用
yyname[] {{0:$end}, {1:error}, {2:$undefined}, {3:NUM}, {4:'\n'}, {5:+}, {6:*}, {7:(}, {8:)}, {9:acc}, {10:OUT}, {11:E}, {12:T}, {13:F}, '\0' }
yytoknum[] { 0, 256, 257, 258, 10, 43, 42, 40, 41 }功能与yytranslate相同,token转化为标示符
yy1[] {}产生式左端符号的编号,阅读Bison生成的.output文件开头即可明白
yyr2[] { } 产生式右端长度,阅读Bison生成的.output文件开头即可明白,规约的时候从栈中弹出多少个状态用到
yydefact[] { } 对于每个状态的缺省规约表达式,对应于状态图中def这一列+1
yydefgoto[] { } 对于每个非终结符号,状态0情况下GOTO状态
yypact[] { } 如果某个状态只有默认动作,则为设置默认操作值,这儿是-6, 没有向前看token的情况下执行判断
yypgoto[] { }
yytable[] { }
yycheck[] { }
yystos[] { }
如果yypact值不为默认值,则yypact、yytoken、yytable、yycheck来确定状态转移,应该是用了某种压缩算法
规约以后状态转移根据yypgoto,判断采用yytable还是yydefgoto计算新的state
参考资源
以下是网上找到的资源,太不容易了
bison的实现中用到的表格:
- yyrhs 和yyprhs一起表示产生式右端文法串,是一个用-1隔开的索引串大数组,串的内容是文法符号的编号
- yyr1 产生式左端文法符号的编号
- yyr2 产生式右端长度
- yyrline 产生式的定义行
- yyprhs 和yyrhs一起表示产生式右端文法串,内容为右端在yyrhs中的起始位置
- yytname 文法符号的名称,必须用YYDEBUG条件编译
- yytranslate 把flex返回的token编号翻译成bison的文法编号
- yytoknum flex返回的token编号翻译成bison的token编号
- yytable DFA状态转移表
- yycheck 和yycheck等长的数组
- yypgoto 非终结符号上的goto下个状态
- yypact Index in YYTABLE of the portion describing STATE-NUM.
- yydefact 缺省动作,长度为DFA的状态个数
- yydefgoto 缺省goto,长度为非终结符号
实 际上BISON就是给我们造表,至于怎么用这个表是我们的事,这些好比是个瓤子,在这个瓤子外头套个毛衣,一个翻译程序就出来了。当然一般来说都是直接用 嵌在BISON里头的毛衣,这样就得到一个LALR(1)分析程序,BISON程序多半支持一个``-S''参数可以用来切换毛衣。
想 了想,明白为什么昨天搞的那个parse tree那么庞大了,因为那个语法是从c99手册扒出来的一点都没有改造过。c99为了严谨用的是优先级级联的无二义性的文法(所以c99里头用不着说明 什么优先级了),这个文法的毛病就是实现太不方便,太多的单一产生式(右端只有一个文法符号的产生式),所以parse tree打印出来就成了一个个很大的锯齿。反观gcc的语法文件就很不一样,引入优先级说明之后,文法变的很简单,所以分析树也得到了简化。
http://www.docin.com/p-483435351.html
介绍了gcc语法分析
yyprhs[] { 0, 0, 3, 7 } 产生式右端文法串在yyrhs中的开始位置,表示从第3、7项开始
yyrhs[] { 6, 0, -1, 6, 4, 3, -1, 3, -1 } 以-1隔开的产生式右端串
yydefact[] { 0, 3, 0, 1, 0, 2 } 对于每个状态的缺省规约表达式,0表示默认出错
yydefgoto[] { -1, 2 } 对于每个非终结符号的缺省GOTO
yypact[] { -2, -3, 0, -3, -1, -3 } -3:默认 没有向前看token的情况下执行判断
yypgoto[] { -3, -3 }
yytable[] { 3, 1, 5, 0, 4 }
yycheck[] { 0, 3, 3, -1, 4 }
yystos[] { 0, 3, 6, 0, 4, 3 }
分享到:
相关推荐
该文件包含tmcpar_lex()由 Bison 生成的解析器在内部调用的词法分析器函数的实现。词法分析器定义文件使用解析器定义文件提供的标记定义。由于词法分析器应该返回标记定义,因此应该先运行 Bison。
Linux环境中使用Flex_Bison进行SQL语法分析
c语法分析器,采用bison2.1(yacc), flex(lex), 生成程序的语法树 分析单个文件,不支持预处理, 不解析预处理符号# bison,flex工具在上传包内,语法见cgrammar-new.y,词法见input.lex 另附相关说明,本代码采用vs...
bison 语法分析程序生成器 flex 记法分析程序生成器 文件内含windows可执行程序和源代码。
windows下的用来生成程序的工具,flex是一个词法分析器,用来将一个.l文件生成一个.c程序文件。bison是词法分析器,根据文法把一系列的记号转换成一个语法分析树。
程序包括.l .y .cpp .h 4个部分,根据原先的 pl0.c 进行改写,功能是读入一段给定的程序并进行自动分析,生成代码序列。 1.程序会要求用户输入文件的名称,然后确定输出文件的名称。 2.自动逐个单词读取文件中信息。...
│ ├── cgen.sh # 由flex/bison生成lexer.c,parser.c,parser.h │ ├── display.c # ast输出主函数display(ASTNode* T) │ ├── lexer.l # 词法规则文件 │ └── parser.y # 语法规则文件 └── test_...
词法分析与语法分析的原始文件扩展: ://www.quut.com/c/ANSI-C-grammar-l-1998.html和 实现了C语言除了struct和指针几乎所有的语法。 运行 环境要求:flex bison g ++ 11 python3 中间代码生成 Windows命令行输入:...
像bison这样的解析器生成器对于语法原型非常有用,不幸的是,它需要大量代码才能启动和运行。 这只是一个非常小的示例,显示了构建基于野牛的解析器所需的样板代码。 我喜欢bison的地方是,您可以编译和部署bison-...
要使用lex和yacc(或其GNU版本flex和bison)来创建一个可以在控制台生成语法分析树的词法分析器和语法分析器,你需要遵循以下步骤: 定义词法规则 (lex文件): 使用正则表达式来定义你的语言中的记号(tokens)。 ...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...
Bison 是一个由 GNU 项目开发的解析器生成器,通常用于将语法描述转换成一个 C 程序。它是 Yacc(Yet Another Compiler Compiler)的一个自由软件替代品,广泛用于编译器和解释器的开发中,尤其是在处理复杂的语法和...