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

Parsing 用于解析文本文件的ANTLR语法,parsing,antlr,grammar,antlr4,Parsing,Antlr,Grammar,Antlr4,我正在疯狂地尝试用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

我正在疯狂地尝试用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
每个“图”实体包含在“图”和EOF前的“(TOT)之间。 在同一个普通txt文件中,可以存在多个“图表”实体

我用安特尔做了一些测试

`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 ;`
我的目标是能够递归地解析图表,并收集所有的文本/数字

任何帮助/提示都将不胜感激! 非常感谢

雷格斯
S.

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

  • 格式约定相当弱
  • 冒号前的标签不能用作标记,因为它们可能会重新出现在正文中(AAA(=标签)与AAAA(=正文)
  • 令牌必须非常原始才能满足此要求
使用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的规范化文本
  • 将腿部线条从身体中过滤掉
  • 使用另一个解析器解析LEGS行(这里一个regexp解析器就足够了,但您也可以定义另一个ANTLR解析器)
另一种选择:

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

  • 它更符合你的语法设计
  • parboiled是纯java(java中指定的语法)
缺点:

  • 空格处理必须在解析器规则中完成
  • 调试/错误消息是一个问题(对于所有packrat解析器)

疯狂?你的问题是什么?你的lexer语法似乎模棱两可。“AAAA”应该是标记“TEXT”,而“AAA”是“LEGS”。也许你应该实现解析器标记,如“swallow_to_semi”或“swallow_to_newline”。你好,可能是因为我对这个概念很陌生,但我不理解你的建议。抱歉,为什么是“AAAA”“应该标记为“文本”?我想我需要标记图表和舰队字符串,不是吗?我也不明白“swallow_to_semi”是什么意思对不起…谢谢你的帮助。当你有像“Fleet:AAAA”这样的输入时,lexer将生成标记:[Fleet_INI(“舰队”)、LEGS(“AAA”)、TEXT(“A”)]。因为LEG列在文本之前,并且匹配前三个“A”。只要尝试调试生成的解析器代码,您就会看到规则“fleet”将失败。