Merge pull request #138 from dubek/js-fix-quasiquote-nil
[jackhill/mal.git] / matlab / reader.m
CommitLineData
9a54ea18
JM
1% this is just being used as a namespace
2classdef reader
3 methods (Static = true)
4 function tokens = tokenize(str)
7f567f36 5 re = '[\s,]*(~@|[\[\]{}()''`~^@]|"(?:\\.|[^\\"])*"|;[^\n]*|[^\s\[\]{}(''"`,;)]*)';
9a54ea18
JM
6 % extract the capture group (to ignore spaces and commas)
7 tokens = cellfun(@(x) x(1), regexp(str, re, 'tokens'));
7f567f36
JM
8 comments = cellfun(@(x) length(x) > 0 && x(1) == ';', tokens);
9 tokens = tokens(~comments);
9a54ea18
JM
10 end
11
12 function atm = read_atom(rdr)
13 token = rdr.next();
14 %fprintf('in read_atom: %s\n', token);
15 if not(isempty(regexp(token, '^-?[0-9]+$', 'match')))
16 atm = str2double(token);
17 elseif strcmp(token(1), '"')
18 atm = token(2:length(token)-1);
6d12affa
JM
19 atm = strrep(atm, '\"', '"');
20 atm = strrep(atm, '\n', char(10));
6a572dff 21 elseif strcmp(token(1), ':')
e0188ffe 22 atm = types.keyword(token(2:end));
d6624158
JM
23 elseif strcmp(token, 'nil')
24 atm = types.nil;
9a54ea18
JM
25 elseif strcmp(token, 'true')
26 atm = true;
27 elseif strcmp(token, 'false')
28 atm = false;
29 else
30 atm = types.Symbol(token);
31 end
32 end
33
6a572dff
JM
34 function seq = read_seq(rdr, start, last)
35 %fprintf('in read_seq\n');
36 seq = {};
9a54ea18 37 token = rdr.next();
6a572dff 38 if not(strcmp(token, start))
0b234e13 39 error(sprintf('expected ''%s''', start));
9a54ea18
JM
40 end
41 token = rdr.peek();
42 while true
43 if eq(token, false)
0b234e13 44 error(sprintf('expected ''%s''', last));
9a54ea18 45 end
6a572dff
JM
46 if strcmp(token, last), break, end
47 seq{end+1} = reader.read_form(rdr);
9a54ea18
JM
48 token = rdr.peek();
49 end
50 rdr.next();
51 end
52
6a572dff
JM
53 function lst = read_list(rdr)
54 seq = reader.read_seq(rdr, '(', ')');
55 lst = types.List(seq{:});
56 end
57
58 function vec = read_vector(rdr)
59 seq = reader.read_seq(rdr, '[', ']');
60 vec = types.Vector(seq{:});
61 end
62
63 function map = read_hash_map(rdr)
64 seq = reader.read_seq(rdr, '{', '}');
65 map = types.HashMap(seq{:});
66 end
67
9a54ea18
JM
68 function ast = read_form(rdr)
69 %fprintf('in read_form\n');
70 token = rdr.peek();
c3023f26
JM
71 switch token
72 case ''''
73 rdr.next();
6a572dff
JM
74 ast = types.List(types.Symbol('quote'), ...
75 reader.read_form(rdr));
c3023f26
JM
76 case '`'
77 rdr.next();
6a572dff
JM
78 ast = types.List(types.Symbol('quasiquote'), ...
79 reader.read_form(rdr));
c3023f26
JM
80 case '~'
81 rdr.next();
6a572dff
JM
82 ast = types.List(types.Symbol('unquote'), ...
83 reader.read_form(rdr));
c3023f26
JM
84 case '~@'
85 rdr.next();
6a572dff
JM
86 ast = types.List(types.Symbol('splice-unquote'), ...
87 reader.read_form(rdr));
53942f88
JM
88 case '^'
89 rdr.next();
90 meta = reader.read_form(rdr);
91 ast = types.List(types.Symbol('with-meta'), ...
92 reader.read_form(rdr), meta);
93 case '@'
94 rdr.next();
95 ast = types.List(types.Symbol('deref'), ...
96 reader.read_form(rdr));
97
9a54ea18
JM
98 case ')'
99 error('unexpected '')''');
100 case '('
101 ast = reader.read_list(rdr);
6a572dff
JM
102 case ']'
103 error('unexpected '']''');
104 case '['
105 ast = reader.read_vector(rdr);
106 case '}'
107 error('unexpected ''}''');
108 case '{'
109 ast = reader.read_hash_map(rdr);
9a54ea18
JM
110 otherwise
111 ast = reader.read_atom(rdr);
112 end
113 end
114
115 function ast = read_str(str)
116 %fprintf('in read_str\n');
117 tokens = reader.tokenize(str);
751ab516 118 rdr = types.Reader(tokens);
9a54ea18
JM
119 ast = reader.read_form(rdr);
120 end
121 end
122end