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

Suz*_*ioc 9 java regex antlr lexer antlr4

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

我的语法如下:

grammar Anytext;

line :
    comment;

comment : '#' anytext;

anytext: ANY*;

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

ANY : .;
Run Code Online (Sandbox Code Playgroud)

我的代码如下:

    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
Run Code Online (Sandbox Code Playgroud)

输出如下:

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

如果我改变ANY规则

ANY : [ \t\r\n.];
Run Code Online (Sandbox Code Playgroud)

它根本不再识别任何符号.

UPDATE1

我最后没有终点字符.

更新2

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

但问题仍然存在.

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

假设我有表格数据,我不想处理某些字段而忽略其他字段.如果我有anytext统治权,我会写

infoline :
    ( codepoint WS 'field1' WS field1Value ) |
    ( codepoint WS 'field2' WS field2Value ) |
    ( codepoint WS anytext );
Run Code Online (Sandbox Code Playgroud)

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

如何实现这种方法?

Sam*_*ell 7

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

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

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

ANY : .;
Run Code Online (Sandbox Code Playgroud)

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

  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)

您当前的语法无法解析,因为规则中WS不允许使用令牌comment.如果你使用它,它会解析这个输入(但是当你扩展你的语法时可能会遇到问题):

// remember that '#' is its own token
anytext: (ANY | WS | '#')*;
Run Code Online (Sandbox Code Playgroud)

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

grammar Anytext;

line : COMMENT;

COMMENT : '#' ~[\r\n]*;

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

ANY : .;
Run Code Online (Sandbox Code Playgroud)

  • @SuzanCioc ANTLR从不为令牌分配多种类型.空格字符符合规则"WS"和"ANY".为了解决这种歧义,由于`WS`出现在语法中的'ANY`之前,因此令牌被赋予了`WS`类型.解析歧义并在解析器看到令牌之前分配令牌类型,因此解析器永远不会看到类型为"ANY"的空格字符令牌. (2认同)

hoa*_*oaz 1

对行注释使用以下规则:

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

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

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

LINE_COMMENT
    :   '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN)
    ;
Run Code Online (Sandbox Code Playgroud)