我有一个解析器,其布局类似于(虽然不完全一样):
compilationUnit: statement* EOF;
methodBody: statement*;
ifBlock: IF '(' expression ')' '{' statement* '}' ;
statement: methodBody | ifBlock | returnStatement | ... ;
此解析器工作正常,我可以使用它。但是,它具有returnStatement
会解析的缺陷,即使它不在方法主体中也是如此。理想情况下,我可以对其进行设置,以使returnStatement
仅在其下一个父级为statement
时才符合methodBody
规则。有办法吗?
答案 0 :(得分:0)
您必须将methodBody内的语句与该作用域外的语句区分开。理想情况下,您将有两种不同的作品。像这样:
compilationUnit: member* EOF;
member: method | class | ... ;
method: methodName '(' parameters ')' '{' methodBody '}' ;
methodBody: statement*;
statement: methodBody | ifBlock | returnStatement | ... ;
ifBlock: IF '(' expression ')' '{' statement* '}' ;
答案 1 :(得分:0)
您正在尝试以错误的级别解决此问题。它不应该在语法级别进行处理,而应在以下语义阶段(用于查找逻辑/语义错误,而不是语法错误的语法阶段,解析器要处理的内容)进行处理。您可以在C grammar中看到相同的方法。 statement
规则引用jumpStatement
规则,该规则依次与return语句匹配(除其他外)。
处理此类语义错误也可以提供更好的错误消息。代替“没有可行的替代项”,您可以打印一个错误,指出“仅在函数体中允许返回”或类似的错误。为此,请检查生成的语法分析树,搜索return语句,并检查该子树的父上下文以了解其是否有效。