chomp

A fast monadic-style parser combinator designed to work on stable Rust.

Subscribe to updates I use chomp


Statistics on chomp

Number of watchers on Github 165
Number of open issues 19
Average time to close an issue about 1 month
Main language Rust
Average time to merge a PR 4 days
Open pull requests 7+
Closed pull requests 0+
Last commit over 1 year ago
Repo Created about 3 years ago
Repo Last Updated 9 months ago
Size 7.29 MB
Organization / Authorm4rw3r
Contributors2
Page Updated
Do you use chomp? Leave a review!
View open issues (19)
View chomp activity
View on github
Latest Open Source Launches
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating chomp for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Chomp

Gitter Build Status Coverage Status Crates.io Documentation

Chomp is a fast monadic-style parser combinator library designed to work on stable Rust. It was written as the culmination of the experiments detailed in these blog posts:

For its current capabilities, you will find that Chomp performs consistently as well, if not better, than optimized C parsers, while being vastly more expressive. For an example that builds a performant HTTP parser out of smaller parsers, see http_parser.rs.

Installation

Add the following line to the dependencies section of your Cargo.toml:

[dependencies]
chomp = "0.3.1"

Usage

Parsers are functions from a slice over an input type Input<I> to a ParseResult<I, T, E>, which may be thought of as either a success resulting in type T, an error of type E, or a partially completed result which may still consume more input of type I.

The input type is almost never manually manipulated. Rather, one uses parsers from Chomp by invoking the parse! macro. This macro was designed intentionally to be as close as possible to Haskell's do-syntax or F#'s computation expressions, which are used to sequence monadic computations. At a very high level, usage of this macro allows one to declaratively:

  • Sequence parsers, while short circuiting the rest of the parser if any step fails.
  • Bind previous successful results to be used later in the computation.
  • Return a composite datastructure using the previous results at the end of the computation.

In other words, just as a normal Rust function usually looks something like this:

fn f() -> (u8, u8, u8) {
    let a = read_digit();
    let b = read_digit();
    launch_missiles();
    return (a, b, a + b);
}

A Chomp parser with a similar structure looks like this:

fn f<I: U8Input>(i: I) -> SimpleResult<I, (u8, u8, u8)> {
    parse!{i;
        let a = digit();
        let b = digit();
                string(b"missiles");
        ret (a, b, a + b)
    }
}

And to implement read_digit we can utilize the map function to manipulate any success value while preserving any error or incomplete state:

// Standard rust, no error handling:
fn read_digit() -> u8 {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().parse().unwrap()
}

// Chomp, error handling built in, and we make sure we only get a number:
fn read_digit<I: U8Input>(i: I) -> SimpleResult<I, u8> {
    satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0')
}

For more documentation, see the rust-doc output.

Example

#[macro_use]
extern crate chomp;

use chomp::prelude::*;

#[derive(Debug, Eq, PartialEq)]
struct Name<B: Buffer> {
    first: B,
    last:  B,
}

fn name<I: U8Input>(i: I) -> SimpleResult<I, Name<I::Buffer>> {
    parse!{i;
        let first = take_while1(|c| c != b' ');
                    token(b' ');  // skipping this char
        let last  = take_while1(|c| c != b'\n');

        ret Name{
            first: first,
            last:  last,
        }
    }
}

assert_eq!(parse_only(name, "Martin Wernstl\n".as_bytes()), Ok(Name{
    first: &b"Martin"[..],
    last: "Wernstl".as_bytes()
}));

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Contact

File an issue here on Github or visit gitter.im/m4rw3r/chomp.

chomp open issues Ask a question     (View All Issues)
  • about 2 years Be able to unwrap Input from InputPosition.
  • about 2 years Accessing numbering::InputPosition::position via map_err
  • about 2 years Reorganize types
  • about 2 years Improving the `buffer` module
  • about 2 years Non `Copy` `Token`s?
  • almost 3 years Implement alternative `parse!` macro using compiler plugin
  • almost 3 years Provide alternatives preventing overflow and unbounded parsing
  • almost 3 years Applicative parsing
  • almost 3 years Proper parsers tests and examples for using `&str` as a parse source
  • almost 3 years Attoparsec parsers
  • almost 3 years Adapter for Nom
  • almost 3 years TOML example parser
  • almost 3 years ForEach macro/method/function to make it easier to use Stream
chomp open pull requests (View All Pulls)
  • NomAdapter
  • Simplified error
  • Input trait
  • Implementation of Input wrapper for Iterator types
  • Support for `no_std`
  • `impl Trait` for Version 2.0.0 of Chomp
  • Fix string parser
chomp questions on Stackoverflow (View All Questions)
  • How can I remove (chomp) a newline in Python?
  • Chomp all keys of a map (using less code)
  • chomp() usage in Perl
  • What is the sequence combinator in Chomp?
  • How to use chomp
  • vagrant fails to get machine up. throwing: keep getting an error `prompt': undefined method `chomp' for nil:NilClass (NoMethodError)
  • Is there a time when 'gets' would be used without 'chomp'?
  • Use Chop() or Chomp() instead of regex to read csv/Tab delimited file?
  • How is it that chomp is able to change the value of a variable not passed by reference?
  • Difference between chomp and trim in Perl?
  • Why doesn't `"hello\r".chomp('')` remove `"\r"`?
  • Can I use strip! and chomp! in one line in Ruby
  • Perl chomp convert string into numerical values
  • How can I get Ant to "chomp" newlines at the end of files?
  • Matching the end of line $ in perl; print showing different behavior with chomp
  • Is it ever necessary to use 'chomp' before using `to_i` or `to_f`?
  • Dlang chomp() not working on certain delimiters
  • Strip left/right a string (and chomp)
  • What is the use of chomp?
  • NoMethodError: undefined method `chomp' for nil:NilClass
  • Why does my file content/user input not match? (missing chomp canonical)
  • How can I chomp every line in an array at once?
  • Strange behavior of 'chomp' for processing a file line-by-line in Perl
  • Why does 'chomp' fail to remove newlines on Windows XP with Eclipse and Cygwin Perl?
  • Perl chomp turn multiple digit number into 1 or 0
  • How to do chomp a Perl array without using foreach?
  • Perl weird chomp and newline
  • NoMethodError (undefined method `chomp!' for nil:NilClass) when using authenticate_or_request_with_http_token
  • Lines are not getting printed after application of chomp in perl
  • Stop getting input with gets when specific character, similar chomp
chomp list of languages used
More projects by m4rw3r View all
Other projects in Rust