/* 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 . */ #include "lisp.h" #include #include #define max_string 255 FILE* source_file; bool Reached_EOF; static struct cell* token_stack; struct cell* make_sym(char* name); struct cell* intern(char *name); struct cell* findsym(char *name); struct cell* append_Cell(struct cell* head, struct cell* tail) { if(NULL == head) { return tail; } if(NULL == head->cdr) { head->cdr = tail; return head; } append_Cell(head->cdr, tail); return head; } /**************************************************************** * def tokenize(s): * * "Convert a string into a list of tokens." * * return s.replace('(',' ( ').replace(')',' ) ').split() * ****************************************************************/ struct cell* tokenize(struct cell* head, char* fullstring, int32_t size) { int32_t c; int32_t i = 0; bool done = false; if((0 >= size) || (0 == fullstring[0])) { return head; } char *store = calloc(max_string + 1, sizeof(char)); do { c = fullstring[i]; if((i > size) || (max_string <= i)) { 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) { head = append_Cell(head, make_sym(store)); } else { free(store); } head = tokenize(head, (fullstring+i), (size - i)); return head; } bool 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; } /******************************************************************** * def atom(token): * * "Numbers become numbers; every other token is a symbol." * * try: return int(token) * * except ValueError: * * try: return float(token) * * except ValueError: * * return Symbol(token) * ********************************************************************/ 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 integer */ if(is_integer(a->string)) { a->type = INT; a->value = atoi(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; } /**************************************************************** * def read_from_tokens(tokens): * * "Read an expression from a sequence of tokens." * * if len(tokens) == 0: * * raise SyntaxError('unexpected EOF while reading') * * token = tokens.pop(0) * * if '(' == token: * * L = [] * * while tokens[0] != ')': * * L.append(read_from_tokens(tokens)) * * tokens.pop(0) # pop off ')' * * return L * * elif ')' == token: * * raise SyntaxError('unexpected )') * * else: * * return atom(token) * ****************************************************************/ struct cell* readlist(); struct cell* readobj() { cell* head = token_stack; token_stack = head->cdr; head->cdr = NULL; if (! strncmp("(", head->string, max_string)) { return readlist(); } return atom(head); } struct cell* readlist() { cell* head = token_stack; if (! strncmp(")", head->string, max_string)) { token_stack = head->cdr; return nil; } cell* tmp = readobj(); // token_stack = head->cdr; return make_cons(tmp,readlist()); } /**************************************************** * def parse(program): * * "Read a Scheme expression from a string." * * return read_from_tokens(tokenize(program)) * ****************************************************/ struct cell* parse(char* program, int32_t size) { token_stack = tokenize(NULL, program, size); if(NULL == token_stack) { return nil; } return readobj(); } uint32_t Readline(FILE* source_file, char* temp) { char store[max_string + 2] = {0}; int32_t c; uint32_t i; uint32_t depth = 0; for(i = 0; i < max_string; i = i + 1) { c = fgetc(source_file); if(-1 == c) { exit(EXIT_SUCCESS); } else if((0 == depth) && ((10 == c) || (13 == c) || (32 == c) || (9 == c))) { goto Line_complete; } else if(('(' == c) || (')' == c)) { if('(' == c) { depth = depth + 1; } if(')' == c) { depth = depth - 1; } store[i] = ' '; store[i+1] = c; store[i+2] = ' '; i = i + 2; } else { store[i] = (char)c; } } Line_complete: if(1 > i) { return Readline(source_file, temp); } strncpy(temp, store, max_string); return i; }