Parsing 在忽略其他空格的情况下,如何在特定规则中获取强制空格?

Parsing 在忽略其他空格的情况下,如何在特定规则中获取强制空格?,parsing,whitespace,antlr,antlr4,grammar,Parsing,Whitespace,Antlr,Antlr4,Grammar,我语法的相关部分结构如下: someRule:subrule1 | WS-sign=(“+”|“-”)subrule2;//此处需要空白 // ... 等 WS:[\t\r\n]+->频道(隐藏);//空白通常被忽略 我想忽略空白,但需要一个特定的规则。我很确定在以前的ANTLR版本中有一种方法可以做到这一点(尽管我不记得很清楚,我认为有一种语法允许在特定规则中不隐藏它们)。我不知道如何在ANTLR4中实现它,当然也不知道是否可以在不使用特定于语言的操作的情况下实现它 我曾考虑以某种方式将WS

我语法的相关部分结构如下:

someRule:subrule1 | WS-sign=(“+”|“-”)subrule2;//此处需要空白
// ... 等
WS:[\t\r\n]+->频道(隐藏);//空白通常被忽略
我想忽略空白,但需要一个特定的规则。我很确定在以前的ANTLR版本中有一种方法可以做到这一点(尽管我不记得很清楚,我认为有一种语法允许在特定规则中不隐藏它们)。我不知道如何在ANTLR4中实现它,当然也不知道是否可以在不使用特定于语言的操作的情况下实现它

我曾考虑以某种方式将WS作为解析器规则,但我认为这不是正确的方法…
(很明显,我不想把WS?放在语法中的任何地方)

是否有(最好是独立于语言的)方法来(a)确保特定点有空格,或(b)确保特定点上的两端不“接触”该通道,或(c)根据它出现在哪个规则中有选择地选择WS通道(默认或隐藏)?

我猜(c)是不可能的,(a | b)需要依赖于语言的操作,除非我遗漏了什么?

我不相信有任何方法可以让解析器规则评估
隐藏通道(或除0以外的任何通道)上的标记。也许我遗漏了什么,但我找不到

我无法从您的摘录中回答的问题是,如果您的签名之前没有WS,是否还有另一个解析器规则应该匹配。这有很大的不同

我倾向于认为一个成功的语法会产生一个解析树,它代表了解释输入流的正确方式。嗯,太多的人试图将“所有规则”编码到语法中,从而使语法复杂化。如果您有一个解释输入的唯一方法的精确树(无论它是否“无错误”),那么您可以编写一个侦听器(可能是访问者)来访问该树并对其他规则进行编辑(例如“符号”前面应该有空格)

这就完成了两件事:

  • 使语法更简单
  • 允许您在错误消息中非常具体
ANTLR对于错误消息的处理非常好,因为它拥有什么样的信息,但是“预期的WS,但看到的是“+”,并不像“符号必须跟在空白后面”那样是一条好的错误消息

记住这一点,您可以访问侦听器中的隐藏通道

首先,您需要使令牌流在侦听器中可用:

类TestListener扩展了TestBaseListener{ 缓冲的TokenStream令牌; 公共TestListener(BufferedTokenStream令牌){ this.tokens=代币; } // ... }
并将其传递给侦听器的构造函数:

CommonTokenStream令牌=新的CommonTokenStream(lexer);
TestListener=新的TestListener(令牌);
然后,在
enter*
方法中,对于需要将其添加到的任何规则,都可以执行以下操作:

const int HIDDEN=1;
@凌驾
public void enterAddSub(TxlParser.AddSubContext ctx){
令牌op=ctx.op;
int opIndex=op.getTokenIndex();
List hiddenChannel=tokens.getHiddenTokensToLeft(opIndex,隐藏);
if(hiddenChannel!=null){
令牌ws=hiddenChannel.get(0);
如果(ws!=null){
System.out.println(“找到的Ws(“+Ws.getText()+”);
}
}否则{
System.out.println(“操作符左侧没有WS”);
//您的代码在此添加错误
}
}
作为参考,这是我与
AddSub一起使用的规则

expr:
    expr (MULT | DIV) expr                          # MulDiv
    | lExpr = expr op = (PLUS | MINUS) rExpr = expr # AddSub
    // ...
    ;
如果我使用输入
a=x+y
运行此操作,我会得到:

There was no WS to the left of the operator
但是输入
a=x+y
给了我:

Found Ws ( )