Skip to content

Latest commit

 

History

History
61 lines (47 loc) · 2.11 KB

README.md

File metadata and controls

61 lines (47 loc) · 2.11 KB

Parcom   License Badge Rust

Parcom is a trait + closure based parser combinator library loosely following the Parsec Paper

This project is experimental and is missing some features that make it generally useful:

  • Distinguishing between fatal and non-fatal errors
  • A generic way of combining characters, string slices and strings efficiently

Example

Here's an example of a parser for a lisp like language (e.g. (+ 1 2 (* 10 10))):

pub fn identifier<'a>() -> impl Parser<&'a str, String> {
    let initial_identifier = || one_of!(alphabetic_char(), one_of_char("!$%&*/:<=>?^_~"));
    let peculiar_identifier = one_of_char("+-");
    let subsequent_identifier = one_of!(initial_identifier(), alphabetic_char(), digit_char());

    one_of!(
        seqc!(initial_identifier(), repeatc(subsequent_identifier)),
        peculiar_identifier
    )
}

pub fn variable<'a>() -> impl Parser<&'a str, Cell> {
    mapv(identifier(), Cell::Symbol)
}

pub fn number<'a>() -> impl Parser<&'a str, Cell> {
    let digit = one_of_char("0123456789");
    let sign = one_of_char("+-");
    let num10 = mapv(
        seqc!(optional(sign), collect(repeat1(digit))),
        |s: String| match s.parse::<i64>() {
            Ok(n) => Cell::Number(n),
            Err(_) => Cell::Number(0),
        },
    );

    mapv(one_of!(num10), Cell::from)
}

pub fn ows<'a>() -> impl Parser<&'a str, String> {
    discard(optional(whitespace_char()))
}

pub fn procedure_call<'a>() -> impl Parser<&'a str, Cell> {
    mapv(
        between(ch('('), repeat1(between(ows(), expression, ows())), ch(')')),
        Cell::new_list,
    )
}

pub fn expression(input: &str) -> ParseResult<&str, Cell> {
    one_of!(procedure_call(), number(), variable()).apply(input)
}