需要Lexer规则冲突解决方案

时间:2015-02-24 15:29:59

标签: antlr3

我的ANTLR3语法中有这些词法规则:

INTEGER:                DIGITS;
FLOAT:                  DIGITS? DOT_SYMBOL DIGITS ('E' (MINUS_OPERATOR | PLUS_OPERATOR)? DIGITS)?;

HEXNUMBER:              '0X' HEXDIGIT+;
HEXSTRING:              'X' '\'' HEXDIGIT+ '\'';

BITNUMBER:              '0B' ('0' | '1')+;
BITSTRING:              'B' '\'' ('0' | '1')+ '\'';

NCHAR_TEXT:             'N' SINGLE_QUOTED_TEXT;

IDENTIFIER:             LETTER_WHEN_UNQUOTED+;

fragment LETTER_WHEN_UNQUOTED:
    '0'..'9'
    | 'A'..'Z' // Only upper case, as we use a case insensitive parser (insensitive only for ASCII).
    | '$'
    | '_'
    | '\u0080'..'\uffff'
;

qualified_identifier:
    IDENTIFIER ( options { greedy = true; }: DOT_SYMBOL IDENTIFIER)?
;

除了输入t1.1_d之类的非常具体的情况之外,这个工作大部分都很好,它应该被解析为2个用点连接的标识符。会发生什么是.1匹配为float,即使后跟下划线和字母。

很清楚它的来源:LETTER_WHEN_UNQUOTED包括数字,因此'1'既可以是整数,也可以是标识符。但规则顺序应该注意将其解析为整数,如同意图(并且通常是)。

但是,我很困惑t1.1_d输入导致浮动规则启动,并会欣赏一些指针来解决这个问题。只要我在点后添加一个空格一切都很好,但这显然不是一个真正的解决方案。

当我将IDENTIFIER规则移到其他规则之前时,我遇到了新的麻烦,因为其他几个规则再也无法匹配了。在IDENTIFIER规则之后移动FLOAT规则也不能解决问题(但至少不会产生新问题)。在这种情况下,我们会看到实际问题:如果直接后跟数字,则点总是与FLOAT规则匹配。在我的情况下,我该怎么做才能使它不匹配?

1 个答案:

答案 0 :(得分:0)

问题是词法分析器独立于解析器运行。当面对输入字符串t1.1_d时,词法分析器将首先消耗IDENTIFIER,离开.1_d。您现在希望它与DOT_SYMBOL匹配,然后是IDENTIFIER。但是,词法分析器将始终匹配最长的令牌,从而导致FLOAT匹配.1

IDENTIFIER之前移动FLOAT无效,因为'。'不是有效的IDENTIFIER符号,因此当它以.开头时,根本无法与输入匹配。

注意Java和co。不允许标识符以数字开头,可能是为了避免这些问题。

一种可能的解决方案是将FLOAT规则更改为要求点前的数字:FLOAT: DIGITS '.' DIGITS ...

相关问题