More combinators, s expression test

This commit is contained in:
Greg Shuflin 2024-01-28 11:54:58 -08:00
parent 56042dbbe2
commit bb06350404
3 changed files with 70 additions and 0 deletions

View File

@ -14,6 +14,40 @@ pub fn literal_char<'a>(expected: char) -> impl Parser<&'a str, char, ()> {
} }
} }
pub fn one_of<'a>(items: &'static str) -> impl Parser<&'a str, char, ()> {
move |input: &'a str| {
if let Some(ch) = input.chars().next() {
if items.contains(ch) {
let (_first, rest) = input.split_at(1);
return Ok((ch, rest));
}
}
Err(((), input))
}
}
/// Parses a standard identifier in a programming language
pub fn identifier(input: &str) -> ParseResult<&str, String, &str> {
let mut chars = input.chars();
let mut buf = String::new();
match chars.next() {
Some(ch) if ch.is_alphabetic() => buf.push(ch),
_ => return Err((input, input)),
}
for next in chars {
if next.is_alphanumeric() {
buf.push(next);
} else {
break;
}
}
let next_index = buf.len();
Ok((buf, &input[next_index..]))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1,3 +1,5 @@
mod sexp;
use super::*; use super::*;
#[test] #[test]

34
src/test/sexp.rs Normal file
View File

@ -0,0 +1,34 @@
use crate::*;
#[derive(Debug, PartialEq)]
enum Expr {
Atom(Atom),
List(Vec<Expr>),
Quote(Vec<Expr>),
}
#[derive(Clone, Debug, PartialEq)]
enum Atom {
Num(i64),
Str(String),
Bool(bool),
Symbol(String),
}
#[test]
fn parse_sexp() {
let parse_bool = choice((
literal("#t").to(Atom::Bool(true)),
literal("#f").to(Atom::Bool(false)),
));
let parse_symbol = identifier;
let parse_number = repeated(one_of("1234567890"))
.at_least(1)
.map(|n| Atom::Num(n.iter().collect::<String>().parse::<i64>().unwrap()));
let parser = choice((parse_bool, parse_number));
let output = parser.parse("#t").unwrap();
assert_eq!(output.0, Atom::Bool(true));
}