ic/term/
syntax.rs

1// Term parser and stringifier. Grammar:
2// <Term> ::= <Lam> | <App> | <Sup> | <Dup> | <Var> | <Set>
3// <Lam>  ::= "λ" <name> <Term>
4// <App>  ::= "(" <Term> <Term> ")"
5// <Ann>  ::= "<" <Term> ":" <Term> ")"
6// <Sup>  ::= "{" <Term> <Term> "}" ["#" <tag>]
7// <Dup>  ::= "dup" ["#" <tag>] <name> <name> "=" <Term> [";"] <Term>
8// <Var>  ::= <name>
9// <Set>  ::= "*"
10// <name> ::= <alphanumeric_name>
11// <tag>  ::= <positive_integer>
12
13use super::*;
14
15// Parses a name, returns the remaining code and the name.
16fn is_name_char(c: Chr) -> bool {
17  false
18  || (c >= b'A' && c <= b'Z')
19  || (c >= b'a' && c <= b'z')
20  || (c >= b'0' && c <= b'9')
21  || (c == b'_')
22  || (c == b'.')
23}
24
25fn parse_name(code: &Str) -> (&Str, &Str) {
26  let code = skip_whitespace(code);
27  let mut i: usize = 0;
28  while i < code.len() && is_name_char(code[i]) {
29    i += 1;
30  }
31  (&code[i..], &code[0..i])
32}
33
34fn skip_whitespace(code: &Str) -> &Str {
35  let mut i: usize = 0;
36  while i < code.len() && (code[i] == b' ' || code[i] == b'\n') {
37    i += 1;
38  }
39  &code[i..]
40}
41
42fn parse_text<'a>(code: &'a Str, text: &Str) -> Result<&'a Str, String> {
43  let code = skip_whitespace(code);
44  if code.starts_with(text) {
45    Ok(&code[text.len()..])
46  } else {
47    Err(format!("Expected '{}', found '{}'", String::from_utf8_lossy(text), String::from_utf8_lossy(code)))
48  }
49}
50
51// Parses a term, returns the remaining code and the term.
52pub fn parse_term<'a>(code: &'a Str, ctx: &mut Context<'a>, idx: &mut u32) -> (&'a Str, Term) {
53  let code = skip_whitespace(code);
54  match code[0] {
55    // Comment: `// many words here ... <newline>`
56    b'/' if code[1] == b'/' => {
57      let end = code.iter().position(|&c| c == b'\n').unwrap_or(code.len());
58      parse_term(&code[end..], ctx, idx)
59    }
60    // Typed Abstraction: `λ(var: Type) body`
61    b'\xce' if code[1] == b'\xbb' && code[2] == b'(' => {
62      let (code, nam) = parse_name(&code[3..]);
63      let  code       = parse_text(code, b":").unwrap();
64      let (code, typ) = parse_term(code, ctx, idx);
65      let  code       = parse_text(code, b")").unwrap();
66      extend(nam, None, ctx);
67      let (code, bod) = parse_term(code, ctx, idx);
68      narrow(ctx);
69      let nam = nam.to_vec();
70      let typ = Some(Box::new(typ));
71      let bod = Box::new(bod);
72      (code, Lam { nam, typ, bod })
73    },
74    // Untyped Abstraction: `λvar body`
75    b'\xce' if code[1] == b'\xbb' => {
76      let (code, nam) = parse_name(&code[2..]);
77      extend(nam, None, ctx);
78      let (code, bod) = parse_term(code, ctx, idx);
79      narrow(ctx);
80      let nam = nam.to_vec();
81      let typ = None;
82      let bod = Box::new(bod);
83      (code, Lam { nam, typ, bod })
84    }
85    // Application: `(func argm1 argm2 ... argmN)`
86    b'(' => {
87      let (mut code, mut fun) = parse_term(&code[1..], ctx, idx);
88      while code[0] != b')' {
89        let (new_code, arg) = parse_term(code, ctx, idx);
90        code = new_code;
91        let arg = Box::new(arg);
92        fun = App { fun: Box::new(fun), arg };
93      }
94      let code = parse_text(code, b")").unwrap();
95      (code, fun)
96    }
97    // Annotation: `<val:typ>`
98    b'<' => {
99      let (code, val) = parse_term(&code[1..], ctx, idx);
100      let code = parse_text(code, b":").unwrap();
101      let (code, typ) = parse_term(code, ctx, idx);
102      let code = parse_text(code, b">").unwrap();
103      (code, Ann { val: Box::new(val), typ: Box::new(typ) })
104    },
105    // Pair: `{val0 val1}#tag` (note: '#tag' is optional)
106    b'{' => {
107      let (code, fst) = parse_term(&code[1..], ctx, idx);
108      let (code, snd) = parse_term(code, ctx, idx);
109      let  code       = parse_text(code, b"}").unwrap();
110      let (code, tag) = if code[0] == b'#' { parse_name(&code[1..]) } else { (code, &b""[..]) };
111      let tag = name_to_index(&tag.to_vec());
112      let fst = Box::new(fst);
113      let snd = Box::new(snd);
114      (code, Sup { tag, fst, snd })
115    }
116    // Dup: `dup #tag fst snd = val; bod` (note: '#tag' and ';' are optional)
117    b'd' if code.starts_with(b"dup ") => {
118      let  code       = &code[4..];
119      let (code, tag) = if code[0] == b'#' { parse_name(&code[1..]) } else { (code, &b""[..]) };
120      let (code, fst) = parse_name(code);
121      let (code, snd) = parse_name(code);
122      let  code       = parse_text(code, b"=").unwrap();
123      extend(snd, None, ctx);
124      extend(fst, None, ctx);
125      let (code, val) = parse_term(code, ctx, idx);
126      let  code       = if code[0] == b';' { &code[1..] } else { code };
127      let (code, nxt) = parse_term(code, ctx, idx);
128      narrow(ctx);
129      narrow(ctx);
130      let tag = name_to_index(&tag.to_vec());
131      let fst = fst.to_vec();
132      let snd = snd.to_vec();
133      let val = Box::new(val);
134      let nxt = Box::new(nxt);
135      (code, Dup { tag, fst, snd, val, nxt })
136    }
137    // Definition: `def nam = val; bod` (note: ';' is optional)
138    b'd' if code.starts_with(b"def ") => {
139      let (code, nam) = parse_name(&code[4..]);
140      let  code       = parse_text(code, b"=").unwrap();
141      let (code, val) = parse_term(code, ctx, idx);
142      let  code       = if code[0] == b';' { &code[1..] } else { code };
143      extend(nam, Some(val), ctx);
144      let (code, bod) = parse_term(code, ctx, idx);
145      narrow(ctx);
146      (code, bod)
147    }
148    // Set: `*`
149    b'*' => {
150      (&code[1..], Set)
151    },
152    // Variable: `<alphanumeric_name>`
153    _ => {
154      let (code, nam) = parse_name(code);
155      let mut val: Option<Term> = None;
156      for i in (0..ctx.len()).rev() {
157        if ctx[i].0 == nam {
158          match ctx[i].1 {
159            Some(ref term) => {
160              let mut name = nam.clone().to_vec();
161              val = Some(copy(&name, *idx, term));
162              *idx += 1;
163              break;
164            }
165            None => {
166              break;
167            }
168          }
169        }
170      }
171      let nam = nam.to_vec();
172      (code, match val { Some(term) => term, None => Var { nam } })
173    }
174  }
175}
176
177// Converts a source-code to a λ-term.
178pub fn from_string<'a>(code : &'a Str) -> Term {
179  let mut ctx = Vec::new();
180  let mut idx = 0;
181  parse_term(code, &mut ctx, &mut idx).1
182}
183
184// Converts a λ-term back to a source-code.
185pub fn to_string(term : &Term) -> Vec<Chr> {
186  fn stringify_term(code : &mut Vec<u8>, term : &Term) {
187    match term {
188      &Lam{ref nam, ref typ, ref bod} => {
189        code.extend_from_slice("λ".as_bytes());
190        if let Some(ref t) = typ {
191          code.extend_from_slice(b"(");
192          code.append(&mut nam.clone());
193          code.extend_from_slice(b": ");
194          stringify_term(code, &t);
195          code.extend_from_slice(b")");
196        } else {
197          code.append(&mut nam.clone());
198        }
199        code.extend_from_slice(b" ");
200        stringify_term(code, &bod);
201      },
202      &App{ref fun, ref arg} => {
203        code.extend_from_slice(b"(");
204        stringify_term(code, &fun);
205        code.extend_from_slice(b" ");
206        stringify_term(code, &arg);
207        code.extend_from_slice(b")");
208      },
209      &Ann{ref val, ref typ} => {
210        code.extend_from_slice(b"<");
211        stringify_term(code, &val);
212        code.extend_from_slice(b": ");
213        stringify_term(code, &typ);
214        code.extend_from_slice(b">");
215      },
216      &Sup{tag, ref fst, ref snd} => {
217        code.extend_from_slice(b"[");
218        stringify_term(code, &fst);
219        code.extend_from_slice(b" ");
220        stringify_term(code, &snd);
221        if tag != 0 {
222          code.extend_from_slice(b"#");
223          code.append(&mut index_to_name(tag));
224        }
225        code.extend_from_slice(b"]");
226      },
227      &Dup{tag, ref fst, ref snd, ref val, ref nxt} => {
228        code.extend_from_slice(b"dup ");
229        if tag != 0 {
230          code.extend_from_slice(b"#");
231          code.append(&mut index_to_name(tag));
232          code.extend_from_slice(b" ");
233        }
234        code.append(&mut fst.clone());
235        code.extend_from_slice(b" ");
236        code.append(&mut snd.clone());
237        code.extend_from_slice(b" = ");
238        stringify_term(code, &val);
239        code.extend_from_slice(b"; ");
240        stringify_term(code, &nxt);
241      },
242      &Set => {
243        code.extend_from_slice(b"*");
244      },
245      &Var{ref nam} => {
246        code.append(&mut nam.clone());
247      },
248    }
249  }
250  let mut code = Vec::new();
251  stringify_term(&mut code, &term);
252  return code;
253}
254