0

我想实现一个简单的Java像sablecc语言解析器,虽然我实施ifwhileblock报表时不断运行到shift-reduce/reduce-reduce问题。创建移降低/减少,减少无关文法

举例来说,我已经考虑了以下几点:

stmts = stmt*;

stmt = if_stmt | block_stmt | while_stmt;

block_stmt = { stmts } | ;;

while_stmt = while(predicate){stmts} | while(predicate);

这个语法,将,例如,导致问题,当你有形式

while (true) ; 

的东西解析器将无法知道是否减少只是;(来自block_stmt)或完整的while (true);(来自while_stmt)。

我一直在阅读各地的原因shift-reduce/reduce-reduce问题,我想我理解他们。但有一点是要知道是什么引起了他们,而另一个完全不同的是知道如何构建语法,以避免它们。我尝试过以不同的方式实现语法,然而我最终遇到了问题。

我想,不是试图从一个特定的问题运行,而是必须采取一种模式来避免这种问题?我相信我的方式来解决问题必须是完全错误的:(

任何资源如何从头开始构建一个语法,而不会陷入所有这些陷阱?在这个问题上的资源往往要么很容易(说明明显if then else问题),或者完全标记语法,这是一种令人费解的。

回答

2

的问题是,指定你的语法使得例如分号可以解释无论是作为while_stmt的分号或block_stmt的...没有遗憾不是,但不知何故,语法是多余的,因为{stmt}在RHS上出现两次。通常你会做

stmts ::= stmt | stmts stmt 
block_stmt ::= { stmts } 
stmt ::= ... | block_stmt | ;  // empty 
while_stmt ::= while ... stmt