#lexer #parser #s-expr #lexing #error #list #input

lexington

A very simple library for lexing / parsing

3 releases (breaking)

0.3.0 May 12, 2024
0.2.0 May 1, 2024
0.1.0 Apr 16, 2024

#1607 in Rust patterns

MIT/Apache

37KB
655 lines

Lexington

A library for building parsers and lexers.

Example

A simple parser for S-Expressions is as follows:

/// A simple definition of the components of an S-expression.
#[derive(Copy,Clone,Debug,PartialEq)]    
enum Kind {
    WhiteSpace,
    LeftBrace,
    RightBrace,
    Symbol
}

/// A simple definition of an S-expression.
#[derive(Clone,Debug,PartialEq)]    
enum SExp<'a> {
    Symbol(&'a str),
    List(Vec<SExp<'a>>)
}

/// Parse an input string into an S-expression, or produce an error.
fn parse<'a>(input: &'a str) -> Result<SExp,()> {    
    // [ \n\t]+
    let whitespace = Any([' ','\n','\t']).one_or_more();
    // [0..9a..zA..Z_]+
    let symbol = Within('0'..='9').or(Within('a'..='z'))
        .or(Within('A'..='Z')).or('_').one_or_more();
    // Construct scanner
    let scanner = Match(whitespace,Kind::WhiteSpace)
        .and_match(symbol,Kind::Symbol)
        .and_match('(',Kind::LeftBrace)
        .and_match(')',Kind::RightBrace);
    // Construct lexer.
    let lexer = Lexer::new(input,scanner);
    // Rule for combining s-expressions
    let reduction_rule = |mut l:SExp<'a>,r:SExp<'a>| {
        match &mut l {
            SExp::List(vs) => { vs.push(r); Ok(l) }
            _ => Err(())
        }
    };
    // Rule for parsing strings into numbers
    ShiftReduceParser::new()
        .apply(reduction_rule)
        .terminate(Kind::Symbol,|tok| SExp::Symbol(&input[tok.range()]))
        .skip(Kind::WhiteSpace)
        .open(Kind::LeftBrace, SExp::List(Vec::new()))
        .close(Kind::RightBrace)
        .parse(lexer)    
}

No runtime deps