我试图用ANTLRv4为DXF files编写一个解析器 . DXF文件使用所谓的组代码来指定以下数据的类型 .
某些DXF文件的示例摘录:
0
SECTION
2
HEADER
9
$ORTHOMODE
70
0
9
0
ENDSEC
例如,第一个 0
意味着在下一行中跟随一个字符串 . 组代码 70
表示将跟随16Bit Integer,在示例中它是 0
. 我现在的问题是如何区分组代码 0
和整数 0
. 在示例代码段中,似乎Integer值有一些特殊的缩进,但我在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
,因为 header
规则 .
所以现在我对如何解决我的问题毫无头绪 . 任何帮助都非常感谢 .
EDIT
更改了ANTLR语法以包含更多词法规则 . 现在的问题是词法分析器完全失败了 . 第一个输入字符是一个 INT
标记而不是 HEADER
标记的一部分,就像我想要的那样...原因是如果它在单个标记内,则用 -> skip
删除空格将不起作用(参见下面的示例):
对于输入 A B
(两个字母之间的空格),该语法将起作用:
start : 'A' 'B' ;
WS : [ \t\r\n]+ -> skip ;
但是这个语法不起作用:
start : AB ;
AB : 'A' 'B' ;
WS : [ \t\r\n]+ -> skip ;
2 回答
我通过做一些预处理解决了这个问题,其中每个组代码和它的相应值都在同一行上 . 正如@UweAllner建议的那样,预处理还消除了前导和尾随空格 . 预处理后问题的示例输入文件如下所示:
像这样很容易区分组代码和简单整数,因为组代码总是在一行的开头,而整数在一行的末尾 . 以下示例语法解决了该问题:
你错过了一个规则
否则(如你所说),组码和值之间不可能有区别 . 或者,如果一个组代码后面可能跟有几个值:
你应该将header和endsec定义为HEADER和ENDSEC,以允许词法分析器区分“只是一个数字”和“是一个序列的开始” . 同样可能是变量规则的开始(以及由固定句子组成的所有内容) .
编辑:像
在我的脑海中浮现,而不是非常优雅 . 但奇怪的文件格式需要外来措施 .
为了稍微理清这一点,你是否有可能在修剪和解析之前修剪前导和尾随空格的行?