使用ANTLR匹配任意文本(符号和空格)?

时间:2013-05-11 11:24:56

标签: java regex antlr lexer antlr4

如何匹配ANTLRv4中的任何文本?我的意思是文本,这在语法写作时是未知的?

我的语法如下:

grammar Anytext;

line :
    comment;

comment : '#' anytext;

anytext: ANY*;

WS : [ \t\r\n]+;

ANY : .;

我的代码如下:

    String line = "# This_is_a_comment";

    ANTLRInputStream input = new ANTLRInputStream(line);

    AnytextLexer lexer = new AnytextLexer(input);

    CommonTokenStream tokens = new CommonTokenStream(lexer);

    AnytextParser parser = new AnytextParser(tokens);

    ParseTree tree = parser.comment();

    System.out.println(tree.toStringTree(parser)); // print LISP-style tree

输出如下:

line 1:1 extraneous input ' ' expecting {<EOF>, ANY}
(comment # (anytext   T h i s _ i s _ a _ c o m m e n t))

如果我更改ANY规则

ANY : [ \t\r\n.];

它会停止识别任何符号。

UPDATE1

我最后没有结束字符。

更新2

所以,我明白,因为词法分析器不能允许多个类,所以不可能将任何文本与词法分析器匹配。如果我为任何符号定义词法分析器规则,它将隐藏所有其他规则或不起作用。

但问题仍然存在。

如何匹配解析器级别的所有符号?

假设我有表格数据,我不想处理某些字段而忽略其他字段。如果我有anytext规则,我会写

infoline :
    ( codepoint WS 'field1' WS field1Value ) |
    ( codepoint WS 'field2' WS field2Value ) |
    ( codepoint WS anytext );

这里我解析行,如果第二列包含field1field2值,否则忽略行。

如何实现这种方法?

2 个答案:

答案 0 :(得分:7)

重要的是要记住,在解析器看到第一个令牌之前,ANTLR会将您的完整输入分解为令牌(至少它的行为方式如此)。您的词法分析器语法如下所示。

T__0 : '#'; // implicit token created due to the use of '#' in parser rule comment

WS : [ \t\r\n]+;

ANY : .;

对于您的输入,令牌如下:

  1. #(类型T__0
  2. [空格](类型WS
  3. T(类型ANY
  4. h(类型ANY
  5. i(类型ANY
  6. s(类型ANY
  7. _(类型ANY
  8. i(类型ANY
  9. s(类型ANY
  10. _(类型ANY
  11. a(类型ANY
  12. _(类型ANY
  13. c(类型ANY
  14. o(类型ANY
  15. m(类型ANY
  16. m(类型ANY
  17. e(类型ANY
  18. n(类型ANY
  19. t(类型ANY
  20. 您当前的语法无法解析,因为WS规则中不允许使用comment令牌。如果你使用它,它会解析这个输入(但是当你扩展你的语法时可能会遇到问题):

    // remember that '#' is its own token
    anytext: (ANY | WS | '#')*;
    

    你可以做的是将comment更改为词法分析器规则,它会消耗#字符以及后面的内容(在这种情况下,到行尾):

    grammar Anytext;
    
    line : COMMENT;
    
    COMMENT : '#' ~[\r\n]*;
    
    WS : [ \t\r\n]+;
    
    ANY : .;
    

答案 1 :(得分:1)

使用以下规则进行行注释:

LINE_COMMENT
    :   '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    ;

匹配'#'和任何符号,直到它到达行尾(unix / windows换行符)。

编辑280Z28:这是ANTLR 4语法中完全相同的规则:

LINE_COMMENT
    :   '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN)
    ;