1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
use std::error::Error; use std::fmt; use std::str::FromStr; use symbolic_expressions::{parser::parse_str, Sexp, SexpError}; use crate::{ expr::{ENode, Language, QuestionMarkName, RecExpr}, pattern::{Pattern, WildcardKind}, }; #[derive(Debug, Clone)] pub struct ParseError(String); pub type Result<T> = std::result::Result<T, ParseError>; impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ParseError: {}", self.0) } } impl Error for ParseError {} impl From<SexpError> for ParseError { fn from(e: SexpError) -> ParseError { ParseError(e.to_string()) } } impl<L: Language + FromStr> FromStr for Pattern<L> { type Err = ParseError; fn from_str(s: &str) -> Result<Self> { let sexp = parse_str(s.trim())?; parse_term(&sexp) } } impl<L: Language + FromStr> FromStr for RecExpr<L> { type Err = ParseError; fn from_str(s: &str) -> Result<Self> { let pat: Pattern<L> = s.parse()?; pat.to_expr().map_err(ParseError) } } fn parse_term<L: Language + FromStr>(sexp: &Sexp) -> Result<Pattern<L>> { match sexp { Sexp::String(s) => { if s.trim() != s || s.is_empty() { panic!("There's whitespace!") } s.parse::<QuestionMarkName>() .map(|q| { let kind = if q.as_ref().ends_with("...") { WildcardKind::ZeroOrMore } else { WildcardKind::Single }; Pattern::Wildcard(q, kind) }) .or_else(|_| s.parse().map(|t| Pattern::ENode(ENode::leaf(t).into()))) .map_err(|_| ParseError(format!("Couldn't parse '{}'", s))) } Sexp::List(vec) => { assert!(!vec.is_empty()); let mut sexps = vec.iter(); let op = match sexps.next().unwrap() { Sexp::String(s) => s .parse::<L>() .map_err(|_| ParseError(format!("bad op: {}", s)))?, op_sexp => return Err(ParseError(format!("expected op, got {}", op_sexp))), }; let children: Result<Vec<Pattern<L>>> = sexps.map(|s| parse_term(s)).collect(); Ok(Pattern::ENode(ENode::new(op, children?).into())) } Sexp::Empty => Err(ParseError("empty!".into())), } } #[cfg(test)] mod tests { use crate::{recexpr as r, *}; #[test] fn simple_parse() { let expr: RecExpr<String> = r!("+", r!("x"), r!("x")); let expr2 = "(+ x x)".parse().unwrap(); assert_eq!(expr, expr2); } }