Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
3c4dbbf
Tests compiling
m4rw3r Aug 19, 2016
0f6fb4a
Implemented Monad, Functor and some MonadPlus methods on Parser type
m4rw3r Aug 22, 2016
f5dab8c
Fixes to warnings, removed or from combinators
m4rw3r Aug 22, 2016
16f1009
Updated example and benches
m4rw3r Aug 22, 2016
7fac29b
Buffer: fixed tests
m4rw3r Aug 22, 2016
31ab360
Fixed bounded combinators
m4rw3r Aug 22, 2016
449a4fe
Unified all many* combinators under one trait
m4rw3r Aug 22, 2016
692b506
skip_many and tests for many and skip_many
m4rw3r Aug 22, 2016
e13e2c8
Travis: only test impl Trait on nightly
m4rw3r Aug 22, 2016
86be71a
Clippy
m4rw3r Aug 22, 2016
2c618dd
Macros: use moving closures since they are all FnOnce
m4rw3r Aug 27, 2016
180b67e
Removed unused module
m4rw3r Aug 27, 2016
581e630
Ascii: Updated ascii module
m4rw3r Aug 27, 2016
5be4d8e
bounded::sep_by: Fixed missing separator
m4rw3r Aug 27, 2016
d069a6c
Test of bounded many for infinite parsers
m4rw3r Aug 27, 2016
f8673b2
Updated parse module
m4rw3r Aug 27, 2016
8510253
Uncommented finished items in prelude
m4rw3r Aug 27, 2016
e422346
Moved test for or into types module
m4rw3r Aug 27, 2016
ea93518
combinators: sep_by and sep_by1
m4rw3r Aug 27, 2016
9544443
Tests: updated combinator tests
m4rw3r Aug 27, 2016
62fd415
Parsers: skip_while
m4rw3r Aug 28, 2016
db53877
combinators: many_till for Range<usize>
m4rw3r Aug 31, 2016
acd4662
Updated ascii compile-fail to use the monad syntax
m4rw3r Aug 31, 2016
71499da
combinators::bounded: Removed unnecessary generic in macros
m4rw3r Aug 31, 2016
4f9f1cc
types: Input no longer requires the Sized bound
m4rw3r Aug 31, 2016
d5530c5
Parser: Added boxed() to turn a parser into a trait object
m4rw3r Aug 31, 2016
d58bf4c
Combinators: many_till, converted tests and added a few more
m4rw3r Aug 31, 2016
ee8122b
combinators::bounded: Fixed bugs related to Range where start == end
m4rw3r Aug 31, 2016
39f42f6
types::Parser: Fixed inference issues with basic combinators in case …
m4rw3r Sep 1, 2016
ad20f99
Fixed some doctests
m4rw3r Sep 1, 2016
5c2ef9d
types::numbering: Fixed test and added monad compatible way to obtain…
m4rw3r Sep 1, 2016
7b61e18
Updated doctests
m4rw3r Sep 1, 2016
edbb26e
macro: Updated doctests
m4rw3r Sep 1, 2016
54d8b37
combinators::bounded: Replaced panic! with unreachable!
m4rw3r Sep 1, 2016
c9949a0
Merge branch 'master' into experiment/impl_trait
m4rw3r Sep 3, 2016
e00af1b
combinators::either: Adapter to monad
m4rw3r Sep 3, 2016
666d952
combinators::bounded: Removed unused variable
m4rw3r Sep 3, 2016
ae0ca8d
Added missing Debug implementations
m4rw3r Sep 4, 2016
03ea29d
combinators::bounded: Improved macros generating parsers and added De…
m4rw3r Sep 4, 2016
f68c267
combinators::bounded: Removed Bounded-prefix from the bounded traits
m4rw3r Sep 4, 2016
08085f2
parsers: Updated tests
m4rw3r Sep 4, 2016
bb8f081
types: Fixed test for Parse::inspect
m4rw3r Sep 4, 2016
35694f4
Fixed warnings in doctests
m4rw3r Sep 6, 2016
4f468fb
Merge branch 'master' into experiment/impl_trait
m4rw3r Sep 6, 2016
5760b22
Tendril: Now compiles also for impl Trait
m4rw3r Sep 6, 2016
7b39f8a
Updated tests for tendril
m4rw3r Sep 6, 2016
0899e6e
Small initial test of Parser::boxed
m4rw3r Sep 6, 2016
15ab521
Test: Fixed type error in boxed test
m4rw3r Feb 11, 2017
a4c6de0
Bumped verisons of bitflags and either
m4rw3r May 18, 2017
aa8c591
Parser: Added tests for Monad Plus laws
m4rw3r May 27, 2017
d56b19a
Ascii: Implemented case-insensitive string-comparison
m4rw3r May 27, 2017
8057556
Updated bitflags and tendril dependencies
m4rw3r May 27, 2017
42dc4eb
Remove requirement for features and by using a ParserConstructor tr…
m4rw3r Jul 24, 2017
608d5d6
Fix markdown header syntax in README
mkantor Jul 12, 2017
14165d2
buffer/data_source: add RWDataSource struct and impls
Jul 14, 2017
3cca9ab
buffer/stateful: implement Write for Source if RWDataSource
Jul 14, 2017
e8835ea
buffer/stateful: add RW Source constructor methods
Jul 14, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ language: rust
sudo: false

