Bison LALR(1)对百分比和mod使用%移位/减少错误

Bison LALR(1)对百分比和mod使用%移位/减少错误,bison,lalr,shift-reduce-conflict,Bison,Lalr,Shift Reduce Conflict,我开始了一个使用%(以及单词mod)作为模运算符的语法项目,现在我想添加%,作为后面的一元运算符除以100 注意,我不使用基于C的语言,我使用bison的XML输出实现了自己的标记器/编译器。我选择的步骤对我的实现至关重要 有没有一种方法可以使我的语法在LALR(1)编译器中编译而不发生任何移位/减少错误 以下陈述基本上都是有效的: 5%->0.05 5%%5->0.05 mod 5 5%%%5->0.0005 mod 5 等等 我只是不知道如何在我的语法中表达: %token S_NUM

我开始了一个使用
%
(以及单词
mod
)作为模运算符的语法项目,现在我想添加
%
,作为后面的一元运算符除以100

注意,我不使用基于C的语言,我使用bison的XML输出实现了自己的标记器/编译器。我选择的步骤对我的实现至关重要

有没有一种方法可以使我的语法在LALR(1)编译器中编译而不发生任何移位/减少错误

以下陈述基本上都是有效的:

  • 5%
    ->0.05
  • 5%%5
    ->0.05 mod 5
  • 5%%%5
    ->0.0005 mod 5 等等
我只是不知道如何在我的语法中表达:

%token S_NUM

%%

default: mod_term ;

mod_term: _mod_value
    | percent_term ;

_mod_value: mod_term O_PERCENT percent_term ;

percent_term: _percent_value
    | value ;

_percent_value: value O_PERCENT ;

value: S_NUM ;

%%
我还使用以下语句编译它:
bison-v--report=all--warnings=no other-Werror=conflicts sr--xml test.y-o test.y.xml

(由于我的环境,我强制转换/减少为错误)


有什么想法吗?我使用了
%left
%right
说明符,但运气不好。

如果您愿意接受解析器复杂性的增加,您可以通过添加
%GLR parser
指令将其转换为GLR解析器。这将意味着解析器在到达冲突点时将拆分和探索这两个状态,然后在处理了足够的令牌后,将删除任何无法解析的状态。不过,这确实需要一个足够新的野牛版本。然而,正如其他人所建议的那样,重新设计语言可能更好。考虑到Bison对GLR解析器的现有限制,使用GLR解析器意味着您可能会使用一行中百分比数量的指数级内存。

如果您愿意接受解析器复杂性的增加,您始终可以通过添加
%GLR parser
指令将其转换为GLR解析器。这将意味着解析器在到达冲突点时将拆分和探索这两个状态,然后在处理了足够的令牌后,将删除任何无法解析的状态。不过,这确实需要一个足够新的野牛版本。然而,正如其他人所建议的那样,重新设计语言可能更好。考虑到Bison对GLR解析器的现有限制,使用GLR解析器意味着您可能会使用一行中百分比数量的指数级内存。

这里的模糊性介于后缀运算符和中缀运算符之间。这与常见的表达式解析器问题非常相似,即
'-'
既是前缀又是中缀运算符,您可以使用显式
%prec
指令以相同的方式解决此问题。写这篇文章的传统方式是:

%left '%'            /* left-associative infix operator */
%nonassoc POSTFIX    /* postfix operations are higher precedence */
%token VAL
%%

expr: expr '%' expr
    | expr '%' %prec POSTFIX
    | VAL
    ;
使用优先级解决中缀-%的关联歧义以及中缀和后缀之间的优先级歧义

要在不使用优先规则的情况下解决此问题,您需要以下内容:

%token S_NUM O_PERCENT
%%

default: mod_term ;

mod_term: _mod_value
    | _mod_value O_PERCENT mod_term ;

_mod_value: _mod_value O_PERCENT ;
    | S_NUM
    ;

这使得中缀-%右关联,而不是左关联。不幸的是,如果不使用使中缀-%左关联的优先级规则,我看不到解决这个问题的方法。这是因为,在看到给定的
'%'
标记之后,您才能确定该标记是中缀还是后缀,因此
'%'
之前的非终结符对于这两个规则都需要相同(
\u mod_value
此处或%prec代码中的
expr
)这里的模糊性介于后缀运算符和中缀运算符之间。这与常见的表达式解析器问题非常相似,即
'-'
既是前缀又是中缀运算符,您可以使用显式
%prec
指令以相同的方式解决此问题。写这篇文章的传统方式是:

%left '%'            /* left-associative infix operator */
%nonassoc POSTFIX    /* postfix operations are higher precedence */
%token VAL
%%

expr: expr '%' expr
    | expr '%' %prec POSTFIX
    | VAL
    ;
使用优先级解决中缀-%的关联歧义以及中缀和后缀之间的优先级歧义

要在不使用优先规则的情况下解决此问题,您需要以下内容:

%token S_NUM O_PERCENT
%%

default: mod_term ;

mod_term: _mod_value
    | _mod_value O_PERCENT mod_term ;

_mod_value: _mod_value O_PERCENT ;
    | S_NUM
    ;

这使得中缀-%右关联,而不是左关联。不幸的是,如果不使用使中缀-%左关联的优先级规则,我看不到解决这个问题的方法。这是因为,在看到给定的
'%'
标记之后,您才能确定该标记是中缀还是后缀,因此
'%'
之前的非终结符对于这两个规则都需要相同(
\u mod_value
此处或
expr
在%prec代码中)

会出现什么错误,关于哪些州?您可能需要添加更多的示例。如果输入为
6%5
,则为6.5。如果输入为
8%%%5
,则为8乘以0.01乘以0.01乘以0.05。我不确定是否有办法使这一点明确无误。当您在
8%%%5
中找到第二个
%%
时,您必须查看前面的两个标记,以确定下一个百分比后面有一个数字-这意味着您的语法不是LALR(1)。看第一个百分比,你必须看前面的三个代币才能知道你在处理什么。我认为你需要重新设计你的语言。@JonathanLeffler谢谢你的回复,我确实添加了你在我的原始帖子中提到的例子。是的,关于LALR(1)不够,你是正确的。我的两个选择是不推荐将
%
作为模数,只使用
mod
,或者我可以重新设计语言并再次实现解析器以进行补偿。我只是希望有更简单的事情。。。低垂的水果。目前,我使用
mod
作为模数,
%
作为百分比,希望没有使用此选项实现。请在编辑问题后发表评论,而不是在编辑问题之前发表评论。在一份报告中看到“我确实添加了示例”是很烦人的