use crate::parser::{ParseResult, Parser, ParserInput, Representation}; pub fn literal_char(expected: char) -> impl Fn(&str) -> ParseResult<&str, char, &str> { move |input| match input.chars().next() { Some(ch) if ch == expected => Ok((expected, &input[ch.len_utf8()..])), _ => Err(input), } } pub fn literal<'a>(expected: &'static str) -> impl Parser<&'a str, &'a str, &'a str> { println!("literal call expected: {}", expected); let rep = Representation::new(expected); let p = move |input: &'a str| match input.get(0..expected.len()) { Some(next) if next == expected => Ok((expected, &input[expected.len()..])), _ => Err(input), }; (p, rep) } pub fn any_char(input: &str) -> ParseResult<&str, char, &str> { match input.chars().next() { Some(ch) => Ok((ch, &input[ch.len_utf8()..])), None => Err(input), } } pub fn one_of<'a>(items: &'static str) -> impl Parser<&'a str, &'a str, &'a str> { let p = move |input: &'a str| { if let Some(ch) = input.chars().next() { if items.contains(ch) { let (first, rest) = input.split_at(1); return Ok((first, rest)); } } Err(input) }; let mut s = String::new(); for ch in items.chars() { s.push(ch); s.push_str(" | "); } let rep = Representation::new(&s); (p, rep) } pub fn pred(parser: P, pred_fn: F) -> impl Parser where I: ParserInput, P: Parser, F: Fn(&O) -> bool, { let orig_rep = parser.representation(); ( move |input| { parser.parse(input).and_then(|(result, rest)| { if pred_fn(&result) { Ok((result, rest)) } else { Err(rest) } }) }, Representation::new(&format!("{:?} if ", orig_rep)), ) } /// 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), } 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)] mod tests { use super::*; #[test] fn test_identifier() { assert_eq!( identifier("bongo1beans").unwrap(), (("bongo1beans".to_string(), "")) ); assert_eq!(identifier("2bongo1beans"), Err("2bongo1beans")); } #[test] fn test_pred() { let p = pred(any_char, |c| *c == 'f'); assert_eq!(p.parse("frog"), Ok(('f', "rog"))); } }