rust:
- stable
- beta
# We require nightly for conservative_impl_trait, unboxed_closures and fn_traits
- nightly
# Minimum supported version (bitflags fails on 1.7 due to op_assign_traits not being stable):
- 1.8.0

# necessary for `travis-cargo coveralls --no-sudo`
addons:
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ include = [
]

[dependencies]
bitflags = "0.7.0"
bitflags = "0.9.0"
conv = { version = "0.3.3", default-features = false, features = ["std"] }
either = { version = "0.1.7" }
either = { version = "1.1.0" }
debugtrace = { version = "0.1.0" }
tendril = { version = "0.2.2", optional = true }
tendril = { version = "0.3.0", optional = true }

# Technically a dev-dependency, but dev-dependencies are not allowed to be optional,
# compiletest_rs fails to compile on stable and beta
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Chomp is a fast monadic-style parser combinator library designed to work on stab

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](examples/http_parser.rs).

##Installation
## Installation

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

Expand All @@ -24,7 +24,7 @@ Add the following line to the dependencies section of your `Cargo.toml`:
chomp = "0.3.1"
```

##Usage
## 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`.

Expand Down Expand Up @@ -125,6 +125,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
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
## Contact

File an issue [here](https://github.com/m4rw3r/chomp/issues/new) on Github or visit [gitter.im/m4rw3r/chomp](https://gitter.im/m4rw3r/chomp).
55 changes: 28 additions & 27 deletions benches/combinators.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![feature(conservative_impl_trait)]
#![feature(test)]
extern crate test;
#[macro_use]
Expand All @@ -14,115 +15,115 @@ use chomp::buffer::InputBuf;
fn count_vec_1k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
count(i, 1024, any)
fn count_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
count(1024, any)
}

b.iter(|| {
parse_only(count_vec, &data)
count_vec().parse(&data[..])
})
}

#[bench]
fn count_vec_10k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10240).collect::<Vec<u8>>();

fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
count(i, 10240, any)
fn count_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
count(10240, any)
}

b.iter(|| {
parse_only(count_vec, &data)
count_vec().parse(&data[..])
})
}

#[bench]
fn many_vec_1k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many(i, any)
fn many_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many(any)
}

b.iter(|| {
parse_only(many_vec, &data)
many_vec().parse(&data[..])
})
}

#[bench]
fn many_vec_10k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many(i, any)
fn many_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many(any)
}

b.iter(|| {
parse_only(many_vec, &data)
many_vec().parse(&data[..])
})
}

#[bench]
fn many1_vec_1k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many1(i, any)
fn many1_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many1(any)
}

b.iter(|| {
parse_only(many1_vec, &data)
many1_vec().parse(&data[..])
})
}

#[bench]
fn many1_vec_10k(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many1(i, any)
fn many1_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many1(any)
}

b.iter(|| {
parse_only(many1_vec, &data)
many1_vec().parse(&data[..])
})
}

#[bench]
fn count_vec_10k_maybe_incomplete(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
count(i, 10024, any)
fn count_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
count(10024, any)
}

b.iter(|| {
count_vec(InputBuf::new(&data))
count_vec().parse(InputBuf::new(&data))
})
}

#[bench]
fn many_vec_10k_maybe_incomplete(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many(i, any)
fn many_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many(any)
}

