【问题标题】:ANTLR Distinguish DXF group codes and integersANTLR 区分 DXF 组码和整数
【发布时间】:2014-05-22 11:38:49
【问题描述】:

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

一些 DXF 文件的示例摘录:

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

例如,第一个0 表示在下一行中跟随一个字符串。组码70 表示后面将跟随一个 16 位整数,在示例中为0。 我现在的问题是例如如何区分组码0和整数0。 在示例 sn-p 中,整数值似乎有一些特殊的缩进,但我在 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 时这会失败,因为这被词法分析器视为组代码 0,这是 header 规则的原因。

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

编辑

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

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

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

但是这个语法不行:

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

【问题讨论】:

    标签: parsing antlr antlr4 dxf


    【解决方案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] ;
    

    【讨论】:

      【解决方案2】:

      你缺少一个规则,比如

      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 ;
      

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

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

      【讨论】:

      • 我在 variable 规则中隐含地将此作为子规则:(groupcode NL value NL)+ 我也尝试用您的建议交换此子规则,但正如预期的那样,我仍然得到相同的结果...
      • 你给出的例子确实不能被这条规则解析;使用组码 70 和 0 作为消耗的值,在此和假定的 endsec 之间保持一个 0,该 endsec 由 0 NL ENDSEC 组成。每个组码可能有多个值吗?
      • 每个组码只能有一个值,但标题部分的变量可能有多个参数(组码+值)。 IMO 的问题是,0 的值在错误的标记类中,因为 header 规则,其中'0' ... 导致词法分析器为零生成标记。
      • @Ibizarudi 我又试了一次;看答案
      • 感谢您的意见。感谢您的最新编辑,我能够提出预处理 dxf 文件的解决方案。
      猜你喜欢
      • 2011-10-24
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多