lisp_read.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* Copyright (C) 2016 Jeremiah Orians
  2. * This file is part of stage0.
  3. *
  4. * stage0 is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * stage0 is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "lisp.h"
  18. #include <stdint.h>
  19. #include <string.h>
  20. FILE* source_file;
  21. int Reached_EOF;
  22. struct cell* token_stack;
  23. struct cell* make_sym(char* name);
  24. struct cell* intern(char *name);
  25. struct cell* findsym(char *name);
  26. /****************************************************************
  27. * "Convert a string into a list of tokens." *
  28. ****************************************************************/
  29. struct cell* tokenize(struct cell* head, char* fullstring, int size)
  30. {
  31. int i = 0;
  32. int done = FALSE;
  33. if((0 >= size) || (0 == fullstring[0]))
  34. {
  35. return head;
  36. }
  37. char *store = calloc(MAX_STRING + 1, sizeof(char));
  38. int c;
  39. do
  40. {
  41. c = fullstring[i];
  42. if((i > size) || (MAX_STRING <= i))
  43. {
  44. done = TRUE;
  45. }
  46. else if(34 == c)
  47. {
  48. store[i] = c;
  49. i = i + 1;
  50. while(34 != fullstring[i])
  51. {
  52. store[i] = fullstring[i];
  53. i = i + 1;
  54. }
  55. i = i + 1;
  56. done = TRUE;
  57. }
  58. else
  59. {
  60. if((' ' == c) || ('\t' == c) || ('\n' == c) | ('\r' == c))
  61. {
  62. i = i + 1;
  63. done = TRUE;
  64. }
  65. else
  66. {
  67. store[i] = c;
  68. i = i + 1;
  69. }
  70. }
  71. } while(!done);
  72. if(i > 1)
  73. {
  74. struct cell* temp = make_sym(store);
  75. temp->cdr = head;
  76. head = temp;
  77. }
  78. else
  79. {
  80. free(store);
  81. }
  82. head = tokenize(head, (fullstring+i), (size - i));
  83. return head;
  84. }
  85. int is_integer(char* a)
  86. {
  87. if(('0' <= a[0]) && ('9' >= a[0]))
  88. {
  89. return TRUE;
  90. }
  91. if('-' == a[0])
  92. {
  93. if(('0' <= a[1]) && ('9' >= a[1]))
  94. {
  95. return TRUE;
  96. }
  97. }
  98. return FALSE;
  99. }
  100. /********************************************************************
  101. * Numbers become numbers *
  102. * Strings become strings *
  103. * Functions become functions *
  104. * quoted things become quoted *
  105. * Everything is treated like a symbol *
  106. ********************************************************************/
  107. struct cell* atom(struct cell* a)
  108. {
  109. /* Check for quotes */
  110. if('\'' == a->string[0])
  111. {
  112. a->string = a->string + 1;
  113. return make_cons(quote, make_cons(a, nil));
  114. }
  115. /* Check for strings */
  116. if(34 == a->string[0])
  117. {
  118. a->type = STRING;
  119. a->string = a->string + 1;
  120. return a;
  121. }
  122. /* Check for integer */
  123. if(is_integer(a->string))
  124. {
  125. a->type = INT;
  126. a->value = numerate_string(a->string);
  127. return a;
  128. }
  129. /* Check for functions */
  130. struct cell* op = findsym(a->string);
  131. if(nil != op)
  132. {
  133. return op->car;
  134. }
  135. /* Assume new symbol */
  136. all_symbols = make_cons(a, all_symbols);
  137. return a;
  138. }
  139. /****************************************************************
  140. * "Read an expression from a sequence of tokens." *
  141. ****************************************************************/
  142. struct cell* readlist();
  143. struct cell* readobj()
  144. {
  145. struct cell* head = token_stack;
  146. token_stack = head->cdr;
  147. head->cdr = NULL;
  148. if (match("(", head->string))
  149. {
  150. return readlist();
  151. }
  152. return atom(head);
  153. }
  154. struct cell* readlist()
  155. {
  156. struct cell* head = token_stack;
  157. if (match(")", head->string))
  158. {
  159. token_stack = head->cdr;
  160. return nil;
  161. }
  162. struct cell* tmp = readobj();
  163. /* token_stack = head->cdr; */
  164. return make_cons(tmp,readlist());
  165. }
  166. /****************************************************
  167. * Put list of tokens in correct order *
  168. ****************************************************/
  169. struct cell* reverse_list(struct cell* head)
  170. {
  171. struct cell* root = NULL;
  172. struct cell* next;
  173. while(NULL != head)
  174. {
  175. next = head->cdr;
  176. head->cdr = root;
  177. root = head;
  178. head = next;
  179. }
  180. return root;
  181. }
  182. /****************************************************
  183. * "Read a Scheme expression from a string." *
  184. ****************************************************/
  185. struct cell* parse(char* program, int size)
  186. {
  187. token_stack = tokenize(NULL, program, size);
  188. if(NULL == token_stack)
  189. {
  190. return nil;
  191. }
  192. token_stack = reverse_list(token_stack);
  193. return readobj();
  194. }
  195. /****************************************************
  196. * Do the heavy lifting of reading an s-expreesion *
  197. ****************************************************/
  198. unsigned Readline(FILE* source_file, char* temp)
  199. {
  200. int c;
  201. unsigned i;
  202. unsigned depth = 0;
  203. for(i = 0; i < MAX_STRING; i = i + 1)
  204. {
  205. restart_comment:
  206. c = fgetc(source_file);
  207. if((-1 == c) || (4 == c))
  208. {
  209. return i;
  210. }
  211. else if(';' == c)
  212. {
  213. /* drop everything until we hit newline */
  214. while('\n' != c)
  215. {
  216. c = fgetc(source_file);
  217. }
  218. goto restart_comment;
  219. }
  220. else if('"' == c)
  221. { /* Deal with strings */
  222. temp[i] = c;
  223. i = i + 1;
  224. c = fgetc(source_file);
  225. while('"' != c)
  226. {
  227. temp[i] = c;
  228. i = i + 1;
  229. c = fgetc(source_file);
  230. }
  231. temp[i] = c;
  232. }
  233. else if((0 == depth) && (('\n' == c) || ('\r' == c) || (' ' == c) || ('\t' == c)))
  234. {
  235. goto Line_complete;
  236. }
  237. else if(('(' == c) || (')' == c))
  238. {
  239. if('(' == c)
  240. {
  241. depth = depth + 1;
  242. }
  243. if(')' == c)
  244. {
  245. depth = depth - 1;
  246. }
  247. temp[i] = ' ';
  248. temp[i+1] = c;
  249. temp[i+2] = ' ';
  250. i = i + 2;
  251. }
  252. else
  253. {
  254. temp[i] = c;
  255. }
  256. }
  257. Line_complete:
  258. if(1 > i)
  259. {
  260. return Readline(source_file, temp);
  261. }
  262. return i;
  263. }