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)编译器中编译而不发生任何移位/减少错误
以下陈述基本上都是有效的:
->0.055%
->0.05 mod 55%%5
->0.0005 mod 5 等等5%%%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
作为模数,%
作为百分比,希望没有使用此选项实现。请在编辑问题后发表评论,而不是在编辑问题之前发表评论。在一份报告中看到“我确实添加了示例”是很烦人的