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
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)
}