为什么我的轮班减少/冲突')'而不是'('?

发布于 2024-08-13 03:45:02 字数 486 浏览 2 评论 0原文

我有类似

%(var)

and

%var

的 语法 (var)

我的规则类似于

optExpr:
    | '%''('CommaLoop')'
    | '%' CommaLoop

CommaLoop:
    val | CommaLoop',' val

Expr:
    MoreRules
    | '(' val ')'

问题是它似乎无法判断 ) 是否属于 %(CommaLoop)% (val) 但它抱怨) 而不是 (。到底是什么?它不应该抱怨 ( 吗?我应该如何修复错误?我认为制作 %( 一个令牌是一个很好的解决方案但我想在执行此操作之前确定为什么 $( 不是错误。

I have syntax like

%(var)

and

%var

and
(var)

My rules are something like

optExpr:
    | '%''('CommaLoop')'
    | '%' CommaLoop

CommaLoop:
    val | CommaLoop',' val

Expr:
    MoreRules
    | '(' val ')'

The problem is it doesnt seem to be able to tell if ) belongs to %(CommaLoop) or % (val) but it complains on the ) instead of the (. What the heck? shouldnt it complain on (? and how should i fix the error? i think making %( a token is a good solution but i want to be sure why $( isnt an error before doing this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹏雨一样淡蓝的深情 2024-08-20 03:45:02

这是由于 LR 解析的工作方式造成的。 LR 解析实际上是自下而上的,根据语法规则的 RHS 将标记分组在一起,并用 LHS 替换它们。当解析器“转移”时,它会将一个令牌放入堆栈中,但实际上尚未匹配规则。相反,它通过当前状态跟踪部分匹配的规则。当它到达与规则结束相对应的状态时,它可以减少,将右侧的符号从堆栈中弹出,并推回表示左侧的单个符号。因此,如果存在冲突,它们不会出现,直到解析器到达某些规则的末尾并且无法决定是否减少(或减少什么)。

在您的示例中,看到 % ( val 后,这就是堆栈上的内容(顶部位于当前瞻为 ) 时,它无法决定是否应该弹出 val 并通过规则 CommaLoop: val 进行归约,或者是否应该这样做。移动),这样它就可以弹出 3 个东西,并使用规则 Expr: '(' val ')' 减少

我在这里假设你有一些额外的规则,例如as CommaLoop: Expr,否则你的语法实际上不匹配任何内容,并且 bison/yacc 会抱怨未使用的非终结符。

This is due to the way LR parsing works. LR parsing is effectively bottom-up, grouping together tokens according to the RHS of your grammar rules, and replacing them with the LHS. When the parser 'shifts', it puts a token on the stack, but doesn't actually match a rule yet. Instead, it tracks partially matched rules via the current state. When it gets to a state that corresponds to the end of the rule, it can reduce, popping the symbols for the RHS off the stack and pushing back a single symbol denoting the LHS. So if there are conflicts, they don't show up until the parser gets to the end of some rule and can't decide whether to reduce (or what to reduce).

In your example, after seeing % ( val, that is what will be on the stack (top is at the right side here). When the lookahead is ), it can't decide whether it should pop the val and reduce via the rule CommaLoop: val, or if it should shift the ) so it can then pop 3 things and reduce with the rule Expr: '(' val ')'

I'm assuming here that you have some additional rules such as CommaLoop: Expr, otherwise your grammar doesn't actually match anything and bison/yacc will complain about unused non-terminals.

呆萌少年 2024-08-20 03:45:02

现在,你的解释和你的语法似乎不相符。在您的解释中,您将所有三个短语显示为具有“var”,但您的语法显示以“%”开头的短语允许逗号分隔的列表,而没有的短语仅允许单个“val”。

目前,我假设所有三个都应该允许使用逗号分隔的列表。在这种情况下,我会像这样分解语法:

optExpr: '%' aList

aList: CommaLoop
    | parenList

parenList: '(' CommaLoop ')'

CommaLoop: 
    | val 
    | CommaLoop ',' val

Expr: MoreRules
    | parenList

我更改了 optExpr 和 Expr,因此两者都不能匹配空序列 - 我的猜测是您可能不打算这样做。我已经充实了它,足以通过 byacc 运行它;它不会产生警告或错误。

Right now, your explanation and your grammar don't seem to match. In your explanation, you show all three phrases as having 'var', but your grammar shows the ones starting with '%' as allowing a comma-separated list, while the one without allows only a single 'val'.

For the moment, I'll assume all three should allow a comma-separated list. In this case, I'd factor the grammar more like this:

optExpr: '%' aList

aList: CommaLoop
    | parenList

parenList: '(' CommaLoop ')'

CommaLoop: 
    | val 
    | CommaLoop ',' val

Expr: MoreRules
    | parenList

I've changed optExpr and Expr so neither can match an empty sequence -- my guess is you probably didn't intend that to start with. I've fleshed this out enough to run it through byacc; it produces no warnings or errors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文