123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /* Copyright (C) 2016 Jeremiah Orians
- * This file is part of stage0.
- *
- * stage0 is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * stage0 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with stage0. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "lisp.h"
- #include <stdint.h>
- #include <string.h>
- FILE* source_file;
- int Reached_EOF;
- struct cell* token_stack;
- struct cell* make_sym(char* name);
- struct cell* intern(char *name);
- struct cell* findsym(char *name);
- /****************************************************************
- * "Convert a string into a list of tokens." *
- ****************************************************************/
- struct cell* tokenize(struct cell* head, char* fullstring, int size)
- {
- int i = 0;
- int done = FALSE;
- if((0 >= size) || (0 == fullstring[0]))
- {
- return head;
- }
- char *store = calloc(MAX_STRING + 1, sizeof(char));
- int c;
- do
- {
- c = fullstring[i];
- if((i > size) || (MAX_STRING <= i))
- {
- done = TRUE;
- }
- else if(34 == c)
- {
- store[i] = c;
- i = i + 1;
- while(34 != fullstring[i])
- {
- store[i] = fullstring[i];
- i = i + 1;
- }
- i = i + 1;
- done = TRUE;
- }
- else
- {
- if((' ' == c) || ('\t' == c) || ('\n' == c) | ('\r' == c))
- {
- i = i + 1;
- done = TRUE;
- }
- else
- {
- store[i] = c;
- i = i + 1;
- }
- }
- } while(!done);
- if(i > 1)
- {
- struct cell* temp = make_sym(store);
- temp->cdr = head;
- head = temp;
- }
- else
- {
- free(store);
- }
- head = tokenize(head, (fullstring+i), (size - i));
- return head;
- }
- int is_integer(char* a)
- {
- if(('0' <= a[0]) && ('9' >= a[0]))
- {
- return TRUE;
- }
- if('-' == a[0])
- {
- if(('0' <= a[1]) && ('9' >= a[1]))
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- /********************************************************************
- * Numbers become numbers *
- * Strings become strings *
- * Functions become functions *
- * quoted things become quoted *
- * Everything is treated like a symbol *
- ********************************************************************/
- struct cell* atom(struct cell* a)
- {
- /* Check for quotes */
- if('\'' == a->string[0])
- {
- a->string = a->string + 1;
- return make_cons(quote, make_cons(a, nil));
- }
- /* Check for strings */
- if(34 == a->string[0])
- {
- a->type = STRING;
- a->string = a->string + 1;
- return a;
- }
- /* Check for integer */
- if(is_integer(a->string))
- {
- a->type = INT;
- a->value = strtoint(a->string);
- return a;
- }
- /* Check for functions */
- struct cell* op = findsym(a->string);
- if(nil != op)
- {
- return op->car;
- }
- /* Assume new symbol */
- all_symbols = make_cons(a, all_symbols);
- return a;
- }
- /****************************************************************
- * "Read an expression from a sequence of tokens." *
- ****************************************************************/
- struct cell* readlist();
- struct cell* readobj()
- {
- struct cell* head = token_stack;
- token_stack = head->cdr;
- head->cdr = NULL;
- if (match("(", head->string))
- {
- return readlist();
- }
- return atom(head);
- }
- struct cell* readlist()
- {
- struct cell* head = token_stack;
- if (match(")", head->string))
- {
- token_stack = head->cdr;
- return nil;
- }
- struct cell* tmp = readobj();
- /* token_stack = head->cdr; */
- return make_cons(tmp,readlist());
- }
- /****************************************************
- * Put list of tokens in correct order *
- ****************************************************/
- struct cell* reverse_list(struct cell* head)
- {
- struct cell* root = NULL;
- struct cell* next;
- while(NULL != head)
- {
- next = head->cdr;
- head->cdr = root;
- root = head;
- head = next;
- }
- return root;
- }
- /****************************************************
- * "Read a Scheme expression from a string." *
- ****************************************************/
- struct cell* parse(char* program, int size)
- {
- token_stack = tokenize(NULL, program, size);
- if(NULL == token_stack)
- {
- return nil;
- }
- token_stack = reverse_list(token_stack);
- return readobj();
- }
- /****************************************************
- * Do the heavy lifting of reading an s-expreesion *
- ****************************************************/
- unsigned Readline(FILE* source_file, char* temp)
- {
- int c;
- unsigned i;
- unsigned depth = 0;
- for(i = 0; i < MAX_STRING; i = i + 1)
- {
- restart_comment:
- c = fgetc(source_file);
- if((-1 == c) || (4 == c))
- {
- return i;
- }
- else if(';' == c)
- {
- /* drop everything until we hit newline */
- while('\n' != c)
- {
- c = fgetc(source_file);
- }
- goto restart_comment;
- }
- else if('"' == c)
- { /* Deal with strings */
- temp[i] = c;
- i = i + 1;
- c = fgetc(source_file);
- while('"' != c)
- {
- temp[i] = c;
- i = i + 1;
- c = fgetc(source_file);
- }
- temp[i] = c;
- }
- else if((0 == depth) && (('\n' == c) || ('\r' == c) || (' ' == c) || ('\t' == c)))
- {
- goto Line_complete;
- }
- else if(('(' == c) || (')' == c))
- {
- if('(' == c)
- {
- depth = depth + 1;
- }
- if(')' == c)
- {
- depth = depth - 1;
- }
- temp[i] = ' ';
- temp[i+1] = c;
- temp[i+2] = ' ';
- i = i + 2;
- }
- else
- {
- temp[i] = c;
- }
- }
- Line_complete:
- if(1 > i)
- {
- return Readline(source_file, temp);
- }
- return i;
- }
|