使用nom识别输入的浮点数

tro*_*ine 2 parser-combinators rust

我正在尝试使用nom来解析基于文本的协议.此协议可以具有以下形式的浮点值:

[-]digit+[.digit+]
Run Code Online (Sandbox Code Playgroud)

其中的例子是:

  • -10.0
  • 10.0
  • 10

我构建的nom解析器是为了识别这个......不漂亮.它也不太明显.到目前为止我得到了什么:

named!(float_prs <&[u8], f64>,
       alt!(
           take_while!(nom::is_digit) => {|x| FromStr::from_str(std::str::from_utf8(x).unwrap()).unwrap()} |
           recognize!(chain!(
               take_while!(nom::is_digit) ~
                   tag!(".") ~
                   take_while!(nom::is_digit),
               || {})
           ) => {|x: &[u8]| FromStr::from_str(std::str::from_utf8(x).unwrap()).unwrap() }
       )
);
Run Code Online (Sandbox Code Playgroud)

第一个替代解析器识别digit+,第二个是尝试识别digit+.digit+但是

<nom macros>:5:38: 5:62 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<nom macros>:5 let index = ( $ i ) . offset ( i ) ; $ crate:: IResult:: Done (
Run Code Online (Sandbox Code Playgroud)

-digit上面没有提到识别等.有大量的重复,意图非常模糊.是否有更好的方法来解析[-]digit+[.digit+]我没有看到的?

She*_*ter 9

仅仅因为nom大量使用宏来完成它的肮脏工作,不要忘记你仍然可以应用正常的编程最佳实践.具体而言,将问题分解为更小的部分并组成它们.

在nom中,这可以通过chain!宏来实现,它允许您构建组件解析器,并named!为它们提供有用的名称.

我建议为数字的三个部分创建子解析器 - 可选符号,必需的整数部分和可选的小数部分.请注意,digit已经拉入多个连续的数字字符.

这段代码的主要棘手之处在于需要使用complete!强制decimal解析器为all-or-nothing.

#[macro_use]
extern crate nom;

use nom::digit;

named!(negative, tag!("-"));

named!(decimal, complete!(do_parse!(
    tag!(".")  >>
    val: digit >>
    (val)
)));

named!(floating_point<(Option<&[u8]>, &[u8], Option<&[u8]>)>, tuple!(
    opt!(negative), digit, opt!(decimal)
));

fn main() {
    println!("{:?}", floating_point(&b"0"[..]));
    println!("{:?}", floating_point(&b"0."[..]));
    println!("{:?}", floating_point(&b"0.0"[..]));
    println!("{:?}", floating_point(&b"-0"[..]));
    println!("{:?}", floating_point(&b"-0."[..]));
    println!("{:?}", floating_point(&b"-0.0"[..]));
}
Run Code Online (Sandbox Code Playgroud)

我已经把字节的任何转换都留给了有趣的东西,它会使代码混乱,我真的不知道如何对它做一些有用的事情.^ _ ^