0

我是 ANTLR 的新手,我正在尝试使用 ANTLRv4为DXF 文件编写解析器。DXF 文件使用所谓的组码来指定以下数据的类型。

一些 DXF 文件的示例摘录:

  0
SECTION
  2
HEADER
  9
$ORTHOMODE
 70
     0
  9
  0
ENDSEC

例如,第一个0意味着在下一行中跟随一个字符串。组码70意味着后面会跟着一个 16Bit Integer,在示例中是0. 我现在的问题是如何区分组代码0和 Integer 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] ;

但显然这在尝试解析 Integer 时会失败,因为这被词法分析器0视为组代码,这是规则的原因。0header

所以现在我不知道如何解决我的问题。非常感谢任何帮助。

编辑

更改了 ANTLR 语法以包含更多词法分析器规则。现在的问题是词法分析器完全失败了。第一个输入字符是一个INT标记,而不是我想要的标记的一部分HEADER......原因是-> skip如果它在单个标记内,删除空格将不起作用(参见以下示例):

对于输入A B(两个字母之间的空格),此语法将起作用:

start   :   'A' 'B' ;
WS      :   [ \t\r\n]+ -> skip ;  

但是这个语法不起作用:

start   :   AB ;
AB      :   'A' 'B' ;
WS      :   [ \t\r\n]+ -> skip ;  
4

2 回答 2

1

我通过做一些预处理解决了这个问题,每个组代码及其对应的值都在同一行。正如@UweAllner 建议的那样,预处理还消除了前导和尾随空格。预处理后问题中的示例输入文件如下所示:

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] ;
于 2014-05-26T15:58:29.637 回答
0

您缺少一条规则,例如

group: groupcode NL value;

否则(如您所说),组码和值本身之间不可能有区别。或者,如果一个组码后面可能跟多个值:

group: groupcode (NL value)+;

并且您应该将 header 和 endsec 定义为 HEADER 和 ENDSEC 以允许词法分析器区分“只是一个数字”和“是序列的开始”。可变规则的开头可能相同(以及由固定句子组成的所有内容)。

编辑:像

HEADER      :   '0' WS* NL WS* 'SECTION' WS* NL WS* '2' WS* NL WS* 'HEADER' WS* NL ;

我的脑海里自然而然地出现了,虽然不是很优雅。但是奇怪的文件格式需要特殊的措施。

为了稍微理顺一下,您是否可以在词法分析和解析之前修剪前导和尾随空格的行?

于 2014-05-22T11:52:34.410 回答