我有两个规则,其中第一个优先于最后一个,解析器无法解析我的表达式,例如ABC.DEF
,期望SQL_TOKE_GETCLASSID
。相反,我想要的是第二条规则。这些规则具有相同的祖先并且具有相同的左前缀,即SQL_TOKE_NAME '.'
是否有办法告诉野牛优先考虑第二条规则而非第一条规则。
第一条规则
ecclassid_fct_spec:
SQL_TOKEN_NAME '.' SQL_TOKEN_GETECCLASSID '(' ')'
{
...
};
第二条规则
property_path:
property_path_entry
{
$$ = SQL_NEW_DOTLISTRULE;
$$->append ($1);
}
| property_path '.' property_path_entry %prec '.'
{
$1->append($3);
$$ = $1;
}
;
property_path_entry:
SQL_TOKEN_NAME opt_column_array_idx
{... }
;
答案 0 :(得分:1)
片段太小,无法说出任何内容。但是:
您可以重新定义ecclassid_fct_spec。此外,为了帮助减少,您可以定义一个新节点。 tmp_node:
SQL_TOKEN_GETECCLASSID '(' ')';
我处理了“。”在flex中使用状态的问题。
答案 1 :(得分:1)
“优先考虑”是什么意思?如果你想匹配第二条规则只有它完全匹配,如果不匹配第一条规则,那么野牛就不会那样。 Bison是一个LALR(1)解析器,因此它会查看每个令牌并决定哪些规则前缀匹配,通过状态机跟踪。当它与规则的末尾匹配时,它会减少该规则,除非有更长的规则可以匹配,在这种情况下,您将获得转换/减少冲突。在这种情况下,您可以强制它选择shift或reduce with precedence规则,但这样做会抛弃与其他可能性相关的选择,如果事实证明选择对于以后的输入是错误的,那么就没有办法回去。
使用你的语法(片段),在看到SQL_TOKEN_NAME
的前瞻'.'
的输入后,需要做出选择(它会产生移位/减少冲突)。此时,它需要知道它是否应将其视为property_path_entry
或ecclass_id_fct_spec
的开头。但哪个是正确的取决于'.'
之后是什么,并且由于野牛只做了一个前瞻性的标记,所以做出这个选择还为时过早。
现在有一种方法可以让野牛使用更强大的解析机制,可以做更多的前瞻。您可以使用%glr-parser
选项创建GLR解析器而不是LALR(1)解析器。只要它不含糊不清,这本身就足以使你的语法有效。但是如果你的语法含有任何含糊之处,你将会遇到运行时故障,除非你在你的语法中添加必要的歧义解决annoations。野牛手册包含大量的GLR模式文档,因此您应该在尝试使用它之前阅读它。