如何使用ANTLR4消除歧义,有时是两个令牌,有时是第三个令牌?

时间:2014-07-17 08:43:45

标签: antlr4 lexer disambiguation

我的ANTLR4语法有问题。我需要解析包含6个AN字符的文本。 根据文本的上下文,它可以表示:   - 6-AN标识符(航班预订编号 - PNR - 看起来像7B22MS,或JPN92Y,或类似),   - 航空公司代号(两个字母)+航班号(四个号码),例如LH1856。

问题在于,如果我创建解析航空公司的lexer规则,数字和PNR标识符如下:

航空公司:'A'..'Z''A'..'Z';

FlNum:('0'..'9')('0'..'9')('0'..'9')('0'..'9');

PNR :('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9')('A'..' Z '|' 0' .. '9')( 'A' .. 'Z' | '0' .. '9')( 'A' .. 'Z' | '0' .. '9') ( 'A' .. 'Z' | '0' .. '9');

然后PNR规则总是获胜并吃掉与其模式匹配的所有令牌。

如果语法的上下文需要解析Airline和FlNum,我怎么能改变它呢?

2 个答案:

答案 0 :(得分:1)

这个怎么样:

AirlineAndFlNm : 'A'..'Z' 'A'..'Z' ('0'..'9')('0'..'9')('0'..'9')('0'..'9');

PNR : ('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9')('A'..'Z'|'0'..'9');

或更具可读性:

AirlineAndFlNm : LETTER LETTER DIGIT DIGIT DIGIT DIGIT ;

PNR : AlphaNum AlphaNum AlphaNum AlphaNum AlphaNum AlphaNum;

// fragments can only be used by other rules, will never create a token on their own
fragment LETTER: 'A'..'Z';
fragment DIGIT : '0'..'9';
fragment AlphaNum: LETTER | DIGIT ;

之后应该很容易将AirlineAndFlNm分开。 由于AirlineAndFlNm位于PNR之前,因此如果可以,它将匹配。

答案 1 :(得分:0)

让词法分析器对单个字符进行标记,并将这些规则提升为解析器规则:

// parser rules

airline
 : LETTER
 ;

fl_num
 : DIGIT DIGIT DIGIT DIGIT
 ;

pnr
 : alpha_num alpha_num alpha_num alpha_num alpha_num alpha_num
 ;

alpha_num
 : DIGIT
 | LETTER
 ;

// lexer rules

DIGIT
 : [0-9]
 ;

LETTER
 : [A-Z]
 ;