mirror of
https://gitee.com/openharmony/third_party_rust_nom
synced 2024-11-23 07:29:54 +00:00
d85878e26a
since we now have specialized versions of a lot of parsers for streaming or complete input cases, we can remove the awkward types CompleteByteSlice and CompleteStr, along with uses of the AtEof trait that were present in most combinators. This change simplifies the code, and shows (especially in the arithmetic expressions parser tests) that the new function based solution can perform the same work as macros while simplifying the code on complete input
282 lines
6.6 KiB
Rust
282 lines
6.6 KiB
Rust
//#![feature(trace_macros)]
|
|
#![allow(dead_code)]
|
|
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
|
|
|
|
#[macro_use]
|
|
extern crate nom;
|
|
|
|
use nom::{character::{is_digit, streaming::space}, Err, IResult, Needed, error::ErrorKind, number::streaming::le_u64};
|
|
|
|
#[allow(dead_code)]
|
|
struct Range {
|
|
start: char,
|
|
end: char,
|
|
}
|
|
|
|
pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
|
|
if !input.is_empty() {
|
|
Ok((&input[1..], input[0] as char))
|
|
} else {
|
|
Err(Err::Incomplete(Needed::Size(1)))
|
|
}
|
|
}
|
|
|
|
//trace_macros!(true);
|
|
|
|
#[allow(dead_code)]
|
|
named!(range<&[u8], Range>,
|
|
alt!(
|
|
do_parse!(
|
|
start: take_char >>
|
|
tag!("-") >>
|
|
end: take_char >>
|
|
(Range {
|
|
start: start,
|
|
end: end,
|
|
})
|
|
) |
|
|
map!(
|
|
take_char,
|
|
|c| {
|
|
Range {
|
|
start: c,
|
|
end: c,
|
|
}
|
|
}
|
|
)
|
|
)
|
|
);
|
|
|
|
#[allow(dead_code)]
|
|
named!(literal<&[u8], Vec<char> >,
|
|
map!(
|
|
many1!(take_char),
|
|
|cs| {
|
|
cs
|
|
}
|
|
)
|
|
);
|
|
|
|
#[test]
|
|
fn issue_58() {
|
|
let _ = range(&b"abcd"[..]);
|
|
let _ = literal(&b"abcd"[..]);
|
|
}
|
|
|
|
//trace_macros!(false);
|
|
|
|
#[cfg(feature = "std")]
|
|
mod parse_int {
|
|
use nom::HexDisplay;
|
|
use nom::{IResult, character::streaming::{digit, space}};
|
|
use std::str;
|
|
|
|
named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));
|
|
|
|
fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
|
|
println!("{}", input.to_hex(8));
|
|
do_parse!(
|
|
input,
|
|
opt!(complete!(space)) >> res: map!(complete!(digit), |x| {
|
|
println!("x: {:?}", x);
|
|
let result = str::from_utf8(x).unwrap();
|
|
println!("Result: {}", result);
|
|
println!("int is empty?: {}", x.is_empty());
|
|
match result.parse() {
|
|
Ok(i) => i,
|
|
Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
|
|
}
|
|
}) >> (res)
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn issue_142() {
|
|
let subject = parse_ints(&b"12 34 5689a"[..]);
|
|
let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
|
|
assert_eq!(subject, expected);
|
|
|
|
let subject = parse_ints(&b"12 34 5689 "[..]);
|
|
let expected = Ok((&b" "[..], vec![12, 34, 5689]));
|
|
assert_eq!(subject, expected)
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn usize_length_bytes_issue() {
|
|
use nom::number::streaming::be_u16;
|
|
let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_bytes!(b"012346", be_u16);
|
|
}
|
|
|
|
/*
|
|
DOES NOT COMPILE
|
|
#[test]
|
|
fn issue_152() {
|
|
named!(take4, take!(4));
|
|
named!(xyz, tag!("XYZ"));
|
|
named!(abc, tag!("abc"));
|
|
|
|
|
|
named!(sw,
|
|
switch!(take4,
|
|
b"abcd" => xyz |
|
|
b"efgh" => abc
|
|
)
|
|
);
|
|
}
|
|
*/
|
|
|
|
#[test]
|
|
fn take_till_issue() {
|
|
named!(nothing, take_till!(call!(|_| true)));
|
|
|
|
assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
|
|
assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
|
|
}
|
|
|
|
named!(
|
|
issue_498<Vec<&[u8]>>,
|
|
separated_nonempty_list!(opt!(space), tag!("abcd"))
|
|
);
|
|
|
|
named!(issue_308(&str) -> bool,
|
|
do_parse! (
|
|
tag! ("foo") >>
|
|
b: alt_complete! (
|
|
map! (tag! ("1"), |_: &str|->bool {true}) |
|
|
value! (false)
|
|
) >>
|
|
(b) ));
|
|
|
|
#[cfg(feature = "alloc")]
|
|
fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
|
|
do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
|
|
}
|
|
|
|
#[test]
|
|
fn issue_655() {
|
|
use nom::character::streaming::{line_ending, not_line_ending};
|
|
named!(twolines(&str) -> (&str, &str),
|
|
do_parse!(
|
|
l1 : not_line_ending >>
|
|
line_ending >>
|
|
l2 : not_line_ending >>
|
|
line_ending >>
|
|
((l1, l2))
|
|
)
|
|
);
|
|
|
|
assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
|
|
assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
|
|
assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
|
|
assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
|
|
}
|
|
|
|
#[test]
|
|
fn issue_721() {
|
|
named!(f1<&str, u16>, parse_to!(u16));
|
|
named!(f2<&str, String>, parse_to!(String));
|
|
assert_eq!(f1("1234"), Ok(("", 1234)));
|
|
assert_eq!(f2("foo"), Ok(("", "foo".to_string())));
|
|
//assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
|
|
//assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
|
|
}
|
|
|
|
#[cfg(feature = "alloc")]
|
|
named!(issue_717<&[u8], Vec<&[u8]> >,
|
|
separated_list!(tag!([0x0]), is_not!([0x0u8]))
|
|
);
|
|
|
|
struct NoPartialEq {
|
|
value: i32,
|
|
}
|
|
|
|
named!(issue_724<&str, i32>,
|
|
do_parse!(
|
|
metadata: permutation!(
|
|
map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
|
|
map!(tag!("world"), |_| NoPartialEq { value: 2 })
|
|
) >>
|
|
(metadata.0.value + metadata.1.value)
|
|
)
|
|
);
|
|
|
|
#[test]
|
|
fn issue_752() {
|
|
assert_eq!(
|
|
Err::Error(("ab", nom::error::ErrorKind::ParseTo)),
|
|
parse_to!("ab", usize).unwrap_err()
|
|
)
|
|
}
|
|
|
|
fn atom_specials(c: u8) -> bool {
|
|
c == b'q'
|
|
}
|
|
|
|
named!(
|
|
capability<&str>,
|
|
do_parse!(tag!(" ") >> _atom: map_res!(take_till1!(atom_specials), std::str::from_utf8) >> ("a"))
|
|
);
|
|
|
|
#[test]
|
|
fn issue_759() {
|
|
assert_eq!(capability(b" abcqd"), Ok((&b"qd"[..], "a")));
|
|
}
|
|
|
|
named_args!(issue_771(count: usize)<Vec<u32>>,
|
|
length_count!(value!(count), call!(nom::number::streaming::be_u32))
|
|
);
|
|
|
|
/// This test is in a separate module to check that all required symbols are imported in
|
|
/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
|
|
/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
|
|
mod issue_780 {
|
|
named!(issue_780<&str, String>,
|
|
escaped_transform!(call!(::nom::character::streaming::alpha), '\\', tag!("n"))
|
|
);
|
|
}
|
|
|
|
// issue 617
|
|
named!(digits, take_while1!( is_digit ));
|
|
named!(multi_617<&[u8], () >, fold_many0!( digits, (), |_, _| {}));
|
|
|
|
// Sad :(
|
|
named!(multi_617_fails<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));
|
|
|
|
mod issue_647 {
|
|
use nom::{Err, number::streaming::be_f64, error::ErrorKind};
|
|
pub type Input<'a> = &'a [u8];
|
|
|
|
#[derive(PartialEq, Debug, Clone)]
|
|
struct Data {
|
|
c: f64,
|
|
v: Vec<f64>
|
|
}
|
|
|
|
fn list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<(&'a [u8], ErrorKind)>> {
|
|
separated_list_complete!(input, tag!(","),be_f64)
|
|
}
|
|
|
|
named!(data<Input,Data>, map!(
|
|
do_parse!(
|
|
c: be_f64 >>
|
|
tag!("\n") >>
|
|
v: call!(list,&c) >>
|
|
(c,v)
|
|
), |(c,v)| {
|
|
Data {
|
|
c: c,
|
|
v: v
|
|
}
|
|
}
|
|
));
|
|
}
|
|
|
|
named!(issue_775, take_till1!(|_| true));
|
|
|
|
#[test]
|
|
fn issue_848_overflow_incomplete_bits_to_bytes() {
|
|
named!(parser<&[u8], &[u8]>, bits!(bytes!(take!(0x2000000000000000))));
|
|
assert_eq!(parser(&b""[..]), Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge))));
|
|
}
|