9

如何匹配 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.];

它根本停止识别任何符号。

更新1

我最后没有结束行字符。

更新 2

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

但问题仍然存在。

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

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

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

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

如何实现这种方法?

4

2 回答 2

9

重要的是要记住,在解析器看到第一个标记之前,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

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

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

您可以做的是更改comment为词法分析器规则,该规则使用#字符以及随后的任何内容(在这种情况下,到行尾):

grammar Anytext;

line : COMMENT;

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

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

ANY : .;
于 2013-05-13T14:03:56.973 回答
1

对行注释使用以下规则:

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

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

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

LINE_COMMENT
    :   '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN)
    ;
于 2013-05-11T14:03:07.800 回答