blob: be75adf651ed08059ba49dfb1ca6cb5054101039 [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#include "lisp.h"
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <stdbool.h>
6#include <stdio.h>
7
8#define MIN(a, b) (a)>(b)?(b):(a)
9
10struct alloc_list *first_a = NULL, *last_a = NULL;
11
12struct value cons (struct value car, struct value cdr)
13{
14 struct cons *c = malloc (sizeof (struct cons));
15
16 struct alloc_list *item = malloc (sizeof (struct alloc_list));
17 item->type = T_CONS;
18 item->data.cons_val = c;
19
20 if ( last_a )
21 {
22 item->prev = last_a;
23 last_a->next = item;
24 item->next = NULL;
25 }
26 else
27 {
28 item->prev = item->next = NULL;
29 first_a = last_a = item;
30 }
31
32 struct value v;
33 v.tag.type = T_CONS;
34 v.value.cons_val = c;
35
36 return v;
37}
38
39void skipws (struct istream *is)
40{
41 while ( isspace (is->peek (is)) )
42 is->get (is);
43}
44
45bool isallowedchar (char c)
46{
47 return (c >= '#' && c <= '\'') ||
48 (c >= '*' && c <= '/') ||
49 (c >= '>' && c <= '@');
50}
51
52bool issymstart (char c)
53{
54 return isalpha (c) || isallowedchar (c);
55}
56
57bool issym (char c)
58{
59 return isalpha (c) || isallowedchar (c) || isdigit (c);
60}
61
62bool readsym (struct istream *is, struct value *val)
63{
64 skipws (is);
65
66 if ( !issymstart (is->peek (is)) )
67 return false;
68
69 int size = 8;
70 char *s = malloc (size);
71
72 s[0] = is->get (is);
73
74 for ( int i = 1; ; i++ )
75 {
76 if ( issym (is->peek (is)) )
77 {
78 if ( i >= size )
79 {
80 size *= 2;
81 s = realloc (s, size);
82 }
83
84 s[i] = is->get (is);
85 }
86 else
87 {
88 s[i] = 0;
89 val->tag.type = T_SYMBOL;
90 val->tag.length = i - 1;
91 val->value.symbol_val = s;
92
93 return true;
94 }
95 }
96}
97
98bool readstr (struct istream *is, struct value *val)
99{
100 skipws (is);
101
102 if ( is->peek (is) != '"' )
103 return false;
104
105 bool escape = false;
106 int size = 8;
107 char *s = malloc (size);
108
109 (void) is->get (is);
110
111 for ( int i = 0; ; i++ )
112 {
113 if ( is->peek (is) != '"' )
114 {
115 if ( i >= size )
116 {
117 i *= 2;
118 s = realloc (s, i);
119 }
120
121 char c = is->get (is);
122
123 if ( escape && c == 'n' )
124 c = '\n';
125 else if ( escape && c == '\\' )
126 c = '\\';
127
128 if ( c == '\\' && !escape )
129 {
130 escape = true;
131 i--; // will be incremented again, UGLY.
132 }
133 else
134 {
135 escape = false;
136 s[i] = c;
137 }
138 }
139 else
140 {
141 is->get (is);
142
143 val->tag.type = T_STRING;
144 val->tag.length = i;
145 val->value.string_val = s;
146
147 return true;
148 }
149 }
150}
151
152void printval (struct value v, int depth)
153{
154 for ( int i = 0; i < depth; i++ )
155 printf(" ");
156
157 switch (v.tag.type)
158 {
159 case T_SYMBOL:
160 printf ("'%s\n", v.value.symbol_val);
161 return;
162 case T_STRING:
163 printf ("\"%s\"\n", v.value.string_val);
164 return;
165 default:
166 printf ("<unknown %d>\n", v.tag.type);
167 }
168}
169
170bool read1 (struct istream *is, struct value *val)
171{
172 if ( readsym (is, val) )
173 return true;
174
175 if ( readstr (is, val) )
176 return true;
177
178 return false;
179}
180
181struct stristream_private
182{
183 char *val;
184 int i;
185 int length;
186};
187
188int stristream_peek (struct istream *is)
189{
190 struct stristream_private *p = is->data;
191
192 if ( p->i < p->length )
193 return p->val[ p->i ];
194 else
195 return -1;
196}
197
198int stristream_get (struct istream *is)
199{
200 struct stristream_private *p = is->data;
201
202 if ( p->i < p->length )
203 return p->val[ p->i++ ];
204 else
205 return -1;
206
207}
208
209int stristream_read (struct istream *s, char *buffer, int size)
210{
211 struct stristream_private *p = s->data;
212
213 int len = MIN (size, p->length - p->i);
214 memcpy (buffer, p->val, len);
215 return len;
216}
217
218struct istream *new_stristream (char *str, int length)
219{
220 struct istream *is = malloc (sizeof (struct istream));
221 struct stristream_private *p = malloc (sizeof (struct stristream_private));
222
223 p->val = strndup (str, length);
224 p->i = 0;
225 p->length = length;
226
227 is->data = p;
228 is->get = stristream_get;
229 is->peek = stristream_peek;
230 is->read = stristream_read;
231
232 return is;
233}
234
235void del_stristream(struct istream *stristream)
236{
237 struct stristream_private *p = stristream->data;
238 free (p->val);
239 free (p);
240 free (stristream);
241}
242
243struct istream *new_stristream_nt (char *str)
244{
245 return new_stristream(str, strlen(str));
246}
247
248bool startswith (struct istream *s, const char *pattern)
249{
250 const char *check = strdup (pattern);
251 s->read (s, check, strlen (pattern));
252
253 bool res = strcmp (check, pattern) == 0;
254 free (check);
255
256 return res;
257}