chomp
chomp copied to clipboard
`impl Trait` for Version 2.0.0 of Chomp
This is the impl Trait based monad implementation of Chomp for Rust Nightly. It is not intended to become the 1.0.0 of Chomp, current master is using the monad-like syntax where an input is manually threaded. Instead version 2.0.0 will be the full-monad. See #50 for the reasoning why.
Still heavily work in progress. An alpha is intended for release once the documentation-issue is solved.
-
[ ] Tests for
MonadPluslaws.Also write the laws in the documentation for the
Parsertrait. -
[x] Fix tests for
Parser::inspectandparsers::* -
[ ] Tests for
Parser::then,Paser::map,Parser::map_err,Parser::skipandParser::boxed -
[ ]
From::fromsupport in fundamental combinatorsThis needs to be investigated, it is definitely a good thing in general, but being able to not have to use type-inference on some chains would be awesome (investigate default types).
-
[ ] Formalize changes to grammar of the
parse!macro. -
[ ] Documentation updates
-
[ ] Describe how the monad executes
-
[ ] Add documentation regarding the two different versions in README.md,
1.0.0and this2.0.0, with links between the two so it is easy to look at both of them (and make sure that users understand which works on stable and which one on nightly, and their benefits and drawbacks). -
[x] Implement support for hosting documentation of both the
1.0.0and2.0.0branch at the same time. -
[x] Investigate feasibility of using a
ParserFactorytrait as a parameter to repeating combinators likemanyinstead of using aFnMut() -> impl Parser<I>generic. This would get rid of the requirements onfn_traitsandunboxed_closuresfeatures. -
[ ] How to solve the issue with
peek_next+switchhaving differently typed parsers for each branch in theswitch?
I should probably rename this branch, it is no longer an experiment :)
How to properly handle the case of peek_next + switch? All the branches of the switch return parsers of different types (and many times different sizes too). Forcing the use of boxed() on each of the returned parsers would be far from ideal.
Example:
macro_rules! ret { ( $e:expr ) => { any().then(ret($e)) } }
peek_next().bind(|c| match c {
b'{' => ret!(Token::StartObject),
b'}' => ret!(Token::EndObject),
b'(' => ret!(Token::StartArray),
b')' => // ...
b'"' => quoted_string(),
_ => tagged!(b"true", Token::True).or(
tagged!(b"false", Token::False).or(
tagged!(b"null", Token::Null).or(
number.or(whitespace))))
})
Seems like https://docs.rs solves the documentation issue, except for providing documentation for master of each of the two versions.
Great stuff! It looks though as this implementation would currently suffer from the lack the "anonymized enums" capability of impl Trait for merging results of potentially different anynomized types (for object-safe traits), this is something that's been discussed in the tracking issue recently. Otherwise you're basically back to boxing once you have several anonymised results to deal with, as shown in your example above :)
I hope I can find the time soon to continue working on Chomp.
@aldanor I have encountered that issue, or something close to it, with the sep_by parser where the separating parser is not present for the first time it iterates. The solution was to create a small enum-wrapper which matches on a contained Option<P: Parser> and calls the nested parser if present. This did not seem to cause any performance-degradation.
But the more general case will require boxing, if no object-safe enum can be used. Maybe a macro can be used to build an enum for the static case to avoid boxing.
combinators::bounded::ParserConstructor<I> is now implemented by FnMut and the special parser for sep_by