diff options
author | David LeGare <legare@google.com> | 2022-03-02 16:21:20 +0000 |
---|---|---|
committer | David LeGare <legare@google.com> | 2022-03-02 16:21:20 +0000 |
commit | 061b49860e4f94f264cb1202713ebc68304e1292 (patch) | |
tree | 63d0f458744432dcb2f047ae214ace796e4a431d | |
parent | 7132b01d1e71be9dbca5a716c8e06ab1f59e0038 (diff) | |
download | nom-061b49860e4f94f264cb1202713ebc68304e1292.tar.gz |
Update nom to 7.1.0
Test: cd external/rust/crates && atest --host -c
Change-Id: Ia47ec422de996e2b4f54422817a49578a2d8eb75
-rw-r--r-- | .cargo_vcs_info.json | 4 | ||||
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | CHANGELOG.md | 42 | ||||
-rw-r--r-- | Cargo.toml | 55 | ||||
-rw-r--r-- | Cargo.toml.orig | 57 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | src/bits/complete.rs | 2 | ||||
-rw-r--r-- | src/bits/streaming.rs | 51 | ||||
-rw-r--r-- | src/branch/mod.rs | 12 | ||||
-rw-r--r-- | src/bytes/complete.rs | 14 | ||||
-rw-r--r-- | src/bytes/streaming.rs | 16 | ||||
-rw-r--r-- | src/combinator/mod.rs | 23 | ||||
-rw-r--r-- | src/internal.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 18 | ||||
-rw-r--r-- | src/multi/mod.rs | 12 | ||||
-rw-r--r-- | src/number/complete.rs | 85 | ||||
-rw-r--r-- | src/number/streaming.rs | 84 | ||||
-rw-r--r-- | src/sequence/mod.rs | 5 | ||||
-rw-r--r-- | src/str.rs | 8 | ||||
-rw-r--r-- | src/traits.rs | 2 | ||||
-rw-r--r-- | tests/blockbuf-arithmetic.rs | 321 | ||||
-rw-r--r-- | tests/issues.rs | 2 |
23 files changed, 301 insertions, 534 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index a624533..d603d8a 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "9678b061d3ed0a6b8e31ce569e024ec25f3dd354" + "sha1": "b6f79c4d375ae55e1fd1a35032ebb47a52ea3389" } -} +}
\ No newline at end of file @@ -23,7 +23,7 @@ rust_library { host_supported: true, crate_name: "nom", cargo_env_compat: true, - cargo_pkg_version: "7.0.0", + cargo_pkg_version: "7.1.0", srcs: ["src/lib.rs"], edition: "2018", features: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 49ef3f5..a1bff5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,38 @@ ### Changed +## 7.1.0 - 2021-11-04 + +### Thanks + +- @nickelc +- @Stargateur +- @NilsIrl +- @clonejo +- @Strytyp +- @schubart +- @jihchi +- @nipunn1313 +- @Gungy2 +- @Drumato +- @Alexhuszagh +- @Aehmlo +- @homersimpsons +- @dne +- @epage +- @saiintbrisson +- @pymongo + +### Changed + +- documentation fixes +- Ci fixes +- the move to minimal-lexical for float parsing introduced bugs that cannot be resolved right now, so this version moves back to using the standard lib' parser. *This is a performance regression**. If you have specific requirements around float parsing, you are strongly encouraged to use [recognize_float](https://docs.rs/nom/latest/nom/number/complete/fn.recognize_float.html) and another library to convert to a f32 or f64 + +### Added + +- alt now works with 1 elment tuples + ## 7.0.0 - 2021-08-21 This release fixes dependency compilation issues and strengthen the minimum supported Rust version (MSRV) policy. This is also the first release without the macros that were used since nom's beginning. @@ -84,7 +116,7 @@ This release was done thanks to the hard work of (by order of appearance in the - lots of documentation fixes - relax trait bounds -- workarounds for depenency issues with bitvec and memchr +- workarounds for dependency issues with bitvec and memchr ## 6.1.2 - 2021-02-15 @@ -245,7 +277,7 @@ containing example patterns. - removed the deprecated `whitespace` module - the default error type is now a struct (`nom::error::Error`) instead of a tuple - the `FromExternalError` allows wrapping the error returned by the function in the `map_res` combinator -- renamed the `dbg!` macro to avoid conficts with `std::dbg!` +- renamed the `dbg!` macro to avoid conflicts with `std::dbg!` - `separated_list` now allows empty elements @@ -256,7 +288,7 @@ containing example patterns. - `success`: returns a value without consuming the input - `satisfy`: checks a predicate over the next character - `eof` function combinator -- `consumed`: returnes the produced value and the consumed input +- `consumed`: returns the produced value and the consumed input - `length_count` function combinator - `into`: converts a parser's output and error values if `From` implementations are available - `IResult::finish()`: converts a parser's result to `Result<(I, O), E>` by removing the distinction between `Error` and `Failure` and panicking on `Incomplete` @@ -1124,7 +1156,7 @@ Considering the number of changes since the last release, this version can conta ## 0.3.11 - 2015-08-04 ### Thanks -- @bluss for remarking that the crate included random junk lying non commited in my local repository +- @bluss for remarking that the crate included random junk lying non committed in my local repository ### Fixed - cleanup of my local repository will ship less files in the crates, resulting in a smaller download @@ -1187,7 +1219,7 @@ Considering the number of changes since the last release, this version can conta ### Added - documentation for a few functions - the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error -- `named!` now handles thge alternative `named!(pub fun_name<OutputType>, ...)` +- `named!` now handles the alternative `named!(pub fun_name<OutputType>, ...)` ### Fixed - `filter!` now returns the whole input if the filter function never returned false @@ -12,7 +12,7 @@ [package] edition = "2018" name = "nom" -version = "7.0.0" +version = "7.1.0" authors = ["contact@geoffroycouprie.com"] include = ["CHANGELOG.md", "LICENSE", "README.md", ".gitignore", "Cargo.toml", "src/*.rs", "src/*/*.rs", "tests/*.rs", "doc/nom_recipes.md", "build.rs"] autoexamples = false @@ -31,15 +31,16 @@ lto = true codegen-units = 1 debug = true -[lib] -bench = false - [[example]] name = "json" path = "examples/json.rs" required-features = ["alloc"] [[example]] +name = "iterator" +path = "examples/iterator.rs" + +[[example]] name = "s_expression" path = "examples/s_expression.rs" required-features = ["alloc"] @@ -57,9 +58,6 @@ name = "arithmetic_ast" required-features = ["alloc"] [[test]] -name = "blockbuf-arithmetic" - -[[test]] name = "css" [[test]] @@ -100,51 +98,16 @@ name = "reborrow_fold" [[test]] name = "fnmut" required-features = ["alloc"] - -[[bench]] -name = "arithmetic" -path = "benches/arithmetic.rs" -harness = false - -[[bench]] -name = "number" -path = "benches/number.rs" -harness = false - -[[bench]] -name = "http" -path = "benches/http.rs" -harness = false - -[[bench]] -name = "ini" -path = "benches/ini.rs" -harness = false - -[[bench]] -name = "ini_str" -path = "benches/ini_str.rs" -harness = false - -[[bench]] -name = "json" -path = "benches/json.rs" -harness = false [dependencies.memchr] -version = "2.0" +version = "2.3" default-features = false [dependencies.minimal-lexical] -version = "0.1.2" -[dev-dependencies.criterion] -version = "0.3" - +version = "0.2.0" +default-features = false [dev-dependencies.doc-comment] version = "0.3" -[dev-dependencies.jemallocator] -version = "^0.3" - [dev-dependencies.proptest] version = "1.0.0" [build-dependencies.version_check] @@ -154,7 +117,7 @@ version = "0.9" alloc = [] default = ["std"] docsrs = [] -std = ["alloc", "memchr/use_std"] +std = ["alloc", "memchr/std", "minimal-lexical/std"] [badges.coveralls] branch = "master" repository = "Geal/nom" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index b2e176a..4e5b011 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,7 +1,7 @@ [package] name = "nom" -version = "7.0.0" +version = "7.1.0" authors = [ "contact@geoffroycouprie.com" ] description = "A byte-oriented, zero-copy, parser combinators library" license = "MIT" @@ -28,20 +28,19 @@ include = [ [features] alloc = [] -std = ["alloc", "memchr/use_std"] +std = ["alloc", "memchr/std", "minimal-lexical/std"] default = ["std"] docsrs = [] -[dependencies] -minimal-lexical = "0.1.2" +[dependencies.minimal-lexical] +version = "0.2.0" +default-features = false [dependencies.memchr] -version = "2.0" +version = "2.3" default-features = false [dev-dependencies] -criterion = "0.3" -jemallocator = "^0.3" doc-comment = "0.3" proptest = "1.0.0" @@ -57,9 +56,6 @@ debug = true lto = true codegen-units = 1 -[lib] -bench = false - [[test]] name = "arithmetic" @@ -68,9 +64,6 @@ name = "arithmetic_ast" required-features = ["alloc"] [[test]] -name = "blockbuf-arithmetic" - -[[test]] name = "css" [[test]] @@ -112,43 +105,14 @@ name = "reborrow_fold" name = "fnmut" required-features = ["alloc"] -[[bench]] -name = "arithmetic" -path = "benches/arithmetic.rs" -harness = false - -[[bench]] -name = "number" -path = "benches/number.rs" -harness = false - -[[bench]] -name = "http" -path = "benches/http.rs" -harness = false - -[[bench]] -name = "ini" -path = "benches/ini.rs" -harness = false - -[[bench]] -name = "ini_str" -path = "benches/ini_str.rs" -harness = false - -[[bench]] -name = "json" -path = "benches/json.rs" -harness = false - [[example]] name = "json" required-features = ["alloc"] path = "examples/json.rs" -#[[example]] -#name = "iterator" +[[example]] +name = "iterator" +path = "examples/iterator.rs" [[example]] name = "s_expression" @@ -164,3 +128,6 @@ path = "examples/string.rs" travis-ci = { repository = "Geal/nom" } coveralls = { repository = "Geal/nom", branch = "master", service = "github" } maintenance = { status = "actively-developed" } + +[workspace] +members = [".", "benchmarks/"] @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/nom/nom-7.0.0.crate" + value: "https://static.crates.io/crates/nom/nom-7.1.0.crate" } - version: "7.0.0" + version: "7.1.0" license_type: NOTICE last_upgrade_date { - year: 2021 - month: 9 - day: 23 + year: 2022 + month: 3 + day: 1 } } @@ -2,8 +2,8 @@ [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Join the chat at https://gitter.im/Geal/nom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Geal/nom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/Geal/nom.svg?branch=master)](https://travis-ci.org/Geal/nom) -[![Coverage Status](https://coveralls.io/repos/Geal/nom/badge.svg?branch=master)](https://coveralls.io/r/Geal/nom?branch=master) +[![Build Status](https://github.com/Geal/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/Geal/nom/actions/workflows/ci.yml) +[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=master)](https://coveralls.io/github/Geal/nom?branch=master) [![Crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom) [![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements) @@ -248,7 +248,9 @@ Here is a (non exhaustive) list of known projects using nom: [Elm](https://github.com/cout970/Elm-interpreter), [SystemVerilog](https://github.com/dalance/sv-parser), [Turtle](https://github.com/vandenoever/rome/tree/master/src/io/turtle), -[CSML](https://github.com/CSML-by-Clevy/csml-interpreter) +[CSML](https://github.com/CSML-by-Clevy/csml-interpreter), +[Wasm](https://github.com/Strytyp/wasm-nom), +[Pseudocode](https://github.com/Gungy2/pseudocode) - Interface definition formats: [Thrift](https://github.com/thehydroimpulse/thrust) - Audio, video and image formats: [GIF](https://github.com/Geal/gif.rs), diff --git a/src/bits/complete.rs b/src/bits/complete.rs index e9ad81a..b46bc7a 100644 --- a/src/bits/complete.rs +++ b/src/bits/complete.rs @@ -50,7 +50,7 @@ where ErrorKind::Eof, ))) } else { - let mut acc: O = (0 as u8).into(); + let mut acc: O = 0_u8.into(); let mut offset: usize = bit_offset; let mut remaining: usize = count; let mut end_offset: usize = 0; diff --git a/src/bits/streaming.rs b/src/bits/streaming.rs index 700b903..e8adc1c 100644 --- a/src/bits/streaming.rs +++ b/src/bits/streaming.rs @@ -24,7 +24,7 @@ where if input.input_len() * 8 < count + bit_offset { Err(Err::Incomplete(Needed::new(count as usize))) } else { - let mut acc: O = (0 as u8).into(); + let mut acc: O = 0_u8.into(); let mut offset: usize = bit_offset; let mut remaining: usize = count; let mut end_offset: usize = 0; @@ -78,3 +78,52 @@ where }) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_take_0() { + let input = [].as_ref(); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; + + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + + assert_eq!(result, Ok(((input, offset), 0))); + } + + #[test] + fn test_tag_ok() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b0001; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); + } + + #[test] + fn test_tag_err() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b1111; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!( + result, + Err(crate::Err::Error(crate::error::Error { + input: (input, offset), + code: ErrorKind::TagBits + })) + ); + } +} diff --git a/src/branch/mod.rs b/src/branch/mod.rs index 902d4e8..9df5a29 100644 --- a/src/branch/mod.rs +++ b/src/branch/mod.rs @@ -46,7 +46,7 @@ pub trait Alt<I, O, E> { /// like this: `alt(parser_a, alt(parser_b, parser_c))` /// /// ```rust -/// # #[macro_use] extern crate nom; +/// # use nom::error_position; /// # use nom::{Err,error::ErrorKind, Needed, IResult}; /// use nom::character::complete::{alpha1, digit1}; /// use nom::branch::alt; @@ -89,7 +89,6 @@ pub trait Permutation<I, O, E> { /// tuple of the parser results. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult}; /// use nom::character::complete::{alpha1, digit1}; /// use nom::branch::permutation; @@ -183,6 +182,15 @@ macro_rules! alt_trait_inner( alt_trait!(A B C D E F G H I J K L M N O P Q R S T U); +// Manually implement Alt for (A,), the 1-tuple type +impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>> + Alt<Input, Output, Error> for (A,) +{ + fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> { + self.0.parse(input) + } +} + macro_rules! permutation_trait( ( $name1:ident $ty1:ident $item1:ident diff --git a/src/bytes/complete.rs b/src/bytes/complete.rs index 8a0c88b..9375b1f 100644 --- a/src/bytes/complete.rs +++ b/src/bytes/complete.rs @@ -18,7 +18,6 @@ use crate::traits::{ /// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::tag; /// @@ -59,7 +58,6 @@ where /// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::tag_no_case; /// @@ -104,7 +102,6 @@ where /// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::is_not; /// @@ -138,7 +135,6 @@ where /// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::is_a; /// @@ -171,7 +167,6 @@ where /// takes the input and returns a bool)*. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::complete::take_while; /// use nom::character::is_alphabetic; @@ -203,7 +198,6 @@ where /// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_while1; /// use nom::character::is_alphabetic; @@ -238,7 +232,6 @@ where /// of range (m <= len <= n). /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_while_m_n; /// use nom::character::is_alphabetic; @@ -322,7 +315,6 @@ where /// takes the input and returns a bool)*. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::complete::take_till; /// @@ -354,7 +346,6 @@ where /// predicate matches the first input. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_till1; /// @@ -385,7 +376,6 @@ where /// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take; /// @@ -418,7 +408,6 @@ where /// if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_until; /// @@ -454,7 +443,6 @@ where /// if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::complete::take_until1; /// @@ -493,7 +481,6 @@ where /// * The third argument matches the escaped characters /// # Example /// ``` -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// # use nom::character::complete::digit1; /// use nom::bytes::complete::escaped; @@ -597,7 +584,6 @@ where /// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) /// /// ``` -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// # use std::str::from_utf8; /// use nom::bytes::complete::{escaped_transform, tag}; diff --git a/src/bytes/streaming.rs b/src/bytes/streaming.rs index 8deac13..e972760 100644 --- a/src/bytes/streaming.rs +++ b/src/bytes/streaming.rs @@ -16,7 +16,6 @@ use crate::traits::{ /// the input that matches the argument. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::tag; /// @@ -58,7 +57,6 @@ where /// the input that matches the argument with no regard to case. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::tag_no_case; /// @@ -104,7 +102,6 @@ where /// It will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::is_not; /// @@ -140,7 +137,6 @@ where /// or if the pattern reaches the end of the input. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::is_a; /// @@ -176,7 +172,6 @@ where /// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::take_while; /// use nom::character::is_alphabetic; @@ -212,7 +207,6 @@ where /// /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_while1; /// use nom::character::is_alphabetic; @@ -249,7 +243,6 @@ where /// /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_while_m_n; /// use nom::character::is_alphabetic; @@ -335,7 +328,6 @@ where /// /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::take_till; /// @@ -368,7 +360,6 @@ where /// end of input or if there was not match. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_till1; /// @@ -406,7 +397,6 @@ where /// /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::take; /// @@ -441,7 +431,6 @@ where /// contain the pattern or if the input is smaller than the pattern. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::bytes::streaming::take_until; /// @@ -481,7 +470,6 @@ where /// contain the pattern or if the input is smaller than the pattern. /// # Example /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::bytes::streaming::take_until1; /// @@ -521,7 +509,6 @@ where /// * The third argument matches the escaped characters /// # Example /// ``` -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// # use nom::character::complete::digit1; /// use nom::bytes::streaming::escaped; @@ -614,7 +601,6 @@ where /// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) /// /// ``` -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// # use std::str::from_utf8; /// use nom::bytes::streaming::{escaped_transform, tag}; @@ -629,7 +615,7 @@ where /// alt(( /// value("\\", tag("\\")), /// value("\"", tag("\"")), -/// value("n", tag("\n")), +/// value("\n", tag("n")), /// )) /// )(input) /// } diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index a2e59fb..7071cc7 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -56,7 +56,6 @@ where /// Maps a function on the result of a parser. /// /// ```rust -/// # #[macro_use] extern crate nom; /// use nom::{Err,error::ErrorKind, IResult,Parser}; /// use nom::character::complete::digit1; /// use nom::combinator::map; @@ -85,7 +84,6 @@ where /// Applies a function returning a `Result` over the result of a parser. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::character::complete::digit1; /// use nom::combinator::map_res; @@ -124,7 +122,6 @@ where /// Applies a function returning an `Option` over the result of a parser. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::character::complete::digit1; /// use nom::combinator::map_opt; @@ -163,7 +160,6 @@ where /// Applies a parser over the result of another one. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::character::complete::digit1; /// use nom::bytes::complete::take; @@ -195,7 +191,6 @@ where /// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::bytes::complete::take; /// use nom::number::complete::u8; @@ -210,11 +205,11 @@ where /// ``` pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>( mut parser: F, - applied_parser: G, + mut applied_parser: G, ) -> impl FnMut(I) -> IResult<I, O2, E> where F: Parser<I, O1, E>, - G: Fn(O1) -> H, + G: FnMut(O1) -> H, H: Parser<I, O2, E>, { move |input: I| { @@ -226,7 +221,6 @@ where /// Optional parser: Will return `None` if not successful. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::opt; /// use nom::character::complete::alpha1; @@ -257,7 +251,6 @@ where /// Calls the parser if the condition is met. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, IResult}; /// use nom::combinator::cond; /// use nom::character::complete::alpha1; @@ -295,7 +288,6 @@ where /// Tries to apply its parser without consuming the input. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::peek; /// use nom::character::complete::alpha1; @@ -326,7 +318,6 @@ where /// will succeed /// /// ``` -/// # #[macro_use] extern crate nom; /// # use std::str; /// # use nom::{Err, error::ErrorKind, IResult}; /// # use nom::combinator::eof; @@ -349,7 +340,6 @@ pub fn eof<I: InputLength + Clone, E: ParseError<I>>(input: I) -> IResult<I, I, /// Transforms Incomplete into `Error`. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::bytes::streaming::take; /// use nom::combinator::complete; @@ -377,7 +367,6 @@ where /// Succeeds if all the input has been consumed by its child parser. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::all_consuming; /// use nom::character::complete::alpha1; @@ -411,7 +400,6 @@ where /// parser. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::verify; /// use nom::character::complete::alpha1; @@ -449,7 +437,6 @@ where /// Returns the provided value if the child parser succeeds. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::value; /// use nom::character::complete::alpha1; @@ -474,7 +461,6 @@ where /// Succeeds if the child parser returns an error. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::not; /// use nom::character::complete::alpha1; @@ -503,7 +489,6 @@ where /// If the child parser was successful, return the consumed input as produced value. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::recognize; /// use nom::character::complete::{char, alpha1}; @@ -544,7 +529,6 @@ where /// Returned tuple is of the format `(consumed input, produced output)`. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::{consumed, value, recognize, map}; /// use nom::character::complete::{char, alpha1}; @@ -594,7 +578,6 @@ where /// transforms an error to failure /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::combinator::cut; /// use nom::character::complete::alpha1; @@ -622,7 +605,6 @@ where /// as long as the `Into` implementations are available /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::IResult; /// use nom::combinator::into; /// use nom::character::complete::alpha1; @@ -753,7 +735,6 @@ enum State<E> { /// specify the default case. /// /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err,error::ErrorKind, IResult}; /// use nom::branch::alt; /// use nom::combinator::{success, value}; diff --git a/src/internal.rs b/src/internal.rs index 762f3d8..8a3c6a1 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -259,7 +259,7 @@ pub trait Parser<I, O, E> { /// Creates a second parser from the output of the first one, then apply over the rest of the input fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O> where - G: Fn(O) -> H, + G: FnMut(O) -> H, H: Parser<I, O2, E>, Self: core::marker::Sized, { @@ -136,13 +136,13 @@ //! A parser in nom is a function which, for an input type `I`, an output type `O` //! and an optional error type `E`, will have the following signature: //! -//! ```rust,ignore +//! ```rust,compile_fail //! fn parser(input: I) -> IResult<I, O, E>; //! ``` //! //! Or like this, if you don't want to specify a custom error type (it will be `(I, ErrorKind)` by default): //! -//! ```rust,ignore +//! ```rust,compile_fail //! fn parser(input: I) -> IResult<I, O>; //! ``` //! @@ -445,29 +445,21 @@ pub use self::str::*; #[macro_use] pub mod error; -#[macro_use] +pub mod combinator; mod internal; mod traits; #[macro_use] -pub mod combinator; -#[macro_use] pub mod branch; -#[macro_use] -pub mod sequence; -#[macro_use] pub mod multi; +pub mod sequence; -#[macro_use] -pub mod bytes; -#[macro_use] pub mod bits; +pub mod bytes; -#[macro_use] pub mod character; mod str; -#[macro_use] pub mod number; #[cfg(feature = "docsrs")] diff --git a/src/multi/mod.rs b/src/multi/mod.rs index 9f72888..a119134 100644 --- a/src/multi/mod.rs +++ b/src/multi/mod.rs @@ -260,7 +260,6 @@ where /// * `sep` Parses the separator between list elements. /// * `f` Parses the elements of the list. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::multi::separated_list1; /// use nom::bytes::complete::tag; @@ -332,7 +331,6 @@ where /// * `n` The maximum number of iterations. /// * `f` The parser to apply. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::multi::many_m_n; /// use nom::bytes::complete::tag; @@ -399,7 +397,6 @@ where /// # Arguments /// * `f` The parser to apply. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::multi::many0_count; /// use nom::bytes::complete::tag; @@ -452,7 +449,6 @@ where /// # Arguments /// * `f` The parser to apply. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::multi::many1_count; /// use nom::bytes::complete::tag; @@ -509,7 +505,6 @@ where /// * `f` The parser to apply. /// * `count` How often to apply the parser. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::multi::count; /// use nom::bytes::complete::tag; @@ -562,7 +557,6 @@ where /// * `f` The parser to apply. /// * `buf` The slice to fill /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::multi::fill; /// use nom::bytes::complete::tag; @@ -616,7 +610,6 @@ where /// * `g` The function that combines a result of `f` with /// the current accumulator. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::multi::fold_many0; /// use nom::bytes::complete::tag; @@ -687,7 +680,6 @@ where /// * `g` The function that combines a result of `f` with /// the current accumulator. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::multi::fold_many1; /// use nom::bytes::complete::tag; @@ -768,7 +760,6 @@ where /// * `g` The function that combines a result of `f` with /// the current accumulator. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::multi::fold_many_m_n; /// use nom::bytes::complete::tag; @@ -847,7 +838,6 @@ where /// # Arguments /// * `f` The parser to apply. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::ErrorKind, Needed, IResult}; /// use nom::number::complete::be_u16; /// use nom::multi::length_data; @@ -892,7 +882,6 @@ where /// * `f` The parser to apply. /// * `g` The parser to apply on the subslice. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::number::complete::be_u16; /// use nom::multi::length_value; @@ -941,7 +930,6 @@ where /// * `f` The parser to apply to obtain the count. /// * `g` The parser to apply repeatedly. /// ```rust -/// # #[macro_use] extern crate nom; /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; /// use nom::number::complete::u8; /// use nom::multi::length_count; diff --git a/src/number/complete.rs b/src/number/complete.rs index c5553a4..d23079e 100644 --- a/src/number/complete.rs +++ b/src/number/complete.rs @@ -1426,6 +1426,40 @@ where )(input) } +// workaround until issues with minimal-lexical are fixed +#[doc(hidden)] +pub fn recognize_float_or_exceptions<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> +where + T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>, + T: Clone + Offset, + T: InputIter + InputTake + Compare<&'static str>, + <T as InputIter>::Item: AsChar, + T: InputTakeAtPosition, + <T as InputTakeAtPosition>::Item: AsChar, +{ + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed), + }) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + ))(input) +} + /// Recognizes a floating point number in text format and returns the integer, fraction and exponent parts of the input data /// /// *Complete version*: Can parse until the end of input. @@ -1444,7 +1478,7 @@ where let (i, sign) = sign(input.clone())?; //let (i, zeroes) = take_while(|c: <T as InputTakeAtPosition>::Item| c.as_char() == '0')(i)?; - let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0' as u8) { + let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') { Some(index) => i.take_split(index), None => i.take_split(i.input_len()), }; @@ -1452,7 +1486,7 @@ where let (i, mut integer) = match i .as_bytes() .iter() - .position(|c| !(*c >= b'0' as u8 && *c <= b'9' as u8)) + .position(|c| !(*c >= b'0' && *c <= b'9')) { Some(index) => i.take_split(index), None => i.take_split(i.input_len()), @@ -1472,8 +1506,8 @@ where let mut zero_count = 0usize; let mut position = None; for (pos, c) in i.as_bytes().iter().enumerate() { - if *c >= b'0' as u8 && *c <= b'9' as u8 { - if *c == b'0' as u8 { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { zero_count += 1; } else { zero_count = 0; @@ -1517,6 +1551,8 @@ where Ok((i, (sign, integer, fraction, exp))) } +use crate::traits::ParseTo; + /// Recognizes floating point number in text format and returns a f32. /// /// *Complete version*: Can parse until the end of input. @@ -1537,7 +1573,7 @@ where pub fn float<T, E: ParseError<T>>(input: T) -> IResult<T, f32, E> where T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>, - T: Clone + Offset, + T: Clone + Offset + ParseTo<f32> + Compare<&'static str>, T: InputIter + InputLength + InputTake, <T as InputIter>::Item: AsChar + Copy, <T as InputIter>::IterElem: Clone, @@ -1546,6 +1582,7 @@ where T: AsBytes, T: for<'a> Compare<&'a [u8]>, { + /* let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; let mut float: f32 = minimal_lexical::parse_float( @@ -1558,18 +1595,27 @@ where } Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => (Ok((i, f))), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } } -/// Recognizes floating point number in text format and returns a f32. +/// Recognizes floating point number in text format and returns a f64. /// /// *Complete version*: Can parse until the end of input. /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; -/// use nom::number::complete::float; +/// use nom::number::complete::double; /// /// let parser = |s| { -/// float(s) +/// double(s) /// }; /// /// assert_eq!(parser("11e-1"), Ok(("", 1.1))); @@ -1580,7 +1626,7 @@ where pub fn double<T, E: ParseError<T>>(input: T) -> IResult<T, f64, E> where T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>, - T: Clone + Offset, + T: Clone + Offset + ParseTo<f64> + Compare<&'static str>, T: InputIter + InputLength + InputTake, <T as InputIter>::Item: AsChar + Copy, <T as InputIter>::IterElem: Clone, @@ -1589,6 +1635,7 @@ where T: AsBytes, T: for<'a> Compare<&'a [u8]>, { + /* let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; let mut float: f64 = minimal_lexical::parse_float( @@ -1601,6 +1648,15 @@ where } Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => (Ok((i, f))), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } } #[cfg(test)] @@ -1608,7 +1664,6 @@ mod tests { use super::*; use crate::error::ErrorKind; use crate::internal::Err; - use crate::traits::ParseTo; use proptest::prelude::*; macro_rules! assert_parse( @@ -1942,6 +1997,7 @@ mod tests { "12.34", "-1.234E-12", "-1.234e-12", + "0.00000000000000000087", ]; for test in test_cases.drain(..) { @@ -1965,6 +2021,14 @@ mod tests { recognize_float(remaining_exponent), Err(Err::Failure(("", ErrorKind::Digit))) ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); } #[test] @@ -2050,6 +2114,7 @@ mod tests { ); } + #[cfg(feature = "std")] fn parse_f64(i: &str) -> IResult<&str, f64, ()> { match recognize_float(i) { Err(e) => Err(e), diff --git a/src/number/streaming.rs b/src/number/streaming.rs index 3ca445f..7c53ccc 100644 --- a/src/number/streaming.rs +++ b/src/number/streaming.rs @@ -1395,6 +1395,40 @@ where )(input) } +// workaround until issues with minimal-lexical are fixed +#[doc(hidden)] +pub fn recognize_float_or_exceptions<T, E: ParseError<T>>(input: T) -> IResult<T, T, E> +where + T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>, + T: Clone + Offset, + T: InputIter + InputTake + InputLength + Compare<&'static str>, + <T as InputIter>::Item: AsChar, + T: InputTakeAtPosition, + <T as InputTakeAtPosition>::Item: AsChar, +{ + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)), + crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed), + }) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float))) + }, + ))(input) +} + /// Recognizes a floating point number in text format and returns the integer, fraction and exponent parts of the input data /// /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. @@ -1413,7 +1447,7 @@ where let (i, sign) = sign(input.clone())?; //let (i, zeroes) = take_while(|c: <T as InputTakeAtPosition>::Item| c.as_char() == '0')(i)?; - let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0' as u8) { + let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') { Some(index) => i.take_split(index), None => i.take_split(i.input_len()), }; @@ -1422,7 +1456,7 @@ where let (i, mut integer) = match i .as_bytes() .iter() - .position(|c| !(*c >= b'0' as u8 && *c <= b'9' as u8)) + .position(|c| !(*c >= b'0' && *c <= b'9')) { Some(index) => i.take_split(index), None => i.take_split(i.input_len()), @@ -1442,8 +1476,8 @@ where let mut zero_count = 0usize; let mut position = None; for (pos, c) in i.as_bytes().iter().enumerate() { - if *c >= b'0' as u8 && *c <= b'9' as u8 { - if *c == b'0' as u8 { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { zero_count += 1; } else { zero_count = 0; @@ -1512,7 +1546,7 @@ pub fn float<T, E: ParseError<T>>(input: T) -> IResult<T, f32, E> where T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>, T: Clone + Offset, - T: InputIter + InputLength + InputTake + crate::traits::ParseTo<i32>, + T: InputIter + InputLength + InputTake + crate::traits::ParseTo<f32> + Compare<&'static str>, <T as InputIter>::Item: AsChar, <T as InputIter>::IterElem: Clone, T: InputTakeAtPosition, @@ -1520,6 +1554,7 @@ where T: AsBytes, T: for<'a> Compare<&'a [u8]>, { + /* let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; let mut float: f32 = minimal_lexical::parse_float( @@ -1532,19 +1567,28 @@ where } Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => (Ok((i, f))), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } } -/// Recognizes floating point number in text format and returns a f32. +/// Recognizes floating point number in text format and returns a f64. /// /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. /// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; -/// use nom::number::complete::float; +/// use nom::number::complete::double; /// /// let parser = |s| { -/// float(s) +/// double(s) /// }; /// /// assert_eq!(parser("11e-1"), Ok(("", 1.1))); @@ -1556,7 +1600,7 @@ pub fn double<T, E: ParseError<T>>(input: T) -> IResult<T, f64, E> where T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>, T: Clone + Offset, - T: InputIter + InputLength + InputTake + crate::traits::ParseTo<i32>, + T: InputIter + InputLength + InputTake + crate::traits::ParseTo<f64> + Compare<&'static str>, <T as InputIter>::Item: AsChar, <T as InputIter>::IterElem: Clone, T: InputTakeAtPosition, @@ -1564,6 +1608,7 @@ where T: AsBytes, T: for<'a> Compare<&'a [u8]>, { + /* let (i, (sign, integer, fraction, exponent)) = recognize_float_parts(input)?; let mut float: f64 = minimal_lexical::parse_float( @@ -1576,6 +1621,15 @@ where } Ok((i, float)) + */ + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_to() { + Some(f) => (Ok((i, f))), + None => Err(crate::Err::Error(E::from_error_kind( + i, + crate::error::ErrorKind::Float, + ))), + } } #[cfg(test)] @@ -1583,7 +1637,6 @@ mod tests { use super::*; use crate::error::ErrorKind; use crate::internal::{Err, Needed}; - use crate::traits::ParseTo; use proptest::prelude::*; macro_rules! assert_parse( @@ -2023,6 +2076,7 @@ mod tests { "12.34", "-1.234E-12", "-1.234e-12", + "0.00000000000000000087", ]; for test in test_cases.drain(..) { @@ -2046,6 +2100,14 @@ mod tests { recognize_float(remaining_exponent), Err(Err::Incomplete(Needed::new(1))) ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); } #[test] @@ -2131,7 +2193,9 @@ mod tests { ); } + #[cfg(feature = "std")] fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + use crate::traits::ParseTo; match recognize_float(i) { Err(e) => Err(e), Ok((i, s)) => { diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs index bf5dcfd..100c63f 100644 --- a/src/sequence/mod.rs +++ b/src/sequence/mod.rs @@ -12,6 +12,7 @@ use crate::internal::{IResult, Parser}; /// # Arguments /// * `first` The first parser to apply. /// * `second` The second parser to apply. +/// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; @@ -45,6 +46,7 @@ where /// # Arguments /// * `first` The opening parser. /// * `second` The second parser to get object. +/// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; @@ -78,6 +80,7 @@ where /// # Arguments /// * `first` The first parser to apply. /// * `second` The second parser to match an object. +/// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; @@ -113,6 +116,7 @@ where /// * `first` The first parser to apply. /// * `sep` The separator parser to apply. /// * `second` The second parser to apply. +/// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; @@ -151,6 +155,7 @@ where /// * `first` The first parser to apply and discard. /// * `second` The second parser to apply. /// * `third` The third parser to apply and discard. +/// /// ```rust /// # use nom::{Err, error::ErrorKind, Needed}; /// # use nom::Needed::Size; @@ -88,7 +88,7 @@ mod test { ); assert!( output == CONSUMED, - "Parser `take_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.", + "Parser `take_s` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); @@ -120,7 +120,7 @@ mod test { assert!( output == CONSUMED, "Parser `take_until`\ - doens't return the string it consumed on success. Expected `{}`, got `{}`.", + doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); @@ -281,7 +281,7 @@ mod test { ); assert!( output == CONSUMED, - "Parser `is_not` doens't return the string it consumed on success. Expected `{}`, got `{}`.", + "Parser `is_not` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); @@ -432,7 +432,7 @@ mod test { ); assert!( output == CONSUMED, - "Parser `is_a` doens't return the string it consumed on success. Expected `{}`, got `{}`.", + "Parser `is_a` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); diff --git a/src/traits.rs b/src/traits.rs index a073fd3..3c3053e 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -701,7 +701,7 @@ impl<'a> InputTakeAtPosition for &'a str { } } -/// Indicates wether a comparison was successful, an error, or +/// Indicates whether a comparison was successful, an error, or /// if more data was needed #[derive(Debug, PartialEq)] pub enum CompareResult { diff --git a/tests/blockbuf-arithmetic.rs b/tests/blockbuf-arithmetic.rs deleted file mode 100644 index 27a295f..0000000 --- a/tests/blockbuf-arithmetic.rs +++ /dev/null @@ -1,321 +0,0 @@ -/* -#[macro_use] -extern crate nom; -extern crate bytes; - -use nom::{Compare,CompareResult,InputLength,InputIter,Slice,HexDisplay}; - -use std::str; -use std::str::FromStr; -use bytes::{Buf,MutBuf}; -use bytes::buf::{BlockBuf,BlockBufCursor}; -use std::ops::{Range,RangeTo,RangeFrom,RangeFull}; -use std::iter::{Enumerate,Iterator}; -use std::fmt; -use std::cmp::{min,PartialEq}; - -#[derive(Clone,Copy)] -#[repr(C)] -pub struct BlockSlice<'a> { - buf: &'a BlockBuf, - start: usize, - end: usize, -} - -impl<'a> BlockSlice<'a> { - fn cursor(&self) -> WrapCursor<'a> { - let mut cur = self.buf.buf(); - cur.advance(self.start); - WrapCursor { - cursor: cur, - length: self.end - self.start, - } - } -} - -impl<'a> fmt::Debug for BlockSlice<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "BlockSlice {{ start: {}, end: {}, data:\n{}\n}}", self.start, self.end, self.buf.bytes().unwrap_or(&b""[..]).to_hex(16)) - } -} - -impl<'a> PartialEq for BlockSlice<'a> { - fn eq(&self, other: &BlockSlice<'a>) -> bool { - let bufs = (self.buf as *const BlockBuf) == (other.buf as *const BlockBuf); - self.start == other.start && self.end == other.end && bufs - } -} - -impl<'a> Slice<Range<usize>> for BlockSlice<'a> { - fn slice(&self, range:Range<usize>) -> Self { - BlockSlice { - buf: self.buf, - start: self.start + range.start, - //FIXME: check for valid end here - end: self.start + range.end, - } - } -} - -impl<'a> Slice<RangeTo<usize>> for BlockSlice<'a> { - fn slice(&self, range:RangeTo<usize>) -> Self { - self.slice(0..range.end) - } -} - -impl<'a> Slice<RangeFrom<usize>> for BlockSlice<'a> { - fn slice(&self, range:RangeFrom<usize>) -> Self { - self.slice(range.start..self.end - self.start) - } -} - -impl<'a> Slice<RangeFull> for BlockSlice<'a> { - fn slice(&self, _:RangeFull) -> Self { - BlockSlice { - buf: self.buf, - start: self.start, - end: self.end, - } - } -} - - -impl<'a> InputIter for BlockSlice<'a> { - type Item = u8; - type RawItem = u8; - type Iter = Enumerate<WrapCursor<'a>>; - type IterElem = WrapCursor<'a>; - - fn iter_indices(&self) -> Self::Iter { - self.cursor().enumerate() - } - fn iter_elements(&self) -> Self::IterElem { - self.cursor() - } - fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool { - self.cursor().position(|b| predicate(b)) - } - fn slice_index(&self, count:usize) -> Option<usize> { - if self.end - self.start >= count { - Some(count) - } else { - None - } - } -} - - -impl<'a> InputLength for BlockSlice<'a> { - fn input_len(&self) -> usize { - self.end - self.start - } -} - -impl<'a,'b> Compare<&'b[u8]> for BlockSlice<'a> { - fn compare(&self, t: &'b[u8]) -> CompareResult { - let len = self.end - self.start; - let blen = t.len(); - let m = if len < blen { len } else { blen }; - let reduced = self.slice(..m); - let b = &t[..m]; - - for (a,b) in reduced.cursor().zip(b.iter()) { - if a != *b { - return CompareResult::Error; - } - } - if m < blen { - CompareResult::Incomplete - } else { - CompareResult::Ok - } - } - - - #[inline(always)] - fn compare_no_case(&self, t: &'b[u8]) -> CompareResult { - let len = self.end - self.start; - let blen = t.len(); - let m = if len < blen { len } else { blen }; - let reduced = self.slice(..m); - let other = &t[..m]; - - if !reduced.cursor().zip(other).all(|(a, b)| { - match (a,*b) { - (0...64, 0...64) | (91...96, 91...96) | (123...255, 123...255) => a == *b, - (65...90, 65...90) | (97...122, 97...122) | (65...90, 97...122 ) |(97...122, 65...90) => { - a & 0b01000000 == *b & 0b01000000 - } - _ => false - } - }) { - CompareResult::Error - } else if m < blen { - CompareResult::Incomplete - } else { - CompareResult::Ok - } - } -} - -impl<'a,'b> Compare<&'b str> for BlockSlice<'a> { - fn compare(&self, t: &'b str) -> CompareResult { - self.compare(str::as_bytes(t)) - } - fn compare_no_case(&self, t: &'b str) -> CompareResult { - self.compare_no_case(str::as_bytes(t)) - } -} - -//Wrapper to implement Iterator on BlockBufCursor -pub struct WrapCursor<'a> { - pub cursor: BlockBufCursor<'a>, - pub length: usize, -} - -impl<'a> Iterator for WrapCursor<'a> { - type Item = u8; - fn next(&mut self) -> Option<u8> { - //println!("NEXT: length={}, remaining={}", self.length, self.cursor.remaining()); - if min(self.length, self.cursor.remaining()) > 0 { - self.length -=1; - Some(self.cursor.read_u8()) - } else { - None - } - } -} - -//Reimplement eat_separator instead of fixing iterators -#[macro_export] -macro_rules! block_eat_separator ( - ($i:expr, $arr:expr) => ( - { - use nom::{InputLength,InputIter,Slice}; - if ($i).input_len() == 0 { - Ok(($i, ($i).slice(0..0))) - } else { - match ($i).iter_indices().position(|(_, item)| { - for (_,c) in ($arr).iter_indices() { - if *c == item { return false; } - } - true - }) { - Some(index) => { - Ok((($i).slice(index..), ($i).slice(..index))) - }, - None => { - Ok((($i).slice(($i).input_len()..), $i)) - } - } - } - } - ) -); - -#[macro_export] -macro_rules! block_named ( - ($name:ident, $submac:ident!( $($args:tt)* )) => ( - fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, BlockSlice<'a>, u32> { - $submac!(i, $($args)*) - } - ); - ($name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => ( - fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, $o, u32> { - $submac!(i, $($args)*) - } - ); -); - -block_named!(sp, block_eat_separator!(&b" \t\r\n"[..])); - -macro_rules! block_ws ( - ($i:expr, $($args:tt)*) => ( - { - sep!($i, sp, $($args)*) - } - ) -); - -block_named!(digit, is_a!("0123456789")); - -block_named!(parens<i64>, block_ws!(delimited!( tag!("("), expr, tag!(")") )) ); - - -block_named!(factor<i64>, alt!( - map_res!( - block_ws!(digit), - to_i64 - ) - | parens - ) -); - -block_named!(term <i64>, do_parse!( - init: factor >> - res: fold_many0!( - pair!(alt!(tag!("*") | tag!("/")), factor), - init, - |acc, (op, val): (BlockSlice, i64)| { - if (op.cursor().next().unwrap() as char) == '*' { acc * val } else { acc / val } - } - ) >> - (res) - ) -); - -block_named!(expr <i64>, do_parse!( - init: term >> - res: fold_many0!( - pair!(alt!(tag!("+") | tag!("-")), term), - init, - |acc, (op, val): (BlockSlice, i64)| { - if (op.cursor().next().unwrap() as char) == '+' { acc + val } else { acc - val } - } - ) >> - (res) - ) -); - - -fn blockbuf_from(input: &[u8]) -> BlockBuf { - let mut b = BlockBuf::new(2, 100); - b.copy_from(input); - b -} - - -fn sl<'a>(input: &'a BlockBuf) -> BlockSlice<'a> { - BlockSlice { - buf: input, - start: 0, - end: input.len(), - } -} - -fn to_i64<'a>(input: BlockSlice<'a>) -> Result<i64, ()> { - let v: Vec<u8> = input.cursor().collect(); - - match str::from_utf8(&v) { - Err(_) => Err(()), - Ok(s) => match FromStr::from_str(s) { - Err(_) => Err(()), - Ok(i) => Ok(i) - } - } -} - -#[test] -fn factor_test() { - let a = blockbuf_from(&b"3"[..]); - println!("calculated: {:?}", factor(sl(&a))); -} - -#[test] -fn parens_test() { - let input1 = blockbuf_from(&b" 2* ( 3 + 4 ) "[..]); - println!("calculated 1: {:?}", expr(sl(&input1))); - let input2 = blockbuf_from(&b" 2*2 / ( 5 - 1) + 3"[..]); - println!("calculated 2: {:?}", expr(sl(&input2))); -} -*/ diff --git a/tests/issues.rs b/tests/issues.rs index 79c3493..6df183b 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -172,7 +172,7 @@ fn issue_many_m_n_with_zeros() { use nom::character::complete::char; use nom::multi::many_m_n; let mut parser = many_m_n::<_, _, (), _>(0, 0, char('a')); - assert_eq!(parser("aaa"), Ok(("aaa", vec!()))); + assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); } #[test] |