用于解析文本文件的 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 解析器)
我正在疯狂地尝试使用 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 解析器)