#parser-combinator #parser #combinator

可取消的_解析器

一个侧重于错误处理的解析器组合库

8个版本

0.2.6 2021年11月2日
0.2.5 2021年11月2日
0.2.4 2021年4月29日
0.2.3 2019年2月2日
0.1.0 2018年10月10日

解析器工具中排名128


用于ucg

Apache-2.0

70KB
1.5K SLoC

可取消的解析器

Build Status

一个在Rust中使用的侧重于错误处理的解析器组合库。在宏组合方法上深受nom的影响。


lib.rs:

一个具有偏见的解析器组合库,侧重于完全可取消的解析和易于错误处理。

宏组合方法深受nom的影响。它关注于简单易用的组合器API和易于错误处理。

我们有一系列宏,用于辅助生成或处理各种类型的错误。

简单的URL解析。

#[macro_use]
extern crate abortable_parser;
use abortable_parser::iter::StrIter;
use abortable_parser::{Result, eoi, ascii_ws};

make_fn!(proto<StrIter, &str>,
    do_each!(
        proto => until!(text_token!("://")),
        _ => must!(text_token!("://")),
        (proto)
    )
);

make_fn!(domain<StrIter, &str>,
    do_each!(
        // domains do not start with a slash
        _ => peek!(not!(text_token!("/"))),
        domain => until!(either!(
            discard!(text_token!("/")),
            discard!(ascii_ws),
            eoi)),
        (domain)
    )
);

make_fn!(path<StrIter, &str>,
     until!(either!(discard!(ascii_ws), eoi))
);

make_fn!(full_url<StrIter, (Option<&str>, Option<&str>, Option<&str>)>,
    do_each!(
        protocol => proto,
        // If we match the protocol then we must have a domain.
        // This is an example of an unrecoverable parsing error so we
        // abort with the must! macro if it doesn't match.
        domain => must!(domain),
        path => optional!(path),
        (Some(protocol), Some(domain), path)
    )
);

make_fn!(relative_url<StrIter, (Option<&str>, Option<&str>, Option<&str>)>,
    do_each!(
        _ => not!(either!(text_token!("//"), proto)),
        // we require a valid path for relative urls.
        path => path,
        (None, None, Some(path))
    )
);

make_fn!(url<StrIter, (Option<&str>, Option<&str>, Option<&str>)>,
    either!(
        full_url,
        relative_url,
    )
);

let iter = StrIter::new("http://example.com/some/path ");
let result = url(iter);
assert!(result.is_complete());
if let Result::Complete(_, (proto, domain, path)) = result {
    assert!(proto.is_some());
    assert!(domain.is_some());
    if let Some(domain) = domain {
        assert_eq!(domain, "example.com");
    }
    assert!(path.is_some());
    if let Some(path) = path {
        assert_eq!(path, "/some/path");
    }
}

let bad_input = StrIter::new("http:///some/path");
let bad_result = url(bad_input);
assert!(bad_result.is_abort());

无运行时依赖