#parser-combinator #tokens #slice #string #methods #location #free

无需 std yap

另一个解析器库。一个轻量级、无依赖的解析器组合灵感的实用方法集合,用于解析字符串和切片。

19 个版本 (11 个重大变更)

0.12.0 2023年11月18日
0.11.0 2023年7月14日
0.10.0 2023年3月8日
0.8.1 2022年12月9日
0.7.1 2021年11月27日

#12 in 解析器工具

Download history 9667/week @ 2024-03-31 7167/week @ 2024-04-07 5852/week @ 2024-04-14 6063/week @ 2024-04-21 5316/week @ 2024-04-28 5698/week @ 2024-05-05 5682/week @ 2024-05-12 5002/week @ 2024-05-19 5175/week @ 2024-05-26 6692/week @ 2024-06-02 5483/week @ 2024-06-09 5745/week @ 2024-06-16 6266/week @ 2024-06-23 5350/week @ 2024-06-30 6471/week @ 2024-07-07 7724/week @ 2024-07-14

每月下载量26,266
用于 6 个 crate (5 个直接使用)

MIT 许可证

115KB
2K SLoC

Yap:另一个(rust)解析库

API docs

这个小型、零依赖的 crate 通过构建在 Iterator 接口上,帮助您解析输入字符串和切片。

这个 crate 的目标是提供您从解析器组合库中期望得到的功能,但不会让您完全沉浸在解析器组合的世界中,也不会强迫您使用新颖的返回类型、库提供的错误或基于解析器组合的控制流。我们牺牲了一些简洁性,以换取简单性。

一些特定的特性/目标

  • 出色的文档,几乎每个函数都提供了示例。
  • 优先考虑简洁性,以牺牲冗长性为代价。
  • 以迭代器为中心。在适用的情况下,组合器返回实现 Tokens/Iterator 的东西。
  • 允许在可能的地方返回用户定义的错误。一些函数有 _err 变体,以防您需要错误信息而它们又没有提供错误信息以保持简单。
  • 位置信息应该始终可用,以便您可以告诉用户出错的地点。请参阅 Tokens::offsetTokens::location()
  • 默认回溯。来自 Haskell 的 Parsec,这是一个合理的默认值。这意味着如果提供的解析函数之一无法解析某个内容,它将不会尝试消耗任何输入。
  • 公开所有“低级”函数。您可以根据需要保存和重置位置(请参阅 Tokens::location),并使用这些原语实现提供的任何函数。
  • 旨在“相对快速”。几乎在所有地方都避免分配(并允许您通过迭代器中心接口做到这一点),如果您需要“尽可能快”,可能会有更快的替代方案。

请查看 Tokens 特性以获取所有可用的解析方法,并查看每个方法的示例。

请查看 examples 文件夹以获取更深入的示例。

示例

use yap::{
    // This trait has all of the parsing methods on it:
    Tokens,
    // Allows you to use `.into_tokens()` on strings and slices,
    // to get an instance of the above:
    IntoTokens
};

// Step 1: convert our input into something implementing `Tokens`
// ================================================================

let mut tokens = "10 + 2 x 12-4,foobar".into_tokens();

// Step 2: Parse some things from our tokens
// =========================================

#[derive(PartialEq,Debug)]
enum Op { Plus, Minus, Multiply }
#[derive(PartialEq,Debug)]
enum OpOrDigit { Op(Op), Digit(u32) }

// The `Tokens` trait builds on `Iterator`, so we get a `next` method.
fn parse_op(t: &mut impl Tokens<Item=char>) -> Option<Op> {
    match t.next()? {
        '-' => Some(Op::Minus),
        '+' => Some(Op::Plus),
        'x' => Some(Op::Multiply),
        _ => None
    }
}

// We also get other useful functions..
fn parse_digits(t: &mut impl Tokens<Item=char>) -> Option<u32> {
    t.take_while(|c| c.is_digit(10))
     .parse::<u32, String>()
     .ok()
}

// As well as combinator functions like `sep_by_all` and `surrounded_by`..
let op_or_digit = tokens.sep_by_all(
    |t| t.surrounded_by(
        |t| parse_digits(t).map(OpOrDigit::Digit),
        |t| { t.skip_while(|c| c.is_ascii_whitespace()); }
    ),
    |t| parse_op(t).map(OpOrDigit::Op)
);

// Now we've parsed our input into OpOrDigits, let's calculate the result..
let mut current_op = Op::Plus;
let mut current_digit = 0;
for d in op_or_digit.into_iter() {
    match d {
        OpOrDigit::Op(op) => {
            current_op = op
        },
        OpOrDigit::Digit(n) => {
            match current_op {
                Op::Plus => { current_digit += n },
                Op::Minus => { current_digit -= n },
                Op::Multiply => { current_digit *= n },
            }
        },
    }
}
assert_eq!(current_digit, 140);

// Step 3: do whatever you like with the rest of the input!
// ========================================================

// This is available on the concrete type that strings
// are converted into (rather than on the `Tokens` trait):
let remaining = tokens.remaining();

assert_eq!(remaining, ",foobar");

无运行时依赖