如何解析antlr中的数组?

时间:2019-06-26 18:33:12

标签: antlr4

我正在解析PDF内容流。我在定义数组时遇到了麻烦。 PDF参考(PDF 32000-1:2008)中数组的定义是:

  

数组对象是按顺序排列的对象的一维集合。 …数组的元素可以是数字,字符串,字典或任何其他对象(包括其他数组)的任意组合。数组可以包含零个元素。

     

一个数组应该被写成一个包含在方括号中的对象序列(使用左方括号(5Bh)和右方括号(5Dh))。

     

示例:[549 3.14错误(Ralph)/ SomeName]

这是我的语法的精简版:

grammar PdfStream;

/*
 * Parser Rules
 */

content : stat* ;

stat
    : array
    | string
    ;

array: ARRAY ;
string: STRING ;

/*
 * Lexer Rules
 */

ARRAY: '[' (ARRAY | DICTIONARY | OBJECT)* ']' ;

DICTIONARY: '<<' (NAME (ARRAY | DICTIONARY | OBJECT))*  '>>' ;

NULL: 'null' ;

BOOLEAN: ('true'|'false') ;

NUMBER: ('+' | '-')? (INT | FLOAT) ;

STRING: (LITERAL_STRING | HEX_STRING) ;

NAME: '/' ID ;

INT: DIGIT+ ;

LITERAL_STRING: '(' .*? ')' ;

HEX_STRING: '<' [0-9A-Za-z]+ '>' ;

FLOAT:  DIGIT+ '.' DIGIT*
     |         '.' DIGIT+
     ;

OBJECT
    : NULL
    | BOOLEAN
    | NUMBER
    | STRING
    | NAME
    ;

fragment DIGIT:   [0-9] ;

// All characters except whitespace and defined delimiters ()<>[]{}/%
ID: ~[ \t\r\n\u000C\u0000()<>[\]{}/%]+ ;

WS: [ \t\r\n\u000C\u0000]+ -> skip ; // PDF defines six whitespace characters

这是我正在处理的测试文件。

<AE93>
(String1)
( String2 )
[]
[549 3.14 false (Ralph) /SomeName]

当我用grun PdfStream tokens -tokens stream.txt处理文件时,得到以下输出:

line 5:0 token recognition error at: '[549 '
line 5:33 token recognition error at: ']'
[@0,0:5='<AE93>',<STRING>,1:0]
[@1,7:15='(String1)',<STRING>,2:0]
[@2,17:27='( String2 )',<STRING>,3:0]
[@3,29:30='[]',<ARRAY>,4:0]
[@4,37:40='3.14',<NUMBER>,5:5]
[@5,42:46='false',<BOOLEAN>,5:10]
[@6,48:54='(Ralph)',<STRING>,5:16]
[@7,56:64='/SomeName',<NAME>,5:24]
[@8,67:66='<EOF>',<EOF>,6:0]

我的语法有什么问题,导致令牌识别错误?

1 个答案:

答案 0 :(得分:2)

[549 3.14 false (Ralph) /SomeName]无法识别为ARRAY,因为它包含空格,并且ARRAY的规则不允许有任何空格。如果要忽略数组元素之间的空格,则应将其变成解析器规则而不是词法分析器规则(同样适用于DICTIONARY)。

您还需要使OBJECT成为解析器规则,因为否则它将永远不会被匹配,因为任何匹配的输入(例如NUMBER都将始终产生NUMBER令牌而不是OBJECT标记,因为OBJECT在语法中排在最后。通常,您永远不需要多个词法分析器规则,在这些规则中,可以由它们之一匹配的所有内容也可以始终与至少另一个匹配。这也意味着您要将INTFLOAT变成fragment s。