首页 > 解决方案 > Antlr4:用双点解析点尾浮点数

问题描述

我正在尝试用点尾浮点数和双点测距数组解析句子,但无法做到。

这是我的语法文件

grammar foo;

Digits
    :   [0-9]+
    ;

Real
    :   Digits* '.' Digits+
    |   Digits+ '.' Digits*
    ;

Range
    :   '..'
    ;

Whitespace
    :   [ \t]+
        -> skip
    ;

Newline
    :   (   '\r' '\n'?
        |   '\n'
        )
        -> skip
    ;

range
    :   Digits Range Digits
    ;

和(文件名为foo.c

代码1:

1..2

代码2:

1 ..2

我使用以下来编译和测试:

antlr4 foo.g4
javac foo*.java
grun foo range -gui foo.c

代码 1 会有错误:

line 1:2 token recognition error at: '. '
line 1:0 extraneous input '1.' expecting Digits
line 1:5 mismatched input '<EOF>' expecting '..'

但是我可以使用代码 2 来实现。

添加额外的空间使其正确,但我想要一个可以解析代码 1 而没有额外空间的语法。

标签: antlr4

解决方案


这就是 ANTLR 词法分析器的工作方式:它尝试匹配尽可能多的字符。所以输入1..2产生 2 个Real标记1.和,而.2不是 3 个标记Digits和。RangeDigits

要创建 3 个标记,您必须在词法分析器中添加一个谓词。尝试这样的事情:

FLOAT
 : [0-9]+ '.' {_input.LA(1) != '.'}?
 | [0-9]* '.' [0-9]+
 ;

INT
 : [0-9]+
 ;

RANGE
 : '..'
 ;

SPACE
 : [ \t\r\n] -> skip
 ;

如果我根据上面的规则创建一个词法分析器,并将其输入 input "1 2. .34 56..7 8.99999",我会得到以下标记:

INT        '1'
FLOAT      '2.'
FLOAT      '.34'
INT        '56'
RANGE      '..'
INT        '7'
FLOAT      '8.99999'

推荐阅读