Bison 如何改变野牛的规则优先级?

Bison 如何改变野牛的规则优先级?,bison,Bison,我有两条规则,第一条规则优先于最后一条规则,解析器无法解析我的表达式,例如ABC.DEFitexpectedSQL\u TOKE\u GETCLASSID。相反,我想要的是第二条规则。这些规则具有相同的祖先和相同的左前缀,即SQL_TOKE_NAME'. 有没有办法告诉野牛优先考虑第二条规则而不是第一条规则 第一条规则 ecclassid_fct_spec: SQL_TOKEN_NAME '.' SQL_TOKEN_GETECCLASSID '(' ')' { ...

我有两条规则,第一条规则优先于最后一条规则,解析器无法解析我的表达式,例如
ABC.DEF
itexpected
SQL\u TOKE\u 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
        {... }
    ;
第二条规则

 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
        {... }
    ;

碎片太小,什么也说不出来。然而:

  • 您可以重新定义ecclassid\u fct\u规范。此外,为了帮助减少,您可以定义一个新节点。 tmp_节点:

    SQL_-TOKEN_-GETECCLASSID'('')

  • 我通过使用flex中的状态来处理“.”问题

  • 不确定是否可以中断SQL\u令牌\u名称。看起来像这样 这是概括
  • 你说的“优先”是什么意思?如果您只想在第二条规则完全匹配的情况下匹配它,如果不想尝试匹配第一条规则,bison就不能这样工作。Bison是一个LALR(1)解析器,因此它会查看每个令牌并决定匹配的规则前缀集,并通过状态机跟踪。当它匹配到一个规则的末尾时,它会减少该规则,除非有一个更长的规则可以匹配,在这种情况下,您会得到一个移位/减少冲突。在这种情况下,您可以强制它选择具有优先规则的shift或reduce,但这样做会丢弃与其他可能性相关的选择,如果结果表明该选择对于以后的输入是错误的,则无法返回

    对于语法(片段),它需要在看到输入的
    SQL\u-TOKEN\u-NAME
    前面有一个
    “,
    之后做出选择(它得到一个移位/减少冲突)。此时,它需要知道是否应该将其视为
    属性\u路径\u条目
    ecclass\u id\u fct\u规范
    的开头。但哪一个是正确的取决于
    后面的内容。
    ,由于野牛只做了一个单独的前瞻标记,现在做出选择还为时过早


    现在有一种方法可以让bison使用更强大的解析机制,可以做更多的前瞻性工作。您可以使用
    %glr parser
    选项来创建glr解析器,而不是LALR(1)解析器。这本身就足以让你的语法有效,只要它不含糊不清。但是如果您的语法包含任何歧义,您将获得运行时失败,除非您在语法中添加必要的歧义解决注释。野牛手册包含大量关于GLR模式的文档,因此在尝试使用它之前,您应该阅读这些文档。

    它确实报告了该规则的冲突。这需要一些调试,但我所做的是消除歧义
    ecclassid\u fct\u spec
    left规则实际上是一个
    属性路径
    。所以我做了
    ecclassid\u fct\u spec:property\u path.'SQL\u TOKEN\u GETECCLASSID'('')
    ,解决了这个问题。我的更改使规则左递归,这对LALR解析器很有好处。但这个问题与flex语法比bison更相关。其中,标记太一般,不使用谓词。但不管怎样,这个问题现在似乎已经解决了。@affan:这一更改使语法更加通用——它将接受类似于
    标记的内容。代币GETECLASSID()
    作为一个
    eclassif\u fct\u规范
    ,它可能是您想要的,也可能不是您想要的。如果您希望这些情况无效,可以在操作中添加额外的语义检查,以针对这些情况发出错误。不,这正是我想要的。但是
    myClass.GETECCLASSID()
    只能以一个
    标记作为前缀。虽然属性路径可以是
    a.d.c
    来处理我抛出的
    YYERROR
    ,但在GETECCLASSID()的情况下,请确保属性路径长度正好是一,您的第三点非常相关。我正好遇到了flex语法包含太多泛化标记的障碍,这实际上导致语法模棱两可。我想我需要使用谓词来使标记更具体。谢谢你的帮助。