rust - 使用 nom 从输入中识别 float

标签 rust parser-combinators

我正在尝试使用 nom解析基于文本的协议(protocol)。该协议(protocol)可以包含以下形式的浮点值:

[-]digit+[.digit+]

例子有:

  • -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() }
       )
);

第一个替代解析器识别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 (

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

最佳答案

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

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

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

此代码的主要棘手之处在于需要使用 complete! 来强制 decimal 解析器为全有或全无。

#[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"[..]));
}

我没有将字节转换为有趣的东西,这会使代码困惑,而且我真的不知道如何用它做一些有用的事情。 ^_^

关于rust - 使用 nom 从输入中识别 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37735624/

相关文章:

rust - 按值从原始类型引用复制的惯用方法是什么?

rust - 如何将 Entry API 与仅在 Entry 为空时才构建的昂贵 key 一起使用?

python - 如何迭代 YAML 文件以给出 PYTHON 中不同列表中项目的所有可能组合

java - 强制正则表达式匹配可选组

rust - 如何推断函数的返回类型?

rust - 从 future 流中获取所有可用项目(非阻塞)

rust - 在模块中派生可编码特征不起作用

parsing - 避免在解析器库中使用解析器失败

haskell - 使用解析器组合器解析 Haskell 本身

Scala PackratParser 忽略失败解析器