使用HIDDEN通道的ANTLR4会导致错误,而使用跳过则不会

时间:2017-02-15 15:14:41

标签: antlr grammar antlr4

在我的语法中我使用:

WS: [ \t\r\n]+ -> skip;

当我将其更改为使用HIDDEN频道时:

WS: [ \t\r\n]+ -> channel(HIDDEN);

我收到错误(无关输入''...)我在使用'skip'时没有收到。 我想,如果涉及传递给解析器的内容,那么跳转和发送到通道并没有什么不同。

您可以在下面找到执行解析器的代码摘录:

    CharStream charStream = new ANTLRInputStream(formulaString);
    FormulaLexer lexer = new FormulaLexer(charStream);
    BufferedTokenStream tokens = new BufferedTokenStream(lexer);
    FormulaParser parser = new FormulaParser(tokens);
    ParseTree tree = parser.startRule();

    StartRuleVisitor startRuleVisitor = new StartRuleVisitor();
    startRuleVisitor.visit(tree);

    VariableVisitor variableVisitor = new VariableVisitor(tokens);
    variableVisitor.visit(tree);

语法本身:

grammar Formula;


startRule
   : variable RELATION_OPERATOR integer
   ;

integer
   : DIGIT+
   ;

identifier
   : (LETTER | DIGIT) ( DIGIT | LETTER | '_' | '.')+
   ;

tableId
   : 'T_' (identifier | WILDCARD)
   ;

rowId
   : 'R_' (identifier | WILDCARD)
   ;

columnId
   : 'C_' (identifier | WILDCARD)
   ;

sheetId
   : 'S_' (identifier | WILDCARD)
   ;

variable
   : L_CURLY_BRACKET cellIdComponent (COMMA cellIdComponent)+ R_CURLY_BRACKET
   ;

cellIdComponent
   : tableId | rowId | columnId | sheetId
   ;

COMMA
   : ','
   ;

RELATION_OPERATOR
   : EQ
   ;

WILDCARD
   : 'NNN'
   ;

L_CURLY_BRACKET
   : '{'
   ;

R_CURLY_BRACKET
   : '}'
   ;


LETTER
   : ('a' .. 'z') | ('A' .. 'Z')
   ;

DIGIT
   : ('0' .. '9')
   ;


EQ
   : '='
   | 'EQ' | 'eq'
   ;


WS
   : [ \t\r\n]+ -> channel(HIDDEN)
   ;

字符串我尝试解析:

{T_C 00.01, R_010,   C_010} = 1

使用通道(HIDDEN)得到的输出:

line 1:4 extraneous input ' ' expecting {'_', '.', LETTER, DIGIT}
line 1:11 extraneous input ' ' expecting {'T_', 'R_', 'C_', 'S_'}
line 1:18 extraneous input '   ' expecting {'T_', 'R_', 'C_', 'S_'}
line 1:27 extraneous input ' ' expecting RELATION_OPERATOR
line 1:29 extraneous input ' ' expecting DIGIT

但如果我将频道(HIDDEN)更改为“跳过”,则没有错误。

更重要的是,我观察到,对于比这更复杂的语法,如果我使用频道(HIDDEN),那么“在输入时没有可行的选择...”,并且再次错误消失为“跳过”。

你知道它可能是什么原因吗?

1 个答案:

答案 0 :(得分:1)

您应该使用CommonTokenStream代替BufferedTokenStream。请参阅BufferedTokenStream description on github

  

此令牌流忽略{@link Token#getChannel}的值。如果你的   解析器需要令牌流过滤器标记仅适用于特定的标记   频道,例如{@link Token#DEFAULT_CHANNEL}或   {@link Token#HIDDEN_CHANNEL},使用过滤令牌流等   {@link CommonTokenStream}。