Parsing ANTLR区分DXF组码和整数
我是ANTLR的新手,我正在尝试用ANTLRv4编写一个解析器。DXF文件使用所谓的组码来指定以下数据的类型 摘自某些DXF文件的示例:Parsing ANTLR区分DXF组码和整数,parsing,antlr,antlr4,dxf,Parsing,Antlr,Antlr4,Dxf,我是ANTLR的新手,我正在尝试用ANTLRv4编写一个解析器。DXF文件使用所谓的组码来指定以下数据的类型 摘自某些DXF文件的示例: 0 SECTION 2 HEADER 9 $ORTHOMODE 70 0 9 0 ENDSEC 例如,第一个0意味着在下一行后面跟着一个字符串。组码70表示后面跟着一个16位整数,在本例中是0。 我现在的问题是,例如,如何区分组码0和整数0。 在示例代码段中,整数值似乎有一些特殊的缩进,但我在DXF参考中找不到任何关于这一点的
0
SECTION
2
HEADER
9
$ORTHOMODE
70
0
9
0
ENDSEC
例如,第一个0
意味着在下一行后面跟着一个字符串。组码70
表示后面跟着一个16位整数,在本例中是0
。
我现在的问题是,例如,如何区分组码0
和整数0
。
在示例代码段中,整数值似乎有一些特殊的缩进,但我在DXF参考中找不到任何关于这一点的内容
到目前为止,我的想法是遵循ANTLR语法:
grammar SimpleDXF;
start : HEADER variable* ENDSEC ;
variable : varstart (groupcode NL value NL)+ ;
varstart : VAR ;
groupcode : INT ;
value : INT | ANYCHARSEQ ;
WS : [ \t]+ -> skip ;
NL : '\r'? '\n' ;
HEADER : '0' NL 'SECTION' NL '2' NL 'HEADER' NL ;
ENDSEC : '0' NL 'ENDSEC' NL ;
VAR : '9' NL VARNAME NL ;
VARNAME : '$' LETTER (LETTER | DIGIT)* NL ;
INT : DIGIT+ NL ;
ANYCHARSEQ : ANYCHAR+ NL ;
fragment ANYCHAR : [\u0021-\u00FF] ;
fragment LETTER : [A-Za-z_] ;
fragment DIGIT : [0-9] ;
但显然,当试图解析整数0
时,这会失败,因为这被lexer视为组代码0
,这是头
规则的原因
所以现在我不知道如何解决我的问题。非常感谢您的帮助
编辑
更改了ANTLR语法以包含更多的词法规则。现在的问题是lexer完全失败了。第一个输入字符是INT
标记,而不是标题的一部分
标记,就像我希望它是。。。这样做的原因是,如果使用->skip
删除空白位于单个令牌内,则该选项将不起作用(请参见以下示例):
对于输入ab
(两个字母之间的空格),此语法将起作用:
start : 'A' 'B' ;
WS : [ \t\r\n]+ -> skip ;
但这种语法是行不通的:
start : AB ;
AB : 'A' 'B' ;
WS : [ \t\r\n]+ -> skip ;
你错过了这样一条规则
group: groupcode NL value;
否则(正如您所说)分组码和值之间不可能有任何区别。
或者,如果一个组码后面可能有多个值:
group: groupcode (NL value)+;
您应该将header和endsec定义为header和endsec,以允许lexer区分“只是一个数字”和“是序列的开始”。
变量规则(以及由固定句子组成的所有内容)的开头可能也是如此
编辑:
差不多
HEADER : '0' WS* NL WS* 'SECTION' WS* NL WS* '2' WS* NL WS* 'HEADER' WS* NL ;
我会自然而然地想到,虽然不是很优雅。但奇怪的文件格式需要特殊的措施
为了稍微理清这一点,您是否可以在对前导和尾随空格行进行词法分析和分析之前对它们进行修剪?我通过进行一些预处理来解决这个问题,其中每个组码及其对应的值都在同一行。预处理还消除了@uwealner建议的前导和尾随空格。预处理后问题的示例输入文件如下所示:
0 SECTION
2 HEADER
9 $ORTHOMODE
70 0
0 ENDSEC
这样很容易区分组码和简单整数,因为组码总是在行首,而整数在行尾。以下示例语法解决了此问题:
grammar SimpleDXF;
start : HEADER variable* ENDSEC ;
variable : varstart groupcodevalue+ ;
varstart : VAR ;
groupcodevalue : GROUPCODE value ;
value : (INT | ANYCHARSEQ) NL ;
NL : '\r'? '\n' ;
HEADER : '0 SECTION' NL '2 HEADER' NL ;
ENDSEC : '0 ENDSEC' NL ;
VAR : '9 ' VARNAME NL ;
GROUPCODE : INT ' ' ;
VARNAME : '$' LETTER (LETTER | DIGIT)* ;
INT : '-'? DIGIT+ ;
ANYCHARSEQ : ANYCHAR+ ;
fragment ANYCHAR: [\u0021-\u00FF] ;
fragment LETTER : [A-Za-z_] ;
fragment DIGIT : [0-9] ;
我在
变量
规则中隐式地将此作为子规则:(groupcode NL value NL)+
我也尝试用您的建议交换此子规则,但正如预期的那样,我仍然得到相同的结果…您给出的示例确实无法用此规则解析;使用组码70和0作为消耗值时,此值与假定的由0 NL endsec组成的endsec之间保持0。每个组码是否有多个可能的值?每个组码只有一个可能的值,但标题部分中的变量可能有多个参数(组码+值)。在我看来,问题是值0
位于错误的令牌类中,因为头
规则,'0'…
导致lexer为零创建令牌。@Ibizarudi我又尝试了一次;请参阅回答谢谢您的输入。由于您最近的编辑,我能够想出一个预处理dxf文件的解决方案。