用于解析文本文件的 ANTLR 语法

ANTLR Grammar for parsing a text file

我正在疯狂地尝试使用 ANTLR 生成解析器语法。 我有像这样的纯文本文件:

Diagram :   VW  503 FSX 09/02/2015  12/02/2015  STP
Fleet   :   AAAA

OFF     :       

AAA     05+44   5R06            
KKK     05+55   06.04   1R06            5530
ZZZ     06.24   06.30   1R06            5530
YYY     07.53           REVRSE      
YYY     08.23   9G98            5070


WORKS   :       

MILES   :(LD)   1288.35 (ETY)   3.18    (TOT)   1291.53

每个 "Diagram" 实体都包含在 "Diagram :" 和 EOF 之前的“(TOT)之间。 在同一个纯文本文件中可以存在多个 "Diagram" 实体。

我用 ANTRL 做了一些测试

`grammar Hello2;

xxxt : diagram+;
diagram : DIAGRAM_ini  txt fleet LEGS+ DIAGRAM_end;
txt : TEXT;

fleet : FLEET_INI txt;
 num : NUMBER;
// Lexer Rules

DIAGRAM_ini : 'Diagram :';
DIAGRAM_end : '(TOT)' ;
LEGS : ('AAA' | 'KKK' | 'ZZZ' | 'YYY') ;
FLEET_INI :  'Fleet :';
TEXT : ('a'..'z')+ ;
NUMBER: ('0'..'9') ;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ -> skip ;`

我的目标是能够递归解析图,并收集所有 LEGS text/number。

任何 help/tips 都非常感谢! 非常感谢

注册 S.

我建议不要像您那样解析文件。这个文件没有用单词和语法定义语言,而是用字符的格式化文本:

  • 格式约定相当薄弱
  • 冒号前的标签不能作为标记,因为它们可能会重新出现在 body (AAA (=label) vs AAAA (=body)
  • 令牌必须非常原始才能满足此要求

使用 ANTLR 的解决方案

你需要一个较弱的语法来解决这个问题,例如

grammar diagrams;

diagrams : diagram+ ;

diagram : section+ ;

section : WORD ':' body? ;

body : textline+;

textline : (WORD | NUMBER | SIGNS)* ('\r' | '\n')+;

WORD : LETTER+ ;

NUMBER : DIGIT+ ;

SIGNS : SIGN+ ;

WHITESPACE : ( '\t' | ' ' )+ -> skip ;

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

fragment SIGN : ('.'|'+'|'('|')'|'/') ;

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

运行 访问者对解析结果

  • 构建body
  • 的规范化文本
  • 过滤掉 body
  • 中的 LEGS 行
  • 用另一个解析器解析 LEGS 行(这里 regexp-parser 就足够了,但您也可以定义另一个 ANTLR-Parser)

另一个选择:

尝试 Packrat 解析(例如 parboiled) - 它(特别是对于编译器构建经验较少的人)更容易理解

  • 它更符合您的语法设计
  • parboiled 是纯的 java(java 中指定的语法)

缺点:

  • 空格处理必须在解析器规则中完成
  • Debugging/Error 消息是个问题(对于所有 Packrat 解析器)