未能匹配与 PEG 解析器匹配规则的字符

问题描述

我正在尝试解析 Java 风格的浮点数(接受数字中间的下划线)并简化了 Java spec 中的语法:

float_lit = [[DIGITS] '.'] DIGITS [FLOAT_EXP] [FLOAT_SUFFIX] ;

DIGITS = /\d[\d_]*\d/ | /\d/ ;
FLOAT_EXP = ( 'e' | 'E' ) [ '+' | '-' ] DIGITS ;
FLOAT_SUFFIX = 'f' | 'F' | 'd' | 'D' ;

不幸的是,它不接受“1e10”输入,奇怪地无法匹配 FLOAT_EXP 中的“e”,如下面的跟踪所示:

<float_lit ~1:1
1e10
<DIGITS<float_lit ~1:1
1e10
!'' /\d[\d_]*?\d/
1e10
>'1' /\d/
e10
>DIGITS<float_lit ~1:2
e10
!'.'
e10
<DIGITS<float_lit ~1:1
1e10
>DIGITS<float_lit ~1:2
e10
<FLOAT_EXP<float_lit ~1:2
e10
!'e'
e10
!'E'
e10
!FLOAT_EXP<float_lit ~1:2
e10
<FLOAT_SUFFIX<float_lit ~1:2
e10
!'f'
e10
!'F'
e10
!'d'
e10
!'D'
e10
!FLOAT_SUFFIX<float_lit ~1:2
e10
>float_lit ~1:2
e10
'1'

谁能指出我做错了什么?

解决方法

这里的问题是 Tatsu 的 nameguard 令牌。由于令牌后面的字符是字母数字,因此不匹配以防止急于消耗令牌。

解决方案是使用正则表达式而不是标记选择来匹配这些字符:

float_lit    = [[DIGITS '.'] DIGITS [FLOAT_EXP] [FLOAT_SUFFIX] ;
DIGITS       = /\d[\d_]*\d/ | /\d/ ;
FLOAT_EXP    = /[eE][+-]?/ DIGITS ;
FLOAT_SUFFIX = /[fFdD]/ ;