Antlr4 如何在antlr中解析数组?
我正在解析PDF内容流。我在定义数组时遇到问题。PDF参考文件(PDF 32000-1:2008)中的数组定义为: 数组对象是按顺序排列的一维对象集合…数组的元素可以是数字、字符串、字典或任何其他对象(包括其他数组)的任意组合。一个数组可以有零个元素 数组应写成方括号内的对象序列(使用左方括号(5Bh)和右方括号(5Dh)) 示例:[549 3.14 false(拉尔夫)/SomeName] 这是我语法的精简版本:Antlr4 如何在antlr中解析数组?,antlr4,Antlr4,我正在解析PDF内容流。我在定义数组时遇到问题。PDF参考文件(PDF 32000-1:2008)中的数组定义为: 数组对象是按顺序排列的一维对象集合…数组的元素可以是数字、字符串、字典或任何其他对象(包括其他数组)的任意组合。一个数组可以有零个元素 数组应写成方括号内的对象序列(使用左方括号(5Bh)和右方括号(5Dh)) 示例:[549 3.14 false(拉尔夫)/SomeName] 这是我语法的精简版本: grammar PdfStream; /* * Parser Rules
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
我的语法有什么问题导致令牌识别错误?[549 3.14 false(Ralph)/SomeName]
未被识别为数组,因为它包含空格,数组的规则不允许任何空格。如果希望忽略数组元素之间的空格,则应将其转换为解析器规则,而不是lexer规则(这同样适用于字典
)
您还需要将OBJECT
设置为解析器规则,否则它将永远不会被匹配,因为匹配的任何输入(例如,NUMBER
将始终生成NUMBER
标记,而不是OBJECT
标记,因为OBJECT
在语法中位于最后。一般来说,您永远不会想要多个lexer规则,其中可以由其中一个匹配的所有规则也可以始终由至少一个其他规则匹配。这也意味着你想把INT
和FLOAT
变成fragment
s。显然,我需要继续学习ANTLR 4参考书,以便更好地掌握什么应该是解析器规则,什么应该是lexer规则。这是一个巨大的帮助,让我振作起来。谢谢。@SSteve根据经验,您可以问问自己是否允许并忽略规则中的空格。作为另一条经验法则,您很少希望lexer规则是递归的(尽管有时您会这样做)。正如我在回答中所写的,你不希望lexer规则重叠,导致其中一些规则冗余。这方面的经验法则是,您不希望lexer规则只是其他lexer规则的替代品(即A:B | C | D
)。
<AE93>
(String1)
( String2 )
[]
[549 3.14 false (Ralph) /SomeName]
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]