eta_core/
human.rs

1
2
3use alloc::{format, rc::Rc, string::String};
4use core::str;
5use hashbrown::HashMap;
6
7use crate::theory::*;
8
9pub struct Dict {
10    map: HashMap< Rc<String>, ID>,
11    rev: HashMap<ID, Rc<String>>,
12    i: ID
13}
14impl Dict {
15    pub fn new() -> Self { Self {map: HashMap::new(), rev: HashMap::new(), i: 0} }
16    pub fn get(&mut self, name: String) -> Option<ID> {
17        match self.map.get(&name) {
18            Some(id) => Some(*id),
19            None => {
20                let owd: Rc<String> = Rc::from(name);
21                self.map.insert(owd.clone(), self.i);
22                self.rev.insert(self.i, owd);
23
24                let ret = self.i;
25                match self.i.checked_add(1) {
26                    Some(ni) => {
27                        self.i = ni;
28                        Some(ret)
29                    },
30                    None => None,
31                }
32            },
33        }
34    }
35    /* expensive (kinda) */
36    pub fn get_name(&self, id: ID) -> Option<&str> {
37        self.rev.get(&id).map(Rc::as_ref).map(|x| x.as_str())
38    }
39}
40
41/* parse errors */
42#[derive(Clone, Debug)]
43pub struct PrsErr {
44    pub msg: &'static str,
45    pub pos: usize,
46}
47
48/* parser: binary s-expressions (s-pairs) */
49struct Prsr<'a> {
50    s: &'a str,
51    i: usize,
52}
53impl<'a> Prsr<'a> {
54    fn new(s: &'a str) -> Self {
55        Self { s, i: 0 }
56    }
57
58    fn eof(&self) -> bool { self.i >= self.s.chars().count() }
59    fn peek(&self) -> Option<char> { self.s.chars().nth(self.i) }
60
61    fn bump(&mut self) -> Option<char> {
62        let b = self.peek()?;
63        self.i += 1;
64        Some(b)
65    }
66
67    fn skip_ws(&mut self) {
68        while let Some(b) = self.peek() {
69            match b {
70                ' ' | '\t' | '\r' | '\n' => self.i += 1,
71                ';' => {
72                    /* comment to end-of-line */
73                    self.i += 1;
74                    while let Some(c) = self.peek() {
75                        self.i += 1;
76                        if c == '\n' { break; }
77                    }
78                }
79                _ => break,
80            }
81        }
82    }
83
84    fn expect(&mut self, want: char) -> Result<(), PrsErr> {
85        self.skip_ws();
86        match self.bump() {
87            Some(got) if got == want => Ok(()),
88            _ => Err(PrsErr {msg: "unexpected character", pos: self.i}),
89        }
90    }
91
92    fn is_sym_char(b: char) -> bool {
93        !matches!(b, ' ' | '\t' | '\r' | '\n' | '(' | ')' | ';')
94    }
95
96    fn parse_atom(&mut self) -> Result<String, PrsErr> {
97        self.skip_ws();
98        let start = self.i;
99
100        while let Some(b) = self.peek() {
101            if Self::is_sym_char(b) { self.i += 1; } else { break; }
102        }
103
104        if self.i == start {
105            return Err(PrsErr {msg: "expected atom", pos: self.i});
106        }
107
108        Ok(self.s.chars().skip(start).take(self.i - start).collect())
109    }
110
111    fn parse_expr(&mut self, dict: &mut Dict) -> Result<Kind, PrsErr> {
112        self.skip_ws();
113        match self.peek() {
114            Some('(') => self.parse_blist(dict),
115            Some(_) => {
116                let sym = self.parse_atom()?;
117                match dict.get(sym) {
118                    Some(gsy) => Ok(Kind::from(gsy)),
119                    None => Err(PrsErr {msg: "internal namespace full", pos: self.i}),
120                }
121            }
122            None => Err(PrsErr {msg: "unexpected end of input", pos: self.i}),
123        }
124    }
125
126    // '(' expr expr ')', exactly two.
127    fn parse_blist(&mut self, dict: &mut Dict) -> Result<Kind, PrsErr> {
128        self.expect('(')?;
129        let l = self.parse_expr(dict)?;
130        let r = self.parse_expr(dict)?;
131        self.skip_ws();
132
133        match self.peek() {
134            Some(')') => { self.i += 1; Ok(Kind::from((l, r))) }
135            Some(_) => Err(PrsErr {
136                msg: "s-pair must contain exactly 2 binary s-pairs",
137                pos: self.i
138            }),
139            None => Err(PrsErr {msg: "missing ')'", pos: self.i}),
140        }
141    }
142}
143
144pub fn parse(input: &str, dict: &mut Dict) -> Result<Kind, PrsErr> {
145    let mut p = Prsr::new(input);
146    let k = p.parse_blist(dict)?;
147    p.skip_ws();
148    if !p.eof() {
149        return Err(PrsErr {msg: "trailing input", pos: p.i});
150    }
151    Ok(k)
152}
153
154pub fn unparse(root: &Kind, dict: &Dict) -> String {
155    match root {
156        Kind::Alp { id } => match dict.get_name(*id) {
157            Some(name) => name.into(),
158            None => format!("#{root:?}"),
159        },
160        Kind::Zta { sid, .. } => match *sid {
161            None => format!("#{root:?}"),
162            Some(id) => match dict.get_name(id) {
163                Some(name) => name.into(),
164                None => format!("#{root:?}"),
165            },
166        }
167        Kind::Pir { l, r } => format!(
168            "({} {})",
169            unparse(l, dict), unparse(r, dict)
170        )
171    }
172}