diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-06 22:13:14 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-06 22:13:14 -0500 |
| commit | 53beaa0a6ddd9d8a5fb531f97c44a9c7129d1de7 (patch) | |
| tree | aad0aa97a9a7f54aed1cc26561aa22cea931f2fe /cs/reader.cs | |
| parent | b2ff794a97a80f8acac1914c679222fda5a3355c (diff) | |
| download | mal-53beaa0a6ddd9d8a5fb531f97c44a9c7129d1de7.tar.gz mal-53beaa0a6ddd9d8a5fb531f97c44a9c7129d1de7.zip | |
CS: add step1_read_print
Diffstat (limited to 'cs/reader.cs')
| -rw-r--r-- | cs/reader.cs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/cs/reader.cs b/cs/reader.cs new file mode 100644 index 0000000..5e38136 --- /dev/null +++ b/cs/reader.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Mal; +using MalVal = Mal.types.MalVal; +using MalList = Mal.types.MalList; +using MalVector = Mal.types.MalVector; +using MalHashMap = Mal.types.MalHashMap; +using MalThrowable = Mal.types.MalThrowable; +using MalContinue = Mal.types.MalContinue; + +namespace Mal { + public class reader { + public class ParseError : MalThrowable { + public ParseError(string msg) : base(msg) { } + } + + public class Reader { + List<string> tokens; + int position; + public Reader(List<string> t) { + tokens = t; + position = 0; + } + + public string peek() { + if (position >= tokens.Count) { + return null; + } else { + return tokens[position]; + } + } + public string next() { + return tokens[position++]; + } + } + + public static List<string> tokenize(string str) { + List<string> tokens = new List<string>(); + string pattern = @"[\s ,]*(~@|[\[\]{}()'`~@]|""(?:[\\].|[^\\""])*""|;.*|[^\s \[\]{}()'""`~@,;]*)"; + Regex regex = new Regex(pattern); + foreach (Match match in regex.Matches(str)) { + string token = match.Groups[1].Value; + if ((token != null) && !(token == "") && !(token[0] == ';')) { + //Console.WriteLine("match: ^" + match.Groups[1] + "$"); + tokens.Add(token); + } + } + return tokens; + } + + public static MalVal read_atom(Reader rdr) { + string token = rdr.next(); + string pattern = @"(^-?[0-9]+$)|(^-?[0-9][0-9.]*$)|(^nil$)|(^true$)|(^false$)|^""(.*)""$|(^[^""]*$)"; + Regex regex = new Regex(pattern); + Match match = regex.Match(token); + //Console.WriteLine("token: ^" + token + "$"); + if (!match.Success) { + throw new ParseError("unrecognized token '" + token + "'"); + } + if (match.Groups[1].Value != String.Empty) { + return new Mal.types.MalInteger(int.Parse(match.Groups[1].Value)); + } else if (match.Groups[3].Value != String.Empty) { + return Mal.types.Nil; + } else if (match.Groups[4].Value != String.Empty) { + return Mal.types.True; + } else if (match.Groups[5].Value != String.Empty) { + return Mal.types.False; + } else if (match.Groups[6].Value != String.Empty) { + //return new MalString(StringEscapeUtils.unescapeJson(match.Groups[6])); + return new Mal.types.MalString(match.Groups[6].Value); + } else if (match.Groups[7].Value != String.Empty) { + return new Mal.types.MalSymbol(match.Groups[7].Value); + } else { + throw new ParseError("unrecognized '" + match.Groups[0] + "'"); + } + } + + public static MalVal read_list(Reader rdr, MalList lst, char start, char end) { + string token = rdr.next(); + if (token[0] != start) { + throw new ParseError("expected '" + start + "'"); + } + + while ((token = rdr.peek()) != null && token[0] != end) { + lst.conj_BANG(read_form(rdr)); + } + + if (token == null) { + throw new ParseError("expected '" + end + "', got EOF"); + } + rdr.next(); + + return lst; + } + + public static MalVal read_hash_map(Reader rdr) { + MalList lst = (MalList)read_list(rdr, new MalList(), '{', '}'); + return new MalHashMap(lst); + } + + + public static MalVal read_form(Reader rdr) { + string token = rdr.peek(); + if (token == null) { throw new MalContinue(); } + MalVal form = null; + + switch (token[0]) { + case '(': form = read_list(rdr, new MalList(), '(' , ')'); break; + case ')': throw new ParseError("unexpected ')'"); + case '[': form = read_list(rdr, new MalVector(), '[' , ']'); break; + case ']': throw new ParseError("unexpected ']'"); + case '{': form = read_hash_map(rdr); break; + case '}': throw new ParseError("unexpected '}'"); + default: form = read_atom(rdr); break; + } + return form; + } + + + public static MalVal read_str(string str) { + return read_form(new Reader(tokenize(str))); + } + } +} |
