我正在编写一种编程语言的语法,但我一直在努力解决转移/减少问题。问题可以在州内找到:
fn_call -> ID . L_PAREN fn_args R_PAREN
assignment -> ID . ASSIGN value
assignment -> ID . ASSIGN container
value -> ID
在进一步解释之前,我想澄清一下:
这是shift / reduce,因为程序无法确定我是在调用函数还是使用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 .) ]
答案 0 :(得分:2)
以下只是猜测,因为你没有表现出太多的语法。我假设你允许表达式作为语句,而不仅仅是函数调用。在这种情况下,表达式可以以(
开头,语句可以以ID
结尾。既然你没有语句分隔符(我认为),那么下面的内容真的很模糊:
a = b
(c + d)
在阅读b
(ID
)后,不清楚是否将其缩减为value
,作为assignment
的一部分,或将其保留为ID并将(
转换为fn_call
的一部分。
您无法通过添加制作来消除歧义。 :)
答案 1 :(得分: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
假设您在此状态下确实存在shift-reduce冲突,则前瞻集必须包含“ASSIGN”或“L_PAREN”。我不能告诉你如何在不知道更多的情况下解决你的问题。
鉴于你目前的语法存在这些问题,你无法解决这个简单的“添加规则”,无论它们是否涉及行分隔符,因为添加规则不会改变已经在先行集中的内容(它可能会添加更多令牌到现有的集合。)
编辑:解决问题的一种方法可能是切换解析技术。您的问题是LALR解析器无法处理您似乎拥有的 local 歧义。但是,如果你向前看,你的整体语法可能没有实际的模糊性。这取决于你的语言语法,但你正在自己动手,所以你可以随意做。我建议研究一下可以处理任意前瞻的GLR解析技术;查看最近版本的Bison。