首页 文章

ANTLR区分DXF组代码和整数

提问于
浏览
0

我试图用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 回答

  • 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] ;
    
  • 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 ;
    

    在我的脑海中浮现,而不是非常优雅 . 但奇怪的文件格式需要外来措施 .

    为了稍微理清这一点,你是否有可能在修剪和解析之前修剪前导和尾随空格的行?

相关问题