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
97
98
99
100
101
use std::convert::TryInto;
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.try_into().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);
}
}