3 个版本 (破坏性更新)

0.3.0 2018年12月15日
0.2.0 2018年12月13日
0.1.0 2018年12月12日

#234 in 解析工具

Apache-2.0

27KB
409

banjin

Build Status Crates.io Documentation dependency status

手动解析的简单代码生成器

属性

结构体

有几个属性可以控制解析器的行为,每个属性都附加到结构体的字段上

  • starts_with = <prefix> - 指定下一个解析步骤应该开始的字符串(可以堆叠)。如果缺少前缀,则错误。
  • ends_with = <prefix> - 指定解析步骤应该结束的字符串(可以堆叠)。如果缺少后缀,则错误。如果为空,则期望EOF。
  • skip = <chars> - 指定要跳过的字符,直到不遇到字符串中指定的字符。
  • skip(ws) - 指定要跳过所有空白字符。
  • format(<format>) - 指定应包含要解析的值的字符列表。
  • format(not(<format>)) - 指定应包含要解析的值的字符列表。
格式
  • 文字字符串 - 当字符串被指定为 format 的参数时,它被用作字符集。
  • numeric - 当指定时,使用 char::is_numeric() 进行匹配
  • digit(<base>) - 当指定时,使用 char::is_digit(<base>) 进行匹配
  • ascii - 当指定时,使用 char::is_ascii()
  • alphabetic - 当指定时,使用 char::is_alphabetic()

枚举

  • format = <format> - 指定要匹配的字符串。
  • case - 指定大小写敏感匹配。默认情况下是不区分大小写的。
  • default - 指定变体使用默认值。应仅接受单个 String,并且只能有一个

使用方法

结构体

use std::str::FromStr;

#[derive(banjin::Parser)]
pub struct Data {
    #[starts_with = "prefix"]
    #[skip(ws)]
    #[starts_with = "+"]
    #[skip(ws)]
    #[format(ascii)]
    #[format(digit(10))]
    pub first: u32,
    #[skip(ws)]
    #[format(not("d"))]
    #[format("13")]
    #[ends_with = "d"]
    #[ends_with = ""]
    pub second: String,
}

fn main() {
    let data = Data::from_str("prefix + 666   13d").expect("Parse");
    assert_eq!(data.first, 666);
    assert_eq!(data.second, "13");

    let data = Data::from_str("prefix + 666   13");
    assert!(data.is_err());

    let data = Data::from_str("prefix 666   13d");
    assert!(data.is_err());

    let data = Data::from_str("prefix + 666   13dg");
    assert!(data.is_err());

    let data = Data::from_str("");
    assert!(data.is_err());
}

枚举

use std::str::FromStr;

#[derive(banjin::Parser, PartialEq, Eq, Debug)]
enum Gender {
    Male,
    #[case]
    Female,
    #[default]
    Other(String)
}

fn main() {
    let gender = Gender::from_str("male").expect("Parse");
    assert_eq!(gender, Gender::Male);

    let gender = Gender::from_str("female").expect("Parse");
    match gender {
        Gender::Other(text) => assert_eq!(text, "female"),
        _ => panic!("Unexpected!")
    }

    let gender = Gender::from_str("none").expect("Parse");
    match gender {
        Gender::Other(text) => assert_eq!(text, "none"),
        _ => panic!("Unexpected!")
    }
}

依赖关系

~2MB
~46K SLoC