我正在解析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]
我的语法有什么问题,导致令牌识别错误?
答案 0 :(得分:2)
[549 3.14 false (Ralph) /SomeName]
无法识别为ARRAY
,因为它包含空格,并且ARRAY
的规则不允许有任何空格。如果要忽略数组元素之间的空格,则应将其变成解析器规则而不是词法分析器规则(同样适用于DICTIONARY
)。
您还需要使OBJECT
成为解析器规则,因为否则它将永远不会被匹配,因为任何匹配的输入(例如NUMBER
都将始终产生NUMBER
令牌而不是OBJECT
标记,因为OBJECT
在语法中排在最后。通常,您永远不需要多个词法分析器规则,在这些规则中,可以由它们之一匹配的所有内容也可以始终与至少另一个匹配。这也意味着您要将INT
和FLOAT
变成fragment
s。