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 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#[derive(Clone, Debug)]
43pub struct PrsErr {
44 pub msg: &'static str,
45 pub pos: usize,
46}
47
48struct 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 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 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}