More combinators, s expression test
This commit is contained in:
parent
56042dbbe2
commit
bb06350404
@ -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::*;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
mod sexp;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
34
src/test/sexp.rs
Normal file
34
src/test/sexp.rs
Normal 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));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user