b.iter(|| {
many_vec(InputBuf::new(&data))
many_vec().parse(InputBuf::new(&data))
})
}

#[bench]
fn many1_vec_10k_maybe_incomplete(b: &mut Bencher) {
let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
many1(i, any)
fn many1_vec<I: Input>() -> impl Parser<I, Output=Vec<I::Token>, Error=Error<I::Token>> {
many1(any)
}

b.iter(|| {
many1_vec(InputBuf::new(&data))
many1_vec().parse(InputBuf::new(&data))
})
}
47 changes: 25 additions & 22 deletions benches/http_bench.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![feature(test)]
#![feature(trace_macros)]
#![feature(conservative_impl_trait)]
extern crate test;
#[macro_use]
extern crate chomp;
Expand Down Expand Up @@ -51,65 +53,66 @@ fn is_not_space(c: u8) -> bool { c != b' ' }
fn is_end_of_line(c: u8) -> bool { c == b'\r' || c == b'\n' }
fn is_http_version(c: u8) -> bool { c >= b'0' && c <= b'9' || c == b'.' }

fn end_of_line<I: U8Input>(i: I) -> SimpleResult<I, u8> {
parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')}
fn end_of_line<I: Input<Token=u8>>() -> impl Parser<I, Output=u8, Error=Error<u8>> {
parse!{(token(b'\r') <|> ret(b'\0')) >> token(b'\n')}
}

fn http_version<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
parse!{i;
fn http_version<I: Input<Token=u8>>() -> impl Parser<I, Output=I::Buffer, Error=Error<u8>> {
parse!{
string(b"HTTP/");
take_while1(is_http_version)
}
}

fn request_line<I: U8Input>(i: I) -> SimpleResult<I, Request<I::Buffer>> {
parse!{i;
fn request_line<I: Input<Token=u8>>() -> impl Parser<I, Output=Request<I::Buffer>, Error=Error<u8>> {
parse!{
let method = take_while1(is_token);
take_while1(is_space);
let uri = take_while1(is_not_space);
take_while1(is_space);
let version = http_version();

ret Request {
ret(Request {
method: method,
uri: uri,
version: version,
}
})
}
}

fn message_header_line<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
parse!{i;
fn message_header_line<I: Input<Token=u8>>() -> impl Parser<I, Output=I::Buffer, Error=Error<u8>> {
parse!{
take_while1(is_horizontal_space);
let line = take_till(is_end_of_line);
end_of_line();

ret line
ret(line)
}
}

fn message_header<I: U8Input>(i: I) -> SimpleResult<I, Header<I::Buffer>> {
parse!{i;
fn message_header<I: Input<Token=u8>>() -> impl Parser<I, Output=Header<I::Buffer>, Error=Error<u8>> {
parse!{
let name = take_while1(is_token);
token(b':');
let lines = many1(message_header_line);

ret Header {
ret(Header {
name: name,
value: lines,
}
})
}
}

#[inline(never)]
fn request<I: U8Input>(i: I) -> SimpleResult<I, (Request<I::Buffer>, Vec<Header<I::Buffer>>)> {
parse!{i;
fn request<I: Input<Token=u8>>() -> impl Parser<I, Output=(Request<I::Buffer>, Vec<Header<I::Buffer>>), Error=Error<u8>>
where I::Buffer: ::std::ops::Deref<Target=[u8]> {
parse!{
let r = request_line();
end_of_line();
let h = many(message_header);
end_of_line();

ret (r, h)
ret((r, h))
}
}

Expand All @@ -126,7 +129,7 @@ Connection: keep-alive\r
\r";

b.iter(|| {
parse_only(request, data)
request().parse(&data[..])
})
}

Expand All @@ -138,7 +141,7 @@ Host: localhost\r
\r";

b.iter(|| {
parse_only(request, data)
request().parse(&data[..])
})
}

Expand All @@ -157,7 +160,7 @@ Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966\r
\r";

b.iter(|| {
parse_only(request, data)
request().parse(&data[..])
})
}

Expand All @@ -166,7 +169,7 @@ fn multiple_requests(b: &mut Bencher) {
let data = include_bytes!("./data/http-requests.txt");

b.iter(|| {
let r: Result<Vec<_>, _> = parse_only(parser!{many(request)}, data);
let (_, r): (_, Result<Vec<_>, _>) = many(request).parse(&data[..]);

r
})
Expand Down
Loading