【问题标题】:ANTLR4: Consuming all remaining input until EOFANTLR4:消耗所有剩余输入直到 EOF
【发布时间】:2015-02-19 08:26:29
【问题描述】:

在此处使用 ANTLR 4.3 版。

此语法接受各种EOF 分隔的表达式,一次一个。表达式以key 开头,之后的语法有所不同。接受的字符串示例:

"cycle in freerun" <EOF>
"runtime <= 20m" <EOF>
"grab enabled" <EOF>

ANTLR 愉快地将所有表达式解析成组件,听者作用于相关组件,生活是幸福的。这里是一个有代表性的sn-p语法:

expr               // <-- Start rule
  : freq_p EOF
  | cycle_p EOF
  ...              // Many more, ad nauseum
  ;

freq_p  : FREQ '=' INT | FREQ '<' INT ;

cycle_p : CYCLE IN cycles ;
cycles  : cycle (',' cycle)* ;
cycle   : PHASELOCK | FREERUN ;

// Keywords
CYCLE     : 'cycle' ;
FREERUN   : 'freerun' ;
FREQ      : 'frequency' ;
IN        : 'in' ;
PHASELOCK : 'phaselock' ;

INT       : '0'..'9'+ ;
WS        : [ \n\t\r]+ -> skip ;

但是现在,我需要扩展语法以包含 2 个新表达式,这两个表达式都以接受任何字符序列(包括 Unicode)到 EOF 结束。示例输入:

"echo = Confirm 'interlock' is clear,\n and actuate \"frequency\" button." <EOF>
"report Process complete." <EOF>

我很难在语法中表达对EOF 的所有输入的接受。以下变化会导致痛苦:

expr
  ...
  : echo_p EOF
  : report_p EOF
  ...

echo_p   : ECHO   '=' REMAINING ; // Snarfs all remaining input until EOF
report_p : REPORT     REMAINING ; // Ditto

ECHO     : 'echo' ;
REPORT   : 'report' ;

REMAINING : <WHAT_GOES_HERE?> ;  // .* messes up everything else

如何做到这一点?期望的结果是解析树侦听器将获取文本值,例如REMAINING().getText()

放弃的方法:Lexer Grammar 利用 mode()

我尝试将 REMAINING 从组合语法中写入单独的 lexer grammarimport,但遇到了 https://github.com/antlr/antlr4/issues/160 和编译时警告。 IntelliJ ANTLR 插件也会出现故障,这会对生产力产生负面影响。我了解到,至少在 ANTLR 4.3 中不支持包含使用模式的词法分析器语法。

lexer grammar Remainder;

@lexer::members {
// Needed at least until ANTLR issue #160 is fixed.
public static final int CONSUME_ALL = 123;
}

REMAINING : . -> more, mode(CONSUME_ALL) ;

mode CONSUME_ALL;

TEXT : .* ; // Consume all remaining input

【问题讨论】:

  • 是否可以“短路”ANTLR,即在解析树侦听器中?监听器的enterReport_p()方法能否将剩余的字符流snar成String,然后指示ANTLR停止(模拟或直接跳转到EOF?)并表示成功?
  • 我遇到了类似的问题。寻找可能使用令牌重写器将伪 EOF 令牌注入令牌流的方法。如果成功,我会在这里发布答案。
  • 太棒了——请做!

标签: java maven antlr antlr4


【解决方案1】:

您应该通过添加? 来使.* 不贪婪:

REMAINING : .*? ;

这将消耗一切,直到找到EOF

看看这里: https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Wildcard+Operator+and+Nongreedy+Subrules

【讨论】:

  • 这并不能解决问题:输入 report report report 被不希望地标记为 report 标记的三元组:[@0,0:5='report',&lt;10&gt;,1:0] [@1,7:12='report',&lt;10&gt;,1:7] [@2,14:19='report',&lt;10&gt;,1:14] [@3,21:20='&lt;EOF&gt;',&lt;-1&gt;,2:0]。所需的令牌流是:reportREMAININGEOF。对于问题中的语法扩展,echo = echo cycle freerun frequency. (Added the missing ECHO` 和 REPORT 标记同样存在标记化问题)。
  • 此外,echo =report 之后的所有未被识别为标记的输入部分都会生成 line 1:10 token recognition error at: 'q' 消息,每个字符或附近一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-18
相关资源
最近更新 更多