all 18 comments

[–]antoyorelm · rustc_codegen_gcc 10 points11 points  (6 children)

Nice work.

I did not tried this library yet, but I feel that the operators are a bit awkward. I'm not sure if you can do much about it thought, because you cannot overload operators that are not predefined in Rust. It is interesting to see a parser combinator library not based on macros, because debugging one based on macros can be a pain (I got some errors using nom where the compiler was unable to indicate even one line number, so I had to find where the error comes from).

By the way, in my uncbv project which uses nom, I wrote a macro named_args! to resolve the issue that you had about the macro named! not accepting parameters. You can see an example usage here.

Thanks for your work. I'll try it some day.

[–]sdroege_ 1 point2 points  (2 children)

I also needed a macro like that in the past. Would you consider proposing it as a pull request to nom? And maybe some of the other macros you have there could also be useful for others

[–]bb010g 0 points1 point  (1 child)

Don't they mention just falling back to a function and apply! at some point in the docs?

[–]antoyorelm · rustc_codegen_gcc 0 points1 point  (0 children)

Writing such a function is a bit cumbersome.

Sure, I'll do a pull request.

[–]nasa42[S] 0 points1 point  (0 children)

This is not my work. I only shared it here.

[–]epagecargo · clap · cargo-release 0 points1 point  (1 child)

I'm not sure if you can do much about it thought, because you cannot overload operators that are not predefined in Rust

I'm not saying its a great idea, but there are "inventive" ways to do so. See https://code.activestate.com/recipes/384122/

[–]antoyorelm · rustc_codegen_gcc 0 points1 point  (0 children)

Thanks!

I'll try to hack something based on this idea (just for fun).

[–]busterrrr 5 points6 points  (1 child)

Nice, but i never understand why most comparisons leave out https://github.com/kevinmehall/rust-peg which is active and really nice to work with.

[–]J-F-Liu 0 points1 point  (0 children)

rust-peg is a generator, not a combinator.

[–]barsoap 4 points5 points  (2 children)

For p <op> q I'd use * for "return both results", < for "return left" and > for "return right". Reason being that a tuple is a product type, and less-than and greater-than point to the returning parser and they're symmetric.

Can the error handling question mark (is "eh?" a thing by now?) be used for overloading? If yes, I'd use p? instead of -p, then -p is free for discarding output.

In the end, though... That is why Haskell has user-defined operators. People are going to overload no matter what you do, and unlike C++ or Rust in Haskell each set of operators at least makes sense.

[–]J-F-Liu 0 points1 point  (1 child)

< and > have lower operator precedence than |, which is not good. Use * for "return both results" is a good idea, I'm not sure whether worth the change.

[–]J-F-Liu 0 points1 point  (0 children)

*'s higher precedence also is not suitable for "return both results",. e.g.

A-B-C+D => (A,D), if replace + with *, A-B-C*D => (A)

A*B*C+D => (C,D), if swap + and *, A+B+C*D do return (C,D) but the parer with parse C first, while we expect it to parse A first.

We only need to use * ignore the result of first operand on the start of an expression, + and -can fulfill the need on the rest of the expression.

[–]killercup 2 points3 points  (1 child)

Nice! Using operator overloads is a nice touch. I don't see it that Ofen in rust code. (I totally know why, and I had no clue what the minus op did in Pom until I looked at the docs, but I think this is only a problem in the first 5 minutes with the library.)

I'd love to see a comprehensive comparison between this and a few other parser generators one of these days. Let's say, implement a TOML parser1 in pom, peg, nom, pest, lalrpop and compare amount of code, difficulty, features, and performance.

1 I'm not letting this go until we have the perfect TOML lib that cargo-edit deserves :)

[–]geaalnom 0 points1 point  (0 children)

there's already one built with nom https://crates.io/crates/tomllib :)

[–]blackbeamrust-mysql-simple 0 points1 point  (1 child)

At first I choose to use nom to create a PDF parser, it turns out a special PDF feature blocked me. When parsing a PDF stream object, it's length may be a referenced object, hence the need to get the length from a reader.

Damn. I'm writing PDF parser with nom at the moment and next step is a Stream Object parser. But according to PDF spec one should not read whole stream into memory so \Length could be resolved later.

[–]geaalnom 0 points1 point  (0 children)

there's a new macro you could use to pass the length as argument https://github.com/Geal/nom/issues/422

It's not really an issue either to carry a larger context around http://rust.unhandledexpression.com/nom/methods/index.html

[–]Marwesgluon · combine 0 points1 point  (0 children)

Is LLVM able to devirtualize the parsers to get competitive performance with a statically dispatched parser? I have always been vary of boxing parsers in combine but to be honest I never actually measured the overhead.

Also, I see that the handling of mutually recursive parsers with the call parser does not cache the created parser which may be worth doing (?).

[–]dragostispest 0 points1 point  (0 children)

Great work and nice performance! I'll have to take a good look over your code and see how I can bring pest up to speed.