在我的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,它应该被解析为两个与点连接的标识符。所发生的情况是,即使.1后面跟着下划线和字母,它也被匹配为浮点数。
很明显,这是从何而来的: LETTER_WHEN_UNQUOTED包含数字,因此'1‘既可以是整数,也可以是标识符。但是规则顺序应该注意将其解析为整数,就像有意的那样(通常也是如此)。
但是,我对t1.1_d输入感到困惑,它会导致浮点数规则的产生,并希望得到一些解决这个问题的指针。只要我在点后加一个空格,一切都很好,但这显然不是一个真正的解决方案。
当我在其他规则之前移动标识符规则时,会遇到新的麻烦,因为其他几条规则那时无法匹配。在标识符规则之后移动浮点规则也不会解决问题(但至少不会产生新的问题)。在这种情况下,我们看到了实际的问题:如果直接跟在数字后面,那么点总是由浮点规则匹配的。在我的情况下,我能做什么使它与之不匹配呢?
发布于 2015-02-24 17:09:40
问题是,lexer独立于解析器运行。当面对输入字符串t1.1_d时,lexer将首先使用一个IDENTIFIER,离开.1_d。现在您希望它与DOT_SYMBOL匹配,然后是IDENTIFIER。但是,lexer将始终匹配最长的可能令牌,从而导致浮点匹配.1。
在IDENTIFIER之前移动FLOAT是没有帮助的,因为“。”不是有效的IDENTIFIER符号,因此在输入以.开头时根本无法匹配。
注意Java和co.不要让标识符从数字开始,这可能是为了避免这类问题。
一种可能的解决方案是更改FLOAT规则以要求在点:FLOAT: DIGITS '.' DIGITS ...之前使用数字。
https://stackoverflow.com/questions/28699788
复制相似问题