Ply shift/reduce 冲突:悬挂 else 和空制作
Ply shift/reduce conflicts: dangling else and empty productions
我有很多冲突,其中大部分是由于运算符和关系运算符具有不同的优先级。但我仍然面临一些我真的不知道如何解决的冲突。其中一些在下面。我怀疑也许我应该对 stmtlist
进行 epsilon 消除,但老实说我不确定。
状态 70:
state 70
(27) block -> LCB varlist . stmtlist RCB
(25) varlist -> varlist . vardec
(28) stmtlist -> . stmt
(29) stmtlist -> . stmtlist stmt
(30) stmtlist -> .
(15) vardec -> . type idlist SEMICOLON
(33) stmt -> . RETURN exp SEMICOLON
(34) stmt -> . exp SEMICOLON
(35) stmt -> . WHILE LRB exp RRB stmt
(36) stmt -> . FOR LRB exp SEMICOLON exp SEMICOLON exp RRB stmt
(37) stmt -> . IF LRB exp RRB stmt elseiflist
(38) stmt -> . IF LRB exp RRB stmt elseiflist ELSE stmt
(39) stmt -> . PRINT LRB ID RRB SEMICOLON
(40) stmt -> . block
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
(44) exp -> . lvalue ASSIGN exp
(45) exp -> . exp SUM exp
(46) exp -> . exp MUL exp
(47) exp -> . exp SUB exp
(48) exp -> . exp DIV exp
(49) exp -> . exp MOD exp
(50) exp -> . exp AND exp
(51) exp -> . exp OR exp
(52) exp -> . exp LT exp
(53) exp -> . exp LE exp
(54) exp -> . exp GT exp
(55) exp -> . exp GE exp
(56) exp -> . exp NE exp
(57) exp -> . exp EQ exp
(58) exp -> . const
(59) exp -> . lvalue
(60) exp -> . ID LRB explist RRB
(61) exp -> . LRB exp RRB
(62) exp -> . ID LRB RRB
(63) exp -> . SUB exp
(64) exp -> . NOT exp
(27) block -> . LCB varlist stmtlist RCB
(31) lvalue -> . ID
(32) lvalue -> . ID LSB exp RSB
(72) const -> . INTEGERNUMBER
(73) const -> . FLOATNUMBER
(74) const -> . TRUE
(75) const -> . FALSE
! shift/reduce conflict for RETURN resolved as shift
! shift/reduce conflict for WHILE resolved as shift
! shift/reduce conflict for FOR resolved as shift
! shift/reduce conflict for IF resolved as shift
! shift/reduce conflict for PRINT resolved as shift
! shift/reduce conflict for ID resolved as shift
! shift/reduce conflict for LRB resolved as shift
! shift/reduce conflict for SUB resolved as shift
! shift/reduce conflict for NOT resolved as shift
! shift/reduce conflict for LCB resolved as shift
! shift/reduce conflict for INTEGERNUMBER resolved as shift
! shift/reduce conflict for FLOATNUMBER resolved as shift
! shift/reduce conflict for TRUE resolved as shift
! shift/reduce conflict for FALSE resolved as shift
RCB reduce using rule 30 (stmtlist -> .)
RETURN shift and go to state 99
WHILE shift and go to state 101
FOR shift and go to state 102
IF shift and go to state 103
PRINT shift and go to state 104
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
ID shift and go to state 31
LRB shift and go to state 36
SUB shift and go to state 34
NOT shift and go to state 37
LCB shift and go to state 45
INTEGERNUMBER shift and go to state 38
FLOATNUMBER shift and go to state 39
TRUE shift and go to state 40
FALSE shift and go to state 41
! RETURN [ reduce using rule 30 (stmtlist -> .) ]
! WHILE [ reduce using rule 30 (stmtlist -> .) ]
! FOR [ reduce using rule 30 (stmtlist -> .) ]
! IF [ reduce using rule 30 (stmtlist -> .) ]
! PRINT [ reduce using rule 30 (stmtlist -> .) ]
! ID [ reduce using rule 30 (stmtlist -> .) ]
! LRB [ reduce using rule 30 (stmtlist -> .) ]
! SUB [ reduce using rule 30 (stmtlist -> .) ]
! NOT [ reduce using rule 30 (stmtlist -> .) ]
! LCB [ reduce using rule 30 (stmtlist -> .) ]
! INTEGERNUMBER [ reduce using rule 30 (stmtlist -> .) ]
! FLOATNUMBER [ reduce using rule 30 (stmtlist -> .) ]
! TRUE [ reduce using rule 30 (stmtlist -> .) ]
! FALSE [ reduce using rule 30 (stmtlist -> .) ]
stmtlist shift and go to state 96
vardec shift and go to state 97
stmt shift and go to state 98
type shift and go to state 72
exp shift and go to state 100
block shift and go to state 105
lvalue shift and go to state 33
const shift and go to state 35
这里是所有作品的列表:
program → declist main ( ) block
declist → dec | declist dec |
dec → vardec | funcdec
type → int | float | bool
iddec → id | id [ exp ] | id=exp
idlist → iddec | idlist , iddec
vardec → type idlist ;
funcdec → type id (paramdecs) block | void id (paramdecs) block
paramdecs → paramdecslist |
paramdecslist → paramdec | paramdecslist , paramdec
paramdec → type id | type id []
Precedencevarlist → vardec | varlist vardec |
block → { varlist stmtlist }
stmtlist → stmt | stmlist stmt |
lvalue → id | id [exp]
stmt → return exp ; | exp ;| block |
while (exp) stmt |
for(exp ; exp ; exp) stmt |
if (exp) stmt elseiflist | if (exp) stmt elseiflist else stmt |
print ( id) ;
elseiflist → elif (exp) stmt | elseiflist elif (exp) stmt |
exp → lvalue=exp | exp operator exp |exp relop exp|
const | lvalue | id(explist) | (exp) | id() | - exp | ! exp
operator → “||” | && | + | - | * | / | %
const → intnumber | floatnumber | true | false
relop → > | < | != | == | <= | >=
explist → exp | explist,exp
另一个问题是著名的悬垂 else,我将 ('nonassoc', 'IFP'), ('left', 'ELSE' , 'ELIF')
添加到优先元组并以这种方式更改语法:
def p_stmt_5(self, p):
"""stmt : IF LRB exp RRB stmt elseiflist %prec IFP """
print("""stmt : IF LRB exp RRB stmt elseiflist """)
def p_stmt_6(self, p):
"""stmt : IF LRB exp RRB stmt elseiflist ELSE stmt"""
print("""stmt : IF LRB exp RRB stmt elseiflist else stmt """)
但这并没有让它消失。下面是发生 shift/reduce 冲突的状态。
状态 130
(37) stmt -> IF LRB exp RRB stmt . elseiflist
(38) stmt -> IF LRB exp RRB stmt . elseiflist ELSE stmt
(41) elseiflist -> . ELIF LRB exp RRB stmt
(42) elseiflist -> . elseiflist ELIF LRB exp RRB stmt
(43) elseiflist -> .
! shift/reduce conflict for ELIF resolved as shift
ELIF shift and go to state 134
RCB reduce using rule 43 (elseiflist -> .)
RETURN reduce using rule 43 (elseiflist -> .)
WHILE reduce using rule 43 (elseiflist -> .)
FOR reduce using rule 43 (elseiflist -> .)
IF reduce using rule 43 (elseiflist -> .)
PRINT reduce using rule 43 (elseiflist -> .)
ID reduce using rule 43 (elseiflist -> .)
LRB reduce using rule 43 (elseiflist -> .)
SUB reduce using rule 43 (elseiflist -> .)
NOT reduce using rule 43 (elseiflist -> .)
LCB reduce using rule 43 (elseiflist -> .)
INTEGERNUMBER reduce using rule 43 (elseiflist -> .)
FLOATNUMBER reduce using rule 43 (elseiflist -> .)
TRUE reduce using rule 43 (elseiflist -> .)
FALSE reduce using rule 43 (elseiflist -> .)
ELSE reduce using rule 43 (elseiflist -> .)
! ELIF [ reduce using rule 43 (elseiflist -> .) ]
elseiflist shift and go to state 133
最后还有两个有 shift/reduce 错误的状态,我在下面列出:
state 45
(27) block -> LCB . varlist stmtlist RCB
(24) varlist -> . vardec
(25) varlist -> . varlist vardec
(26) varlist -> .
(15) vardec -> . type idlist SEMICOLON
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
! shift/reduce conflict for INTEGER resolved as shift
! shift/reduce conflict for FLOAT resolved as shift
! shift/reduce conflict for BOOLEAN resolved as shift
RETURN reduce using rule 26 (varlist -> .)
WHILE reduce using rule 26 (varlist -> .)
FOR reduce using rule 26 (varlist -> .)
IF reduce using rule 26 (varlist -> .)
PRINT reduce using rule 26 (varlist -> .)
ID reduce using rule 26 (varlist -> .)
LRB reduce using rule 26 (varlist -> .)
SUB reduce using rule 26 (varlist -> .)
NOT reduce using rule 26 (varlist -> .)
LCB reduce using rule 26 (varlist -> .)
INTEGERNUMBER reduce using rule 26 (varlist -> .)
FLOATNUMBER reduce using rule 26 (varlist -> .)
TRUE reduce using rule 26 (varlist -> .)
FALSE reduce using rule 26 (varlist -> .)
RCB reduce using rule 26 (varlist -> .)
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
! INTEGER [ reduce using rule 26 (varlist -> .) ]
! FLOAT [ reduce using rule 26 (varlist -> .) ]
! BOOLEAN [ reduce using rule 26 (varlist -> .) ]
varlist shift and go to state 70
vardec shift and go to state 71
type shift and go to state 72
并且:
state 0
(0) S' -> . program
(1) program -> . declist MAIN LRB RRB block
(2) declist -> . dec
(3) declist -> . declist dec
(4) declist -> .
(5) dec -> . vardec
(6) dec -> . funcdec
(15) vardec -> . type idlist SEMICOLON
(16) funcdec -> . type ID LRB paramdecs RRB block
(17) funcdec -> . VOID ID LRB paramdecs RRB block
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
! shift/reduce conflict for VOID resolved as shift
! shift/reduce conflict for INTEGER resolved as shift
! shift/reduce conflict for FLOAT resolved as shift
! shift/reduce conflict for BOOLEAN resolved as shift
MAIN reduce using rule 4 (declist -> .)
VOID shift and go to state 7
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
! VOID [ reduce using rule 4 (declist -> .) ]
! INTEGER [ reduce using rule 4 (declist -> .) ]
! FLOAT [ reduce using rule 4 (declist -> .) ]
! BOOLEAN [ reduce using rule 4 (declist -> .) ]
program shift and go to state 1
declist shift and go to state 2
dec shift and go to state 3
vardec shift and go to state 4
funcdec shift and go to state 5
type shift and go to state 6
在此先感谢您。
这里实际上有两个有些相关的问题,都与递归产生式中重复的基本案例引起的歧义有关:
1。 stmtlist
中的歧义
首先,正如您所说,stmtlist
存在问题。 stmtlist
的语法是:
stmtlist → stmt | stmlist stmt |
有两个基本情况:stmtlist → stmt
和 stmtlist →
。这种重复意味着可以用两种方式解析单个 stmt
:
stmtlist → stmt
stmtlist → stmtlist stmt → stmt
语法歧义总是表现为冲突。消除冲突,消除歧义。如果您希望 stmtlist
可能为空,请使用:
stmtlist → stmlist stmt |
如果你想坚持 stmtlist
至少包含一个 stmt
,请使用:
stmtlist → stmlist stmt | stmt
最重要的是,尝试理解上述建议的逻辑。
此外,您允许 stmt
为空。很明显,这将导致 stmtlist
中的歧义,因为不可能知道列表中有多少个空的 stmt
。可能是 3;可能是 42;可能是八百万。空是看不见的。
stmt
的潜在虚无也与那些以 stmt
结尾的复合语句产生歧义,例如 "while" '(' exp ')' stmt
。如果 stmt
什么都不是,那么
while (x) while(y) c;
可以是两个语句:while(x)
有一个空的重复语句,然后 while(y)
有一个在 c;
上的循环。或者它可能具有(可能是预期的)while(x)
循环的含义,其重复语句是嵌套的 while(y) c;
。我建议没有人会期待第一种解释,而且语法不应该允许它。如果你想要一个空的 while
目标,你可以使用 ;
作为重复语句,而不是什么都没有。
我确定您并没有打算让 stmt
什么都不是。允许将空语句写成 ;
(即空后跟分号)很有意义,但这显然是一种不同的语法。 (在 {
…}
中,您可能不想允许任何内容,而不是坚持使用分号。为此,您需要一个空的 stmtlist
,而不是一个空的 stmt
。 )
2。其他悬挂:实际上是 elseiflist
中的歧义
我认为这是您正在使用的语法:
(37) stmt -> "if" '(' exp ')' stmt elseiflist %prec IFP
(38) stmt -> "if" '(' exp ')' stmt elseiflist "else" stmt
(41) elseiflist -> "elif" '(' exp ')' stmt
(42) elseiflist -> elseiflist "elif" '(' exp ')' stmt
(43) elseiflist ->
正如 stmtlist
产生式一样,elseiflist
是具有两个基本情况的递归产生式,其中一个是冗余的。同样,有必要确定 elseiflist
是否真的可以为空(提示:可以),然后删除一个或另一个基本情况以避免解析不明确。
话虽如此,我认为这不是编写 if 语句语法的最佳方式;它构建的解析树可能并不像您预期的那样。但我想它会起作用。
我有很多冲突,其中大部分是由于运算符和关系运算符具有不同的优先级。但我仍然面临一些我真的不知道如何解决的冲突。其中一些在下面。我怀疑也许我应该对 stmtlist
进行 epsilon 消除,但老实说我不确定。
状态 70:
state 70
(27) block -> LCB varlist . stmtlist RCB
(25) varlist -> varlist . vardec
(28) stmtlist -> . stmt
(29) stmtlist -> . stmtlist stmt
(30) stmtlist -> .
(15) vardec -> . type idlist SEMICOLON
(33) stmt -> . RETURN exp SEMICOLON
(34) stmt -> . exp SEMICOLON
(35) stmt -> . WHILE LRB exp RRB stmt
(36) stmt -> . FOR LRB exp SEMICOLON exp SEMICOLON exp RRB stmt
(37) stmt -> . IF LRB exp RRB stmt elseiflist
(38) stmt -> . IF LRB exp RRB stmt elseiflist ELSE stmt
(39) stmt -> . PRINT LRB ID RRB SEMICOLON
(40) stmt -> . block
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
(44) exp -> . lvalue ASSIGN exp
(45) exp -> . exp SUM exp
(46) exp -> . exp MUL exp
(47) exp -> . exp SUB exp
(48) exp -> . exp DIV exp
(49) exp -> . exp MOD exp
(50) exp -> . exp AND exp
(51) exp -> . exp OR exp
(52) exp -> . exp LT exp
(53) exp -> . exp LE exp
(54) exp -> . exp GT exp
(55) exp -> . exp GE exp
(56) exp -> . exp NE exp
(57) exp -> . exp EQ exp
(58) exp -> . const
(59) exp -> . lvalue
(60) exp -> . ID LRB explist RRB
(61) exp -> . LRB exp RRB
(62) exp -> . ID LRB RRB
(63) exp -> . SUB exp
(64) exp -> . NOT exp
(27) block -> . LCB varlist stmtlist RCB
(31) lvalue -> . ID
(32) lvalue -> . ID LSB exp RSB
(72) const -> . INTEGERNUMBER
(73) const -> . FLOATNUMBER
(74) const -> . TRUE
(75) const -> . FALSE
! shift/reduce conflict for RETURN resolved as shift
! shift/reduce conflict for WHILE resolved as shift
! shift/reduce conflict for FOR resolved as shift
! shift/reduce conflict for IF resolved as shift
! shift/reduce conflict for PRINT resolved as shift
! shift/reduce conflict for ID resolved as shift
! shift/reduce conflict for LRB resolved as shift
! shift/reduce conflict for SUB resolved as shift
! shift/reduce conflict for NOT resolved as shift
! shift/reduce conflict for LCB resolved as shift
! shift/reduce conflict for INTEGERNUMBER resolved as shift
! shift/reduce conflict for FLOATNUMBER resolved as shift
! shift/reduce conflict for TRUE resolved as shift
! shift/reduce conflict for FALSE resolved as shift
RCB reduce using rule 30 (stmtlist -> .)
RETURN shift and go to state 99
WHILE shift and go to state 101
FOR shift and go to state 102
IF shift and go to state 103
PRINT shift and go to state 104
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
ID shift and go to state 31
LRB shift and go to state 36
SUB shift and go to state 34
NOT shift and go to state 37
LCB shift and go to state 45
INTEGERNUMBER shift and go to state 38
FLOATNUMBER shift and go to state 39
TRUE shift and go to state 40
FALSE shift and go to state 41
! RETURN [ reduce using rule 30 (stmtlist -> .) ]
! WHILE [ reduce using rule 30 (stmtlist -> .) ]
! FOR [ reduce using rule 30 (stmtlist -> .) ]
! IF [ reduce using rule 30 (stmtlist -> .) ]
! PRINT [ reduce using rule 30 (stmtlist -> .) ]
! ID [ reduce using rule 30 (stmtlist -> .) ]
! LRB [ reduce using rule 30 (stmtlist -> .) ]
! SUB [ reduce using rule 30 (stmtlist -> .) ]
! NOT [ reduce using rule 30 (stmtlist -> .) ]
! LCB [ reduce using rule 30 (stmtlist -> .) ]
! INTEGERNUMBER [ reduce using rule 30 (stmtlist -> .) ]
! FLOATNUMBER [ reduce using rule 30 (stmtlist -> .) ]
! TRUE [ reduce using rule 30 (stmtlist -> .) ]
! FALSE [ reduce using rule 30 (stmtlist -> .) ]
stmtlist shift and go to state 96
vardec shift and go to state 97
stmt shift and go to state 98
type shift and go to state 72
exp shift and go to state 100
block shift and go to state 105
lvalue shift and go to state 33
const shift and go to state 35
这里是所有作品的列表:
program → declist main ( ) block
declist → dec | declist dec |
dec → vardec | funcdec
type → int | float | bool
iddec → id | id [ exp ] | id=exp
idlist → iddec | idlist , iddec
vardec → type idlist ;
funcdec → type id (paramdecs) block | void id (paramdecs) block
paramdecs → paramdecslist |
paramdecslist → paramdec | paramdecslist , paramdec
paramdec → type id | type id []
Precedencevarlist → vardec | varlist vardec |
block → { varlist stmtlist }
stmtlist → stmt | stmlist stmt |
lvalue → id | id [exp]
stmt → return exp ; | exp ;| block |
while (exp) stmt |
for(exp ; exp ; exp) stmt |
if (exp) stmt elseiflist | if (exp) stmt elseiflist else stmt |
print ( id) ;
elseiflist → elif (exp) stmt | elseiflist elif (exp) stmt |
exp → lvalue=exp | exp operator exp |exp relop exp|
const | lvalue | id(explist) | (exp) | id() | - exp | ! exp
operator → “||” | && | + | - | * | / | %
const → intnumber | floatnumber | true | false
relop → > | < | != | == | <= | >=
explist → exp | explist,exp
另一个问题是著名的悬垂 else,我将 ('nonassoc', 'IFP'), ('left', 'ELSE' , 'ELIF')
添加到优先元组并以这种方式更改语法:
def p_stmt_5(self, p):
"""stmt : IF LRB exp RRB stmt elseiflist %prec IFP """
print("""stmt : IF LRB exp RRB stmt elseiflist """)
def p_stmt_6(self, p):
"""stmt : IF LRB exp RRB stmt elseiflist ELSE stmt"""
print("""stmt : IF LRB exp RRB stmt elseiflist else stmt """)
但这并没有让它消失。下面是发生 shift/reduce 冲突的状态。
状态 130
(37) stmt -> IF LRB exp RRB stmt . elseiflist
(38) stmt -> IF LRB exp RRB stmt . elseiflist ELSE stmt
(41) elseiflist -> . ELIF LRB exp RRB stmt
(42) elseiflist -> . elseiflist ELIF LRB exp RRB stmt
(43) elseiflist -> .
! shift/reduce conflict for ELIF resolved as shift
ELIF shift and go to state 134
RCB reduce using rule 43 (elseiflist -> .)
RETURN reduce using rule 43 (elseiflist -> .)
WHILE reduce using rule 43 (elseiflist -> .)
FOR reduce using rule 43 (elseiflist -> .)
IF reduce using rule 43 (elseiflist -> .)
PRINT reduce using rule 43 (elseiflist -> .)
ID reduce using rule 43 (elseiflist -> .)
LRB reduce using rule 43 (elseiflist -> .)
SUB reduce using rule 43 (elseiflist -> .)
NOT reduce using rule 43 (elseiflist -> .)
LCB reduce using rule 43 (elseiflist -> .)
INTEGERNUMBER reduce using rule 43 (elseiflist -> .)
FLOATNUMBER reduce using rule 43 (elseiflist -> .)
TRUE reduce using rule 43 (elseiflist -> .)
FALSE reduce using rule 43 (elseiflist -> .)
ELSE reduce using rule 43 (elseiflist -> .)
! ELIF [ reduce using rule 43 (elseiflist -> .) ]
elseiflist shift and go to state 133
最后还有两个有 shift/reduce 错误的状态,我在下面列出:
state 45
(27) block -> LCB . varlist stmtlist RCB
(24) varlist -> . vardec
(25) varlist -> . varlist vardec
(26) varlist -> .
(15) vardec -> . type idlist SEMICOLON
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
! shift/reduce conflict for INTEGER resolved as shift
! shift/reduce conflict for FLOAT resolved as shift
! shift/reduce conflict for BOOLEAN resolved as shift
RETURN reduce using rule 26 (varlist -> .)
WHILE reduce using rule 26 (varlist -> .)
FOR reduce using rule 26 (varlist -> .)
IF reduce using rule 26 (varlist -> .)
PRINT reduce using rule 26 (varlist -> .)
ID reduce using rule 26 (varlist -> .)
LRB reduce using rule 26 (varlist -> .)
SUB reduce using rule 26 (varlist -> .)
NOT reduce using rule 26 (varlist -> .)
LCB reduce using rule 26 (varlist -> .)
INTEGERNUMBER reduce using rule 26 (varlist -> .)
FLOATNUMBER reduce using rule 26 (varlist -> .)
TRUE reduce using rule 26 (varlist -> .)
FALSE reduce using rule 26 (varlist -> .)
RCB reduce using rule 26 (varlist -> .)
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
! INTEGER [ reduce using rule 26 (varlist -> .) ]
! FLOAT [ reduce using rule 26 (varlist -> .) ]
! BOOLEAN [ reduce using rule 26 (varlist -> .) ]
varlist shift and go to state 70
vardec shift and go to state 71
type shift and go to state 72
并且:
state 0
(0) S' -> . program
(1) program -> . declist MAIN LRB RRB block
(2) declist -> . dec
(3) declist -> . declist dec
(4) declist -> .
(5) dec -> . vardec
(6) dec -> . funcdec
(15) vardec -> . type idlist SEMICOLON
(16) funcdec -> . type ID LRB paramdecs RRB block
(17) funcdec -> . VOID ID LRB paramdecs RRB block
(7) type -> . INTEGER
(8) type -> . FLOAT
(9) type -> . BOOLEAN
! shift/reduce conflict for VOID resolved as shift
! shift/reduce conflict for INTEGER resolved as shift
! shift/reduce conflict for FLOAT resolved as shift
! shift/reduce conflict for BOOLEAN resolved as shift
MAIN reduce using rule 4 (declist -> .)
VOID shift and go to state 7
INTEGER shift and go to state 8
FLOAT shift and go to state 9
BOOLEAN shift and go to state 10
! VOID [ reduce using rule 4 (declist -> .) ]
! INTEGER [ reduce using rule 4 (declist -> .) ]
! FLOAT [ reduce using rule 4 (declist -> .) ]
! BOOLEAN [ reduce using rule 4 (declist -> .) ]
program shift and go to state 1
declist shift and go to state 2
dec shift and go to state 3
vardec shift and go to state 4
funcdec shift and go to state 5
type shift and go to state 6
在此先感谢您。
这里实际上有两个有些相关的问题,都与递归产生式中重复的基本案例引起的歧义有关:
1。 stmtlist
中的歧义
首先,正如您所说,stmtlist
存在问题。 stmtlist
的语法是:
stmtlist → stmt | stmlist stmt |
有两个基本情况:stmtlist → stmt
和 stmtlist →
。这种重复意味着可以用两种方式解析单个 stmt
:
stmtlist → stmt
stmtlist → stmtlist stmt → stmt
语法歧义总是表现为冲突。消除冲突,消除歧义。如果您希望 stmtlist
可能为空,请使用:
stmtlist → stmlist stmt |
如果你想坚持 stmtlist
至少包含一个 stmt
,请使用:
stmtlist → stmlist stmt | stmt
最重要的是,尝试理解上述建议的逻辑。
此外,您允许 stmt
为空。很明显,这将导致 stmtlist
中的歧义,因为不可能知道列表中有多少个空的 stmt
。可能是 3;可能是 42;可能是八百万。空是看不见的。
stmt
的潜在虚无也与那些以 stmt
结尾的复合语句产生歧义,例如 "while" '(' exp ')' stmt
。如果 stmt
什么都不是,那么
while (x) while(y) c;
可以是两个语句:while(x)
有一个空的重复语句,然后 while(y)
有一个在 c;
上的循环。或者它可能具有(可能是预期的)while(x)
循环的含义,其重复语句是嵌套的 while(y) c;
。我建议没有人会期待第一种解释,而且语法不应该允许它。如果你想要一个空的 while
目标,你可以使用 ;
作为重复语句,而不是什么都没有。
我确定您并没有打算让 stmt
什么都不是。允许将空语句写成 ;
(即空后跟分号)很有意义,但这显然是一种不同的语法。 (在 {
…}
中,您可能不想允许任何内容,而不是坚持使用分号。为此,您需要一个空的 stmtlist
,而不是一个空的 stmt
。 )
2。其他悬挂:实际上是 elseiflist
中的歧义
我认为这是您正在使用的语法:
(37) stmt -> "if" '(' exp ')' stmt elseiflist %prec IFP
(38) stmt -> "if" '(' exp ')' stmt elseiflist "else" stmt
(41) elseiflist -> "elif" '(' exp ')' stmt
(42) elseiflist -> elseiflist "elif" '(' exp ')' stmt
(43) elseiflist ->
正如 stmtlist
产生式一样,elseiflist
是具有两个基本情况的递归产生式,其中一个是冗余的。同样,有必要确定 elseiflist
是否真的可以为空(提示:可以),然后删除一个或另一个基本情况以避免解析不明确。
话虽如此,我认为这不是编写 if 语句语法的最佳方式;它构建的解析树可能并不像您预期的那样。但我想它会起作用。