自动生成的野牛符号枚举

时间:2016-05-21 20:54:17

标签: bison

我想要使用Flex / Bison生成的解析器来处理玩具语言,该解析器绑定到Rust。为简单起见,我想让Bison简单地为每个匹配的规则调用一个Rust定义的createCstNode()函数来创建一个具体的语法树(它将被转换为Rust中的AST以供进一步处理)。函数调用需要包含匹配的规则类型作为参数,以便我的Rust代码知道它是什么类型的节点(表达式,if语句,while语句,函数调用,文字字符串,数字等)。

通过查看生成的Bison解析器,看起来有一个变量yyn,它似乎是一个表示匹配规则的整数,但我还没有看到它记录在任何地方。我知道%defines选项会在parser.tab.h中给我一个令牌枚举,但我需要枚举终端和非终端符号。我也看到了%token-table选项,它也提供了非终端符号,但也不是我需要的,也直接进入parser.tab.c文件而不是{parser.tab.h文件。 1}}文件,这使得使用类似rust-bindgen的内容变得更加困难。

那么有没有办法让Bison生成类似于yytokentype enum的枚举,其中包含非终端符号,并放入头文件中?还是我坚持为CST节点类型定义自己的枚举,它与我的符号相匹配? yyn是否记录在案?使用它作为识别行动中匹配的规则的方式是否安全?我有什么更好的方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

yyn 记录在任何地方(甚至在生成的代码注释中都没有),我个人不建议使用它。当bison开始执行某个操作时,yyn是操作编号,或者如果您愿意,还会减少触发操作的生产编号。由于非终端可以(通常也可以)有多个产品,因此不是与非终端相对应的数字。

如果使用-v选项打印状态转换,则可以看到差异。在该文件的开头,您将找到生产列表和非终端列表。这是一个简单的例子:

Grammar

    0 $accept: prog $end

    1 prog: expr
    2     | prog ';' expr

    3 expr: NUMBER
    4     | '(' expr ')'
    5     | expr '+' expr
    6     | expr '-' expr
    7     | expr '*' expr
    8     | expr '/' expr

(接下来是终端列表,我省略了。)

Nonterminals, with rules where they appear

$accept (11)
    on left: 0
prog (12)
    on left: 1 2, on right: 0 2
expr (13)
    on left: 3 4 5 6 7 8, on right: 1 2 4 5 6 7 8

在这里,您可以看到有两个用户定义的终端,prog,令牌ID为12,expr,ID为13.有九个用户定义的制作,编号从1到8。这些数字范围不重叠是巧合的;小于11的令牌代码已用于(重新编号的)终端符号以及一些内部令牌。

不会为非终端令牌ID生成枚举,也不会为生产号码生成枚举。野牛解析器并不需要这样的枚举,并且根本不清楚用户程序可能选择用它们做什么,特别是生产数字。

我认为你以错误的方式处理这个问题。如果我理解你正在尝试做什么,你想为每个生产构建一个特定的函数,它将在Rust中实现,并且还需要一个C原型。这似乎是一个简单的代码生成问题,您可以从语法本身开始生成。

从原始的野牛来源中提取语法并不复杂,但如果您不想这样做,您可以轻松使用{{1}中的列表如上所示的文件,可以很好地解析任何简单的文本处理工具,如.output

通过一些工作,并利用未记录的功能,您还可以将语法从野牛的调试数据结构中删除。