最近需要给REVOKE语句增加一个新的语法形式,原来的语法形式如下:
RevokeStmt: REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_cascade_restrict opt_revoke_grant_option: GRANT OPTION FOR | /*EMPTY*/ |
原计划按如下形式增加新的语法形式:
RevokeStmt: REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_cascade_restrict |REVOKE privileges2 FROM grantee_list opt_revoke_grant_option: GRANT OPTION FOR | /*EMPTY*/ |
通过bison编译,发现移进/规约冲突(SHIFT/REDUCT CONFLICT),查看output文件如下:
State 49 conflicts: 6 shift/reduce |
查看State 49如下:
state 49 1386 RevokeStmt: REVOKE . opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_cascade_restrict 1387 | REVOKE . privileges2 FROM grantee_list opt_grant_admin_option …… EXECUTE shift, and go to state 572 GRANT shift, and go to state 573 INSERT shift, and go to state 574 $default reduce using rule 1433 (opt_revoke_grant_option) …… |
由于opt_revoke_grant_option可以为空(EMPTY),则在EMPTY时,既可以采用规则1386对opt_revoke_grant_option进行规约(见红色字体),也可以采用规则1387移进到privileges2。
通过增加一个新的规则privileges_and_grantee来解决该问题:
RevokeStmt: REVOKE opt_revoke_grant_option privileges_and_grantee privileges_and_grantee: privileges ON privilege_target FROM grantee_list opt_cascade_restrict |privileges2 FROM grantee_list |
上面的修改会改变语法形态,由于opt_revoke_grant_option不一定是EMPTY,还可能是GRANTOPTION FOR,所以,第二条语法规则会增加如下语法形态:
REVOKE GRANT OPTION FOR privileges2 FROM grantee_list |
虽然可以通过判断opt_revoke_grant_option是否为空在语义分析时来报错,但语法形态不符合我们的本意。
拆分语法规则:
http://blog.csdn.net/shujiezhang
另外可以通过拆分语法规则的方式,来解决该问题,可以将opt_revoke_grant_option语法规则拆分掉,那么在privileges之前就不再产生规约,从而屏蔽掉移进规约冲突。
增加一个新的语法规则,revoke_privilege来取代原有的移进规约冲突的位置:
RevokeStmt: REVOKE revoke_privileges ON privilege_target FROM grantee_list opt_cascade_restrict |REVOKE revoke_privileges FROM grantee_list revoke_privileges: privileges |GRANT OPTION FOR privileges |privileges2 |