Skip to main content

eta_core/
human.rs

1
2
3use alloc::{format, rc::Rc, string::String};
4use core::{fmt::Display, iter::Peekable, str};
5use hashbrown::HashMap;
6use thiserror::Error;
7
8use crate::theory::{ID, Kind};
9
10pub struct Dict {
11    map: HashMap< Rc<String>, ID>,
12    rev: HashMap<ID, Rc<String>>,
13    i: ID
14}
15impl Dict {
16    pub fn new() -> Self { Self {map: HashMap::new(), rev: HashMap::new(), i: 0} }
17    pub fn get(&mut self, name: String) -> Option<ID> {
18        match self.map.get(&name) {
19            Some(id) => Some(*id),
20            None => {
21                let owd: Rc<String> = Rc::from(name);
22                self.map.insert(owd.clone(), self.i);
23                self.rev.insert(self.i, owd);
24
25                let ret = self.i;
26                match self.i.checked_add(1) {
27                    Some(ni) => {
28                        self.i = ni;
29                        Some(ret)
30                    },
31                    None => None,
32                }
33            },
34        }
35    }
36    /* expensive (kinda) */
37    pub fn get_name(&self, id: ID) -> Option<&str> {
38        self.rev.get(&id).map(Rc::as_ref).map(|x| x.as_str())
39    }
40}
41
42/* parse errors */
43#[derive(Debug, Error)]
44pub enum ParserErr {
45    #[error("expected '{what}' at {pos}")]
46    Expected { what: char, pos: usize },
47
48    #[error("expected an atom at {pos}")]
49    NeedAtom { pos: usize },
50
51    #[error("namespace full while at {pos}")]
52    NamespaceFull { pos: usize },
53
54    #[error("end of input at {pos}")]
55    EndOfInput { pos: usize },
56
57    #[error("pair has more than 2 members at {pos}")]
58    PairHasMore { pos: usize },
59}
60type PrsErr = ParserErr;
61
62struct Prsable<It: Iterator<Item = char>> {
63    inner: Peekable<It>,
64    pos: usize
65}
66impl<It: Iterator<Item = char>> Prsable<It> {
67    fn new(it: It) -> Self { Self { inner: it.peekable(), pos: 0 }}
68    fn next(&mut self) -> Option<char> {
69        let n = self.inner.next()?;
70        self.pos += 1;
71        Some(n)
72    }
73    fn peek(&mut self) -> Option<char> { self.inner.peek().copied() }
74}
75
76/* parser: binary s-expressions (s-pairs) */
77pub struct Parser<It: Iterator<Item = char>> {
78    it: Prsable<It>
79}
80
81type Prsr<It> = Parser<It>;
82impl<It: Iterator<Item = char>> Prsr<It> {
83    pub fn new(it: It) -> Self { Self { it: Prsable::new(it) }}
84
85    fn skip_ws(&mut self) {
86        while let Some(b) = self.it.peek() {
87            match b {
88                ' ' | '\t' | '\r' | '\n' => { self.it.next(); },
89                ';' => { /* comment to end-of-line */
90                    while let Some(c) = self.it.next() {
91                        if c == '\n' { break }
92                    }
93                }
94                _ => break,
95            }
96        }
97    }
98
99    fn expect(&mut self, want: char) -> Result<(), PrsErr> {
100        self.skip_ws();
101        match self.it.next() {
102            Some(got) if got == want => Ok(()),
103            _ => Err(PrsErr::Expected { what: want, pos: self.it.pos }),
104        }
105    }
106
107    fn is_sym_char(b: char) -> bool {
108        !matches!(b, ' ' | '\t' | '\r' | '\n' | '(' | ')' | ';')
109    }
110
111    pub fn parse_atom(&mut self, dict: &mut Dict) -> Result<Kind, PrsErr> {
112        self.skip_ws();
113        let mut st = String::new();
114        let start = self.it.pos;
115
116        while let Some(b) = self.it.peek() {
117            if Self::is_sym_char(b) {
118                self.it.next(); /* consume */
119                st.push(b);
120            } else { break; }
121        }
122
123        if self.it.pos == start {
124            return Err(PrsErr::NeedAtom { pos: self.it.pos });
125        }
126
127        match dict.get(st) {
128            Some(sy) => Ok(Kind::from(sy)),
129            None => Err(PrsErr::NamespaceFull { pos: self.it.pos }),
130        }
131    }
132
133    pub fn parse_expr(&mut self, dict: &mut Dict) -> Result<Kind, PrsErr> {
134        self.skip_ws();
135        match self.it.peek() {
136            Some('(') => self.parse_spair(dict),
137            Some(_) => self.parse_atom(dict),
138            None => Err(PrsErr::EndOfInput { pos: self.it.pos }),
139        }
140    }
141
142    // '(' expr expr ')', exactly two.
143    pub fn parse_spair(&mut self, dict: &mut Dict) -> Result<Kind, PrsErr> {
144        self.expect('(')?;
145        let l = self.parse_expr(dict)?;
146        let r = self.parse_expr(dict)?;
147        self.skip_ws();
148
149        match self.it.peek() {
150            Some(')') => {
151                self.it.next(); /* consume */
152                Ok(Kind::from((l, r)))
153            }
154            Some(_) => Err(PrsErr::PairHasMore { pos: self.it.pos }),
155            None => Err(PrsErr::Expected { what: ')', pos: self.it.pos }),
156        }
157    }
158    pub fn has_ended(&mut self) -> Result<usize, ()> {
159        self.skip_ws();
160        match self.it.peek() {
161            Some(_) => Ok(self.it.pos),
162            None => Err(())
163        }
164    }
165}
166
167pub fn unparse(root: &Kind, dict: &Dict) -> String {
168    match root {
169        Kind::Alp { id } => match dict.get_name(*id) {
170            Some(name) => name.into(),
171            None => format!("#{root:?}"),
172        },
173        Kind::Zta { sid, .. } => match *sid {
174            None => format!("#{root:?}"),
175            Some(id) => match dict.get_name(id) {
176                Some(name) => name.into(),
177                None => format!("#{root:?}"),
178            },
179        }
180        Kind::Pir { l, r } => format!(
181            "({} {})",
182            unparse(l, dict), unparse(r, dict)
183        )
184    }
185}
186
187pub struct View<'a> {
188    root: &'a Kind,
189    dict: &'a Dict
190}
191impl<'a> View<'a> {
192    pub fn new(root: &'a Kind, dict: &'a Dict) -> Self { Self { root, dict } }
193}
194
195impl<'a> Display for View<'a> {
196    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
197        match self.root {
198            Kind::Alp { id } => match self.dict.get_name(*id) {
199                Some(name) => write!(f, "{name}"),
200                None => write!(f, "#{:?}", self.root),
201            },
202            Kind::Zta { sid, .. } => match *sid {
203                None => write!(f, "#{:?}", self.root),
204                Some(id) => match self.dict.get_name(id) {
205                    Some(name) => write!(f, "{name}"),
206                    None => write!(f, "#{:?}", self.root),
207                },
208            }
209            Kind::Pir { l, r } => write!(
210                f, "({} {})",
211                View::new(l, self.dict),
212                View::new(r, self.dict)
213            )
214        }
215    }
216}