Java 复杂文件解析中的Antlr Lexer回溯
我们使用ANTLR解析复杂的文件结构,然后创建java对象来执行某些活动 到目前为止,文件中的每一行都以标识符开头。例如:Java 复杂文件解析中的Antlr Lexer回溯,java,antlr,antlr3,Java,Antlr,Antlr3,我们使用ANTLR解析复杂的文件结构,然后创建java对象来执行某些活动 到目前为止,文件中的每一行都以标识符开头。例如: 第1行…\n 第2行…\n EOF 现在有了新的要求,线路的标识符,即线路1等,可以出现在线路的任何部分。标识符中的字符也可以出现 下面是我尝试过的语法,但由于Lexer没有回溯,所以失败了,我不知道如何使它工作。 file : line* EOF; line : (line_one line_two* ) NEWLINE?; line_one : field+ LI
第1行…\n
第2行…\n
EOF
现在有了新的要求,线路的标识符,即线路1等,可以出现在线路的任何部分。标识符中的字符也可以出现 下面是我尝试过的语法,但由于Lexer没有回溯,所以失败了,我不知道如何使它工作。
file : line* EOF;
line : (line_one line_two* ) NEWLINE?;
line_one : field+ LINE1_ID field* {
System.out.println("got line_one:" + $line_one.text);
};
line_two : field+ LINE2_ID field* {
System.out.println("got line_two:" + $line_two.text);
};
field : (FIELD | SKIP_ID )+;
LINE1_ID : 'LINE1' ;
LINE2_ID : 'LINE2' ;
SKIP_ID : 'L';
FIELD : FCHAR+;
fragment
FCHAR : ~('\r' | '\n' | 'L' );
NEWLINE: ('\r' '\n' | '\r' | '\n');
我不是Antlr或编写语法的专家,非常感谢您的指点或帮助。P.S.使用的Antlr版本是3.4,我们无法将其升级到4
正在使用的文件示例(固定长度格式):
每行的标识符由1001、1002等标记。1001是文件的头,1002标记组的开始,而1004标记组的结束。1003表示实际记录,1005表示文件结束。
行标识符位置的出现可能因行而异,但出现位置在一行中是固定的,即,如果同一行在CUST记录中多次出现,则位置固定为5(假设第一个字符位于位置0)
lexer的问题是,一旦识别出100,它就假定总是尝试与标题记录匹配,如果失败,它不会回溯,并且如果使用$line.text获取已使用的行,这些字符(即100)也会丢失
在上面的示例中,我使用数字来标识一行,但标识符可以是字母数字,并且有效字符是UTF-8的字符,而不仅仅是ASCII字符
上述语法的输入为:
ABCDLINE1aaaaFGHA\n
aaabbbBCLINE2XYZ\n
LINELINELINE2PQR\n
LIN QRSTLINE2ABC579\n
调用parser.file()时程序的输出:
got line_one:ABCDLINE1aaaaFGHA
line 2:8 mismatched input 'LINE2' expecting LINE1_ID
line 3:0 no viable alternative at character 'L'
line 2:16 mismatched input '\r\n' expecting LINE1_ID
line 3:4 no viable alternative at character 'L'
line 3:8 mismatched input 'LINE2' expecting LINE1_ID
line 4:0 no viable alternative at character 'L'
line 3:16 mismatched input '\r\n' expecting LINE1_ID
line 4:8 mismatched input 'LINE2' expecting LINE1_ID
line 4:19 mismatched input '\r\n' expecting LINE1_ID
感谢@BartKiers,在上述语法中添加了示例、输入和输出。在我看来,您刚刚开始编写语法,而没有尝试熟悉ANTLR的基础知识。我建议你拿一份,从头开始。谢谢Bart,但你认为使用ANTLR3实现上述目标可行吗,还是我应该从其他方向着手处理?当然,但是您可能试图在解析器规则中加入太多的逻辑:通常最好稍微松散地匹配,然后遍历生成的AST以进行进一步验证。另外,请务必仔细阅读如何创建标记:ANTLR的lexer总是尽可能多地匹配标记。祝你好运
got line_one:ABCDLINE1aaaaFGHA
line 2:8 mismatched input 'LINE2' expecting LINE1_ID
line 3:0 no viable alternative at character 'L'
line 2:16 mismatched input '\r\n' expecting LINE1_ID
line 3:4 no viable alternative at character 'L'
line 3:8 mismatched input 'LINE2' expecting LINE1_ID
line 4:0 no viable alternative at character 'L'
line 3:16 mismatched input '\r\n' expecting LINE1_ID
line 4:8 mismatched input 'LINE2' expecting LINE1_ID
line 4:19 mismatched input '\r\n' expecting LINE1_ID