#parser #combinator #nom #parsing #parse

combinedfun

A little nom-like parser combinator library which stays away from macros, while trying to achieve at least part of the expressiveness of nom

4 releases

✓ Uses Rust 2018 edition

new 0.1.3 Aug 17, 2019
0.1.2 Aug 13, 2019
0.1.1 May 13, 2019
0.1.0 May 13, 2019

#6 in #combinator

30 downloads per month

MIT license

61KB
1K SLoC

combinedfun

A little nom-like parser combinator library which stays away from macros, while trying to achieve at least part of the expressiveness of nom

Welcome to this little library, the only limit is the sky. And deep recursion. And compile times. And type inference that fucks up. And sometimes, if you're "lucky": Major fuckups when it comes to lifetime inference, leaving you having to use the methods instead of operators, since, while the methods actually use the operators, actually work there. Don't ask me why. It's a mystery.


lib.rs:

This is a parser combinator library that aims to provide short and consise, but easily readable parser combinators.

If you don't know how parser combinators work, I suggest looking at nom first.

This library doesn't use macros, so it is a bit limited for some applications (specifically places where you can use map_parser are rather limited).

It also uses operator overloading for writing parsers that are easy to read and write.

Here is one example (I have no clue why almost every closure needs its arguments specified):

use std::iter;
use combinedfun as cf;

enum End {
    Repeat(String),
    Add(usize),
}

let parser = (
    cf::record_while(|c: &char| c.is_digit(10), 1..)
    >> (|s: &str| s.parse::<usize>().unwrap())
    >> (
        -cf::tag(" ")
        >> cf::take(..)
        >> (|s: &str| End::Repeat(s.to_owned()))
        |
        -cf::tag("+")
        >> cf::record_while(|c: &char| c.is_digit(10), 1..)
        >> (|s: &str| End::Add(s.parse::<usize>().unwrap()))
    )
    >> (|(i, end)| match end {
        End::Repeat(s) => (0..i).fold("".to_owned(), |acc, _| acc + &s),
        End::Add(j) => (i + j).to_string()
    })
);

assert_eq!(parser.parse("3 abc"), Ok("abcabcabc".to_owned()));
assert_eq!(parser.parse("10 x"), Ok("xxxxxxxxxx".to_owned()));
assert_eq!(parser.parse("42+123"), Ok("165".to_owned()));
assert_eq!(parser.parse("42+abc"), Err(()));
assert_eq!(parser.parse("+123"), Err(()));

No runtime deps