ANTLR - 如何在 'for' 循环中跳过丢失的标记

ANTLR - how to skip missing tokens in a 'for' loop

我正在开发一种 'toy' 语言来学习 antlr。

我的 for 循环构造如下所示。

for(4,10){ //program expressions };

我有一个我认为可行的语法,但它有点难看。具体来说,我不确定我是否很好地处理了语义上不重要的标记。

例如,中间的逗号作为标记出现,但它对解析器并不重要,它只需要循环边界的 2 和 3。这意味着当我看到 loop 标记部分的 child() 元素时,我必须跳过不重要的元素。

如果您检查 ANTLR 查看器并查看解析树,您可能会看得最清楚。红色箭头指向我认为多余的token。

感觉我应该比现在更多地使用 skip() 功能,但我不知道如何在这个级别插入标记的语法。

loop: 'for(' foridxitem ',' foridxitem '){' (programexpression)+ '}'; foridxitem: NUM #ForIndexNumÌ | var #ForIndexVar;

简短的回答是 Antlr 会生成一个解析树,因此在遍历树时总会有需要跳过或以其他方式忽略的问题。

更长的答案是,在词法分析器中跳过 cruft 和生成语法价值有限的标记之间存在紧张关系,而这些标记对于编写明确的规则仍然是必需的。

例如,您将 for( 确定为跳过的候选者,但在语法上可能是必需的。相反,参数逗号可能真的没有句法意义。因此,您可以通过这种方式在词法分析器(和解析器)中清理它:

FOR: 'for(' -> pushMode(params) ;
ENDLOOP: '}' ;
WS: .... -> skip() ;

mode params;
NUM: .... ;
VAR: .... ;
COMMA: ',' -> skip() ;
ENDPARAMS: '){' -> skip(), popMode() ;
P_WS: .... -> skip() ;

您的 parer 规则将变为

loop: FOR foridxitem* programexpression+ ENDLOOP ;
foridxitem: NUM | VAR ;
programexpression: .... ;

这应该会稍微清理一下树。