1#![allow(non_snake_case, non_camel_case_types)]
21
22use alt_std::*;
23use alt_std::{format};
24
25pub struct ParseError {
26 message : String,
27 offset : usize
28}
29
30pub enum ParseResult<T> {
31 PROk(T),
32 PRErr(ParseError)
33}
34
35use ParseResult::*;
36
37impl<T : core::cmp::PartialEq> PartialEq for ParseResult<T> {
38 fn eq(&self, other: &Self) -> bool {
39 match (self, other) {
40 (PROk(s), PROk(o)) => *s == *o,
41 (PRErr (ParseError{ message: msg1, offset: offset1 }), PRErr (ParseError{ message: msg2, offset: offset2 })) => *msg1 == *msg2 && *offset1 == *offset2,
42 _ => false
43 }
44 }
45}
46
47#[derive(Clone)]
48pub enum Exp {
49 Bool(bool),
50 Char(char),
51 Int(i64),
52 Float(f64),
53 String(String),
54 Symbol(String),
55 List(Vec<Exp>),
56}
57
58impl PartialEq<Exp> for Exp {
59 fn eq(&self, other: &Exp) -> bool {
60 match (self, other) {
61 (Self::Bool(b0), Self::Bool(bo)) => b0 == bo,
62 (Self::Char(c0), Self::Char(c1)) => c0 == c1,
63 (Self::Int(i0), Self::Int(i1)) => i0 == i1,
64 (Self::Float(f0), Self::Float(f1)) => f0 == f1,
65 (Self::String(s0), Self::String(s1)) => s0 == s1,
66 (Self::Symbol(s0), Self::Symbol(s1)) => s0 == s1,
67 (Self::List(s), Self::List(o)) => {
68 if s.len() != o.len() { return false }
69 for i in 0..s.len() {
70 if !Self::eq(&s[i], &o[i]) { return false }
71 }
72 true
73 },
74 _ => false
75 }
76 }
77}
78impl Exp {
79 fn peek(src: &[u8], offset: usize) -> Option<u8> {
80 if src.len() <= offset {
81 None
82 } else {
83 Some(src[offset])
84 }
85 }
86
87 fn getchar(src: &[u8], offset: &mut usize) -> Option<u8> {
88 match Self::peek(src, *offset) {
89 None => None,
90 Some(c) => { *offset += 1; Some(c) },
91 }
92 }
93
94 fn isDigit(c: u8) -> bool {
95 match c as char {
96 c if c >= '0' && c <= '9' => true,
97 _ => false
98 }
99 }
100
101 fn isAlpha(c: u8) -> bool {
102 match c as char {
103 c if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') => true,
104 _ => false
105 }
106 }
107
108
109 fn isOp(c: u8) -> bool {
110 match c as char {
111 '+' | '-' | '*' | '/' | '%' | '~' | '!' | '@' | '#' | '$' | '^' | '&' | '|' | '_' | '=' | '<' | '>' | '?' | '.' | ':' | '\\' | '\'' => true,
112 _ => false
113 }
114 }
115
116 fn isWS(c: u8) -> bool {
117 match c as char {
118 ' ' | '\n' | '\t' => true,
119 _ => false
120 }
121 }
122
123 fn isSeparator(c: u8) -> bool {
124 match c as char {
125 '(' | ')' | '{' | '}' | ',' | '\'' | '"' => true,
126 x if Self::isWS(x as u8) => true,
127 _ => false
128 }
129 }
130
131 pub fn parseNumber(src: &[u8], offset: &mut usize) -> ParseResult<Exp> {
132 let mut s = String::new();
133 loop {
134 match Self::peek(src, *offset) {
135 Some(c) if c == b'+' || c == b'-' || c == b'.' || c == b'e' || c == b'E' || Self::isDigit(c) => {
136 s.add(c);
137 Self::getchar(src, offset);
138 },
139 Some(c) if Self::isSeparator(c) => break,
140 None => break,
141 _ => return PRErr (ParseError { message: String::from("Unexpected end of stream (sign)"), offset: *offset })
142 }
143 }
144
145 match str::parse::<i64>(s.toStr()) {
146 Ok(i) => return ParseResult::PROk(Exp::Int(i)),
147 _ => ()
148 }
149
150 match str::parse::<f64>(s.toStr()) {
151 Ok(f) => return ParseResult::PROk(Exp::Float(f)),
152 _ => ()
153 }
154
155 PRErr (ParseError { message: String::from("invalid number format"), offset: *offset })
156 }
157
158 fn parseString(src: &[u8], offset: &mut usize) -> ParseResult<String> {
159 let mut s = String::new();
160 match Self::peek(src, *offset) {
161 Some(c) if c as char == '"' => (),
162 _ => return PRErr (ParseError{ message: String::from("Expected \""), offset: *offset })
163 }
164
165 Self::getchar(src, offset);
166 loop {
168 match Self::getchar(src, offset) {
169 None => return PRErr (ParseError{ message: String::from("Unexpected end of stream (string)"), offset: *offset }),
170 Some(c) if c as char == '"' => break,
171 Some(c) => s.add(c),
172 }
173 }
174
175 return PROk(s)
176 }
177
178 fn parseSymbol(src: &[u8], offset: &mut usize) -> ParseResult<String> {
179 let mut s = String::new();
180 match Self::peek(src, *offset) {
181 Some(c) if Self::isAlpha(c) || Self::isOp(c) => (),
182 _ => return PRErr (ParseError{ message: String::from("Expected alpha/operator"), offset: *offset })
183 }
184
185 loop {
186 match Self::peek(src, *offset) {
187 Some(c) if Self::isAlpha(c) || Self::isOp(c) || Self::isDigit(c) => s.add(c),
188 _ => break,
189 }
190 Self::getchar(src, offset);
191 }
192
193 return PROk(s)
194 }
195
196 fn skipWS(src: &[u8], offset: &mut usize) {
197 loop {
198 match Self::peek(src, *offset) {
199 Some(c) if Self::isWS(c) => { Self::getchar(src, offset); },
200 _ => break
201 }
202 }
203 }
204
205 fn parseToken(src: &[u8], offset: &mut usize) -> ParseResult<Exp> {
206 match Self::peek(src, *offset) {
207 Some(c) if c as char == '"' => {
208 let stringRes = Self::parseString(src, offset);
209 match stringRes {
210 PROk(r) => PROk(Exp::String(r)),
211 PRErr(err) => PRErr(err)
212 }
213 },
214 Some(c) if Self::isDigit(c) || ((c as char == '+' || c as char == '-') && match Self::peek(src, *offset + 1) { Some(c) if Self::isDigit(c) => true, _ => false }) => {
215 let numRes = Self::parseNumber(src, offset);
216 match numRes {
217 PROk(r) => PROk(r),
218 PRErr(err) => PRErr(err)
219 }
220 },
221 Some(c) if Self::isAlpha(c) || Self::isOp(c) => {
222 let symbolRes = Self::parseSymbol(src, offset);
223 match symbolRes {
224 PROk(r) => PROk(Exp::Symbol(r)),
225 PRErr(err) => PRErr(err)
226 }
227 },
228 Some(c) if c as char == '(' => Self::parseList(src, offset),
229 Some(_) => PRErr(ParseError { message: String::from("unexpected char (token)"), offset: *offset}),
230 None => PRErr(ParseError { message: String::from("unexpected end of stream (token)"), offset: *offset}),
231 }
232 }
233
234 fn parseList(src: &[u8], offset: &mut usize) -> ParseResult<Exp> {
235 match Self::getchar(src, offset) {
236 Some(c) if c as char == '(' => (),
237 Some(_) => return PRErr(ParseError { message: String::from("unexpected character (list)"), offset: *offset}),
238 None => return PRErr(ParseError { message: String::from("unexpected end of stream (list)"), offset: *offset}),
239 }
240
241 let mut cells = Vec::new();
242 loop {
243 Self::skipWS(src, offset);
244 match Self::peek(src, *offset) {
245 Some(c) if c as char == ')' => {
246 Self::getchar(src, offset);
247 return PROk(Exp::List(cells))
248 },
249 Some(_) => {
250 match Self::parseToken(src, offset) {
251 PROk(c) => cells.pushBack(c),
252 PRErr(err) => return PRErr(err),
253 }
254 },
255 None => return PRErr(ParseError { message: String::from("unexpected end of stream (list)"), offset: *offset})
256 }
257 }
258 }
259
260 pub fn fromSExp(src: &[u8]) -> ParseResult<Exp> {
261 let mut offset : usize = 0;
262 Self::skipWS(src, &mut offset);
263 Self::parseToken(src, &mut offset)
264 }
265
266 pub fn toString(&self) -> String {
267 match self {
268 Self::Bool(b) => format!("{}", b),
269 Self::Char(c) => format!("{}", c),
270 Self::Int(i) => format!("{}", i),
271 Self::Float(f) => format!("{}", f),
272 Self::String(s) => {
273 let mut sr = String::new();
274 sr.add('"' as u8);
275 let a = s.asArray();
276 for i in a.iter() {
277 sr.add(*i);
278 }
279 sr.add('"' as u8);
280 sr
281 },
282 Self::Symbol(s) => s.clone(),
283 Self::List(l) => {
284 let mut s = String::new();
285 s.add('(' as u8);
286 for i in 0..l.len() {
287 s.append(&(l[i].toString()));
288 if i != l.len() - 1 {
289 s.add(' ' as u8);
290 }
291 }
292 s.add(')' as u8);
293 s
294 }
295 }
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302
303 #[test]
304 fn testParseInt() {
305 let s = String::from("1234");
306 let mut offset = 0;
307 let res = Exp::parseNumber(s.asArray(), &mut offset);
308 assert!(res == PROk(Exp::Int(1234)));
309
310 let s = String::from("-001234");
311 let mut offset = 0;
312 let res = Exp::parseNumber(s.asArray(), &mut offset);
313 assert!(res == PROk(Exp::Int(-1234)));
314
315 let s = String::from("-1234");
316 let mut offset = 0;
317 let res = Exp::parseNumber(s.asArray(), &mut offset);
318 assert!(res == PROk(Exp::Int(-1234)));
319
320 let s = String::from("-1234 ");
321 let mut offset = 0;
322 let res = Exp::parseNumber(s.asArray(), &mut offset);
323 assert!(res == PROk(Exp::Int(-1234)));
324
325 let s = String::from("-1234+");
326 let mut offset = 0;
327 let res = Exp::parseNumber(s.asArray(), &mut offset);
328 assert!(res != PROk(Exp::Int(-1234)));
329
330 let s = String::from("-1234a");
331 let mut offset = 0;
332 let res = Exp::parseNumber(s.asArray(), &mut offset);
333 assert!(res != PROk(Exp::Int(-1234)));
334 }
335
336 #[test]
337 fn testParseFloat() {
338 let s = String::from("1234.");
339 let mut offset = 0;
340 let res = Exp::parseNumber(s.asArray(), &mut offset);
341 assert!(res == PROk(Exp::Float(1234.)));
342
343 let s = String::from("1234.0");
344 let mut offset = 0;
345 let res = Exp::parseNumber(s.asArray(), &mut offset);
346 assert!(res == PROk(Exp::Float(1234.)));
347
348 let s = String::from("-001234.0");
349 let mut offset = 0;
350 let res = Exp::parseNumber(s.asArray(), &mut offset);
351 assert!(res == PROk(Exp::Float(-1234.)));
352
353 let s = String::from("-1234.0");
354 let mut offset = 0;
355 let res = Exp::parseNumber(s.asArray(), &mut offset);
356 assert!(res == PROk(Exp::Float(-1234.)));
357
358 let s = String::from("-1234.0 ");
359 let mut offset = 0;
360 let res = Exp::parseNumber(s.asArray(), &mut offset);
361 assert!(res == PROk(Exp::Float(-1234.)));
362
363 let s = String::from("-1234.0+");
364 let mut offset = 0;
365 let res = Exp::parseNumber(s.asArray(), &mut offset);
366 assert!(res != PROk(Exp::Float(-1234.)));
367
368 let s = String::from("-1234.0a");
369 let mut offset = 0;
370 let res = Exp::parseNumber(s.asArray(), &mut offset);
371 assert!(res != PROk(Exp::Float(-1234.)));
372
373 let s = String::from("-001234.0E10");
374 let mut offset = 0;
375 let res = Exp::parseNumber(s.asArray(), &mut offset);
376 assert!(res == PROk(Exp::Float(-1234.0E10)));
377
378 let s = String::from("-001234.0E-10");
379 let mut offset = 0;
380 let res = Exp::parseNumber(s.asArray(), &mut offset);
381 assert!(res == PROk(Exp::Float(-1234.0E-10)));
382 }
383
384 #[test]
385 fn testParseString() {
386 let s = String::from("\"1234\"");
387 let mut offset = 0;
388 let res = Exp::parseString(s.asArray(), &mut offset);
389 assert!(res == PROk(String::from("1234")));
390
391 let s = String::from("\"1234");
392 let mut offset = 0;
393 let res = Exp::parseString(s.asArray(), &mut offset);
394 assert!(res != PROk(String::from("1234")));
395 }
396
397 #[test]
398 fn testParseSymbol() {
399 let s = String::from("#t");
400 let mut offset = 0;
401 let res = Exp::parseSymbol(s.asArray(), &mut offset);
402 assert!(res == PROk(String::from("#t")));
403
404 let s = String::from("t123");
405 let mut offset = 0;
406 let res = Exp::parseSymbol(s.asArray(), &mut offset);
407 assert!(res == PROk(String::from("t123")));
408
409 let s = String::from("t123(");
410 let mut offset = 0;
411 let res = Exp::parseSymbol(s.asArray(), &mut offset);
412 assert!(res == PROk(String::from("t123")));
413
414 let s = String::from("t123+=");
415 let mut offset = 0;
416 let res = Exp::parseSymbol(s.asArray(), &mut offset);
417 assert!(res == PROk(String::from("t123+=")));
418
419 let s = String::from("12t123");
420 let mut offset = 0;
421 let res = Exp::parseSymbol(s.asArray(), &mut offset);
422 assert!(res != PROk(String::from("12t123")));
423 }
424
425 #[test]
426 fn testParseList() {
427
428 let cells : [Exp; 3] = [Exp::Symbol(String::from("abcd")), Exp::Int(123), Exp::Symbol(String::from("abc"))];
429
430 let sexp = String::from("(abcd 123 abc)");
431 let res : ParseResult<Exp> = Exp::fromSExp(sexp.asArray());
432 match res {
433 PROk(r) => {
434 let mut v = Vec::new();
435 for c in cells.iter() {
436 v.pushBack(c.clone());
437 }
438 let e = Exp::List(Vec::from(v));
439 assert!(Exp::eq(&e, &r))
440 },
441 PRErr(err) => panic!("{}", err.message.toStr())
442 }
443 }
444
445 #[test]
446 fn testParseListString() {
447 let sexp = String::from("(abcd 123 abc)");
448 let res = Exp::fromSExp(sexp.asArray());
449 match res {
450 PROk(r) => {
451 let s = r.toString();
452 assert!(s == "(abcd 123 abc)")
453 },
454 PRErr(err) => panic!("{}", err.message.toStr())
455 }
456 }
457}