我可以让我的ANTLR4 Lexer从输入流中丢弃一个字符吗?
我正在解析PDF流。在关于文字字符串对象的第7.3.4.2节中,说明应忽略文字字符串中未后跟行尾字符、一到三个八进制数字或其中一个字符“nrtbf()\”的反斜杠。有没有办法让我的lexer中的我可以让我的ANTLR4 Lexer从输入流中丢弃一个字符吗?,antlr4,Antlr4,我正在解析PDF流。在关于文字字符串对象的第7.3.4.2节中,说明应忽略文字字符串中未后跟行尾字符、一到三个八进制数字或其中一个字符“nrtbf()\”的反斜杠。有没有办法让我的lexer中的recover方法在这种情况下忽略反斜杠 以下是我的简化解析器: parser grammar PdfStreamParser; options { tokenVocab=PdfSteamLexer; } array: LBRACKET object* RBRACKET ; dictionary:
recover
方法在这种情况下忽略反斜杠
以下是我的简化解析器:
parser grammar PdfStreamParser;
options { tokenVocab=PdfSteamLexer; }
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
这是lexer。(根据《我不使用单独的字符串模式》中的建议):
lexer语法PdfStreamLexer;
Tj:‘Tj’;
TJ:‘TJ’;
空:“空”;
布尔值:('true'|'false');
勒布朗:“[”;
RBRACKET:']';
LDOUBLEANGLE:'';
编号:(“+”|“-”)?(国际浮点数);
名称:“/”ID;
//用括号括起来的一系列文字字符。
文字字符串:'('([()\\]+|转义序列|文字字符串)*');
//可以出现在文字字符串中的转义序列
片段逃逸序列
:“\\”([\r\nnrtbf()\\]\[0-7][0-7]?[0-7]?)
;
十六进制字符串:“”;//尖括号内的十六进制数据
片段INT:DIGIT+;//匹配一个或多个数字
片段浮点:数字+'.'数字*//匹配1。393.14159等。。。
|'.'位+//匹配.1.14159
;
片段数字:[0-9];//匹配一位数
//接受除空格和定义的分隔符以外的所有字符()[]{}/%
ID:~[\t\r\n\u000C\u0000()[\]{}/%]+;
WS:[\t\r\n\u000C\u0000]+->skip;//PDF定义了六个空白字符
我可以重写PdfStreamLexer类中的recover方法,并在出现
LexerNoViableAltException
时收到通知,但我不确定如何(或者如果可能的话)忽略反斜杠并继续进行文本字符串标记化。要能够跳过部分字符串,需要使用词汇模式。下面是一个快速演示:
lexer grammar DemoLexer;
STRING_OPEN
: '(' -> pushMode(STRING_MODE)
;
SPACES
: [ \t\r\n] -> skip
;
OTHER
: .
;
mode STRING_MODE;
STRING_CLOSE
: ')' -> popMode
;
ESCAPE
: '\\' ( [nrtbf()\\] | [0-7] [0-7] [0-7] )
;
STRING_PART
: ~[\\()]
;
NESTED_STRING_OPEN
: '(' -> type(STRING_OPEN), pushMode(STRING_MODE)
;
IGNORED_ESCAPE
: '\\' . -> skip
;
可在解析器中使用,如下所示:
parser grammar DemoParser;
options {
tokenVocab=DemoLexer;
}
parse
: ( string | OTHER )* EOF
;
string
: STRING_OPEN ( ESCAPE | STRING_PART | string )* STRING_CLOSE
;
如果现在解析字符串FU(abc(def)\@\)条
,将得到以下解析树:
如您所见,
\)
保留在树中,但忽略了\@
。也许您可以将转义序列视为“\\”后跟八进制序列或除“0”(由八进制处理)或行尾以外的任何字符。再次感谢。像解析器一样思考与像编译器一样思考有很大不同。我还有很长的路要走。我需要做的唯一更改是从忽略的转义中删除点,因为只有反斜杠被忽略,而不是它后面的字符。但是修改很好。啊,我明白了,只有\@
中的反斜杠被省略,而@
应该保留。那么是的,你是对的:忽略\u转义:'\\'->跳过代码>是一条路要走。当然不客气@SSteve
parser grammar DemoParser;
options {
tokenVocab=DemoLexer;
}
parse
: ( string | OTHER )* EOF
;
string
: STRING_OPEN ( ESCAPE | STRING_PART | string )* STRING_CLOSE
;