【发布时间】:2016-04-07 16:50:51
【问题描述】:
目前我正在尝试为 VHDL 构建一个解析器 有一些 C++-Parsers 必须面对的问题。 VHDL 的上下文无关文法产生解析 森林而不是单个解析树,因为它是 关于函数调用和数组订阅的歧义
foo := fun(3) + arr(5);
这个赋值只能在解析器明确解析 会携带一个层次分明的、类型感知的符号表 它可以用来即时解决歧义。
我不想这样做,因为对于像 前面提到,解析森林不会呈指数增长,但是 相当线性取决于函数调用的数量和 数组订阅。
(当然,除非有人会用类似这样的语句来折磨解析器)
foo := fun(fun(fun(fun(fun(4)))));
由于野牛强制用户只创建一个解析树, 我使用 %merge 属性递归地收集所有子树 在单例中的所谓 AMBIG 节点下添加了这些子树 AST。
结果看起来像this。
为了产生上述内容,我解析了令牌流“I=I(N);”。 我在 parse.y 文件中使用的语法的实质是 下面收集。它试图类似于 VHDL 的模棱两可的部分:
start: prog
;
/* I cut out every semantic action to make this
text more readable */
prog: assignment ';'
| prog assignment ';'
;
assignment: 'I' '=' expression
;
expression: function_call %merge <stmtmerge2>
| array_indexing %merge <stmtmerge2>
| 'N'
;
function_call: 'I' '(' expression ')'
| 'I'
;
array_indexing: function_call '(' expression ')' %merge <stmtmerge>
| 'I' '(' expression ')' %merge <stmtmerge>
;
The whole sourcecode can be read at this github repository.
现在,让我们开始讨论实际的问题。 正如您在上面生成的解析树中看到的那样, 节点 FCALL1 和 ARRIDX1 指的是同一个 单节点 EXPR1 依次引用 N1 两次。
无论如何,这不应该发生,我也没有 知道为什么。相反应该有路径
FCALL1 -> EXPR2 -> N2
ARRIDX1 -> EXPR1 -> N1
你知道为什么野牛会重复使用上述 节点?
我还写了一份关于官方 gnu 邮件的错误报告 列出野牛,但没有对此作出答复。 不幸的是,由于新 stackoverflow 的限制 用户,我无法提供此错误报告的链接...
【问题讨论】:
标签: parsing bison text-parsing glr