如何分析与ANTLR嵌套字符串分隔符PDF字符串?(How do I parse PDF strin

2019-10-16 13:45发布

我正在解析PDF内容流。 字符串是用括号分隔,但可以包含嵌套转义括号。 从PDF参考:

一个字符串可以写为括在括号中的任意字符数。 任何字符可能会出现在除不平衡括号(LEFT PARENHESIS(28H)和右括号(29H))和反斜线的字符串(REVERSE SOLIDUS(5CH)),如在该子条款描述了将被特殊处理。 在字符串中的平衡双括号不需要特殊治疗。

例1:

The following are valid literal strings: 
(This is a string)
(Strings may contain newlines
and such.)
(Strings may contain balanced parentheses ( ) and special characters (*!&}^% and so on).)

这似乎是推词法模式到堆栈是处理这个事情。 这里是我的词法和语法分析器的精简版本。

lexer grammar PdfStringLexer;

Tj: 'Tj' ;
TJ: 'TJ' ;

NULL: 'null' ;

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

LBRACKET: '[' ;
RBRACKET: ']' ;
LDOUBLEANGLE: '<<' ;
RDOUBLEANGLE: '>>' ;

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

NAME: '/' ID ;

// A sequence of literal characters enclosed in parentheses.
OPEN_PAREN: '(' -> more, pushMode(STR) ; 

// Hexadecimal data enclosed in angle brackets
HEX_STRING: '<' [0-9A-Za-z]+ '>' ; 

fragment INT: DIGIT+ ; // match 1 or more digits

fragment FLOAT:  DIGIT+ '.' DIGIT*  // match 1. 39. 3.14159 etc...
     |         '.' DIGIT+  // match .1 .14159
     ;

fragment DIGIT:   [0-9] ;        // match single digit

// Accept 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

mode STR;

LITERAL_STRING : ')' -> popMode ;
STRING_OPEN_PAREN: '(' -> more, pushMode(STR) ; 
TEXT : . -> more ;

parser grammar PdfStringParser;

options { tokenVocab=PdfStringLexer; } 

array: LBRACKET object* RBRACKET ;
dictionary: LDOUBLEANGLE (NAME object)* RDOUBLEANGLE ;
string: (LITERAL_STRING | HEX_STRING) ;
object
    : NULL
    | array
    | dictionary
    | BOOLEAN
    | NUMBER
    | string
    | NAME
    ;

content : stat* ;

stat
    : tj
    ;

tj: ((string Tj) | (array TJ)) ; // Show text

当我处理此文件:

(Oliver’s Army) Tj
((What’s So Funny ’Bout) Peace, Love, and Understanding) Tj

我得到这个错误,并分析树:

line 2:24 extraneous input ' Peace, Love, and Understanding)' expecting 'Tj'

因此,也许pushMode不推重复模式到堆栈中。 如果没有,什么是处理嵌套的括号的方式吗?


编辑

我离开了关于字符串中的转义序列的说明:

在一个字符串,反向SOLIDUS用作转义字符。 紧跟在REVERSE SOLIDUS的字符确定它的精确解释如表3所示。如果按照REVERSE SOLIDUS的字符不是在表3中示出的那些中的一个,反向SOLIDUS应被忽略。

表3列出\n\r\t\b退格(08H), \f换页(FF), \( \) \\ ,和\ddd字符码DDD(八进制)

文字串中出现没有先前的REVERSE SOLIDUS结束的行的标记应被视为(0AH)的一个字节的值,而不论是否结束行标记的是一个回车(0DH),换行(0AH),或两者。

例2:

(These \
two strings \
are the same.)
(These two strings are the same.)

例3:

(This string has an end-of-line at the end of it. 
)
(So does this one.\n)

我应该使用这个字符串的定义:

STRING
 : '(' ( ~[()]+ | STRING )* ')'
 ;

没有在我的代码或创建的字符串词法分析器模式和应对语法转义序列模式和处理转义序列?

Answer 1:

你可以用词汇模式做到这一点,但在这种情况下,它不是真的需要。 你可以简单地定义这样的词法规则:

STRING
 : '(' ( ~[()]+ | STRING )* ')'
 ;

和转义序列,你可以尝试:

STRING
 : '(' ( ~[()\\]+ |  ESCAPE_SEQUENCE | STRING )* ')'
 ;

fragment ESCAPE_SEQUENCE
 : '\\' ( [nrtbf()\\] | [0-7] [0-7] [0-7] )
 ;


文章来源: How do I parse PDF strings with nested string delimiters in antlr?
标签: pdf antlr4