1

我正在为编程语言编写语法,但我首先遇到了移位/减少问题。问题可以在状态中找到:

fn_call -> ID . L_PAREN fn_args R_PAREN
assignment -> ID . ASSIGN value
assignment -> ID . ASSIGN container
value -> ID

在进一步解释之前,我想澄清一下:

这是因为程序无法确定我是在调用函数还是将 ID 用作值(例如常量或变量)而导致移位/减少?

继续,有可能解决这个问题吗?我的语言目前不使用行分隔符(例如 C 中的“;”或 Python 中的“\n”)。解析器是 LALR(1)。

在函数调用或带有行分隔符的变量之间进行破译的最有效(向语法中添加最少规则)的方法是什么?

编辑:这是该状态的前瞻。

  ! shift/reduce conflict for L_PAREN resolved as shift
    L_PAREN         shift and go to state 60
    ASSIGN          shift and go to state 61
    COMMA           reduce using rule 43 (value -> ID .)
    R_PAREN         reduce using rule 43 (value -> ID .)
    DASH            reduce using rule 43 (value -> ID .)
    R_BRACE         reduce using rule 43 (value -> ID .)
    NONE            reduce using rule 43 (value -> ID .)
    DEFN            reduce using rule 43 (value -> ID .)
    FOR             reduce using rule 43 (value -> ID .)
    INT_T           reduce using rule 43 (value -> ID .)
    DBL_T           reduce using rule 43 (value -> ID .)
    STR_T           reduce using rule 43 (value -> ID .)
    ID              reduce using rule 43 (value -> ID .)
    INT             reduce using rule 43 (value -> ID .)
    DBL             reduce using rule 43 (value -> ID .)
    STR             reduce using rule 43 (value -> ID .)
    COMMENT_LINE    reduce using rule 43 (value -> ID .)
    L_BRACE         reduce using rule 43 (value -> ID .)
    SET             reduce using rule 43 (value -> ID .)

  ! L_PAREN         [ reduce using rule 43 (value -> ID .) ]
4

2 回答 2

2

以下只是猜测,因为您没有展示太多语法。我假设您允许表达式作为语句,而不仅仅是函数调用。在这种情况下,表达式可以以 开头,(语句可以以 结尾ID。由于您没有语句分隔符(我认为),因此以下内容确实模棱两可:

a = b
(c + d)

阅读b( ID) 后,不清楚是将其简化为value,作为 的一部分assignment,还是将其保留为 ID 并将 转移(为 的一部分fn_call

您无法通过添加产品来消除歧义。:)

于 2013-07-16T07:08:43.107 回答
1

如果这是构成解析器“状态”的一组项目,那么您没有正确写下它:

fn_call -> ID . L_PAREN fn_args R_PAREN
assignment -> ID . ASSIGN value
assignment -> ID . ASSIGN container
value -> ID .  *missing lookahead set*

你没有展示你的语言的其余部分,所以我们不知道规则的前瞻集是什么

 value -> ID

假设您在这种状态下确实存在移位减少冲突,那么前瞻集必须包含“ASSIGN”或“L_PAREN”。如果不了解更多信息,我无法告诉您如何解决您的问题。

鉴于您目前的语法存在这些问题,您无法简单地解决任何类型的“添加规则”,无论它们是否涉及行分隔符,因为添加规则不会更改前瞻集中已经存在的内容(它可能会向现有的套)。

编辑:解决问题的一种方法可能是切换解析技术。您的问题是 LALR 解析器无法处理您似乎拥有的本地歧义。但是,如果您进一步向前看,您的整体语法可能不会有实际的歧义。这取决于你的语言语法,但你自己滚动,所以你可以随心所欲。我建议研究 GLR 解析技术,它可以处理任意前瞻;查看最新版本的 Bison。

于 2013-07-16T07:02:32.687 回答