#include "reader.h" #include "alloc.h" #include #include Cell* reader_next_list_cell(Cell* cell, ReaderState* rs) { cell->next = alloc_nil(); cell = cell->next; rs->state = PST_ATOM; return cell; } Cell* reader_end_list(Cell* cell, ReaderState* rs) { if (rs->level<1) { rs->state = PST_ERR_UNEXP_CLOSING_BRACE; return cell; } rs->level--; rs->stack--; if (cell->addr) cell->next = alloc_nil(); cell = *rs->stack; Cell* tmpc = cell; cell = reader_next_list_cell(cell, rs); rs->state = PST_ATOM; return cell; } ReaderState* read_char(char c, ReaderState* rs) { Cell* cell = rs->cell; Cell* new_cell; if (!cell) { // make a root cell = alloc_nil(); cell->next = alloc_nil(); *rs->stack = cell; } if (rs->state == PST_ATOM) { if (c==' ' || c==13 || c==10) { // skip whitespace } else if (c==';') { // comment rs->state = PST_COMMENT; } else if (c>='0' && c<='9') { rs->state = PST_NUM; rs->valuestate = VST_DEFAULT; new_cell = alloc_int(0); new_cell->value = c-'0'; cell->addr = new_cell; } else if (c=='(') { // start list new_cell = alloc_nil(); cell->addr = new_cell; *rs->stack = cell; cell = new_cell; rs->stack++; rs->level++; rs->state = PST_ATOM; } else if (c==')') { // end of list cell = reader_end_list(cell, rs); } else if (c=='[') { // bytes (hex notation) rs->state = PST_BYTES; rs->sym_len = 0; new_cell = alloc_bytes(); cell->addr = new_cell; } else if (c=='"') { // string rs->state = PST_STR; rs->sym_len = 0; new_cell = alloc_string(); cell->addr = new_cell; } else { // symbol rs->state = PST_SYM; rs->sym_len = 1; new_cell = alloc_num_bytes(SYM_INIT_BUFFER_SIZE); new_cell->tag = TAG_SYM; memset(new_cell->addr, 0, SYM_INIT_BUFFER_SIZE); ((char*)new_cell->addr)[0] = c; new_cell->size = SYM_INIT_BUFFER_SIZE; // buffer space cell->addr = new_cell; } } else if (rs->state == PST_COMMENT) { if (c=='\n' || c==0) { rs->state = PST_ATOM; } } else if (rs->state == PST_NUM || rs->state == PST_NUM_NEG) { if (c>='0' && c<='9' || ((rs->valuestate == VST_HEX && c>='a' && c<='f'))) { // build number Cell* vcell = (Cell*)cell->addr; int mul = 10; if (rs->valuestate == VST_HEX) mul = 16; int d = 0; if (c>='a') { d = 10+(c-'a'); } else { d = c-'0'; } if (rs->state == PST_NUM_NEG) { vcell->value = vcell->value*mul - d; } else { vcell->value = vcell->value*mul + d; } } else if (c==' ' || c==13 || c==10) { cell = reader_next_list_cell(cell, rs); } else if (c==')') { cell = reader_end_list(cell, rs); } else if (c=='x') { rs->valuestate = VST_HEX; } else { rs->state = PST_ERR_UNEXP_JUNK_IN_NUMBER; } } else if (rs->state == PST_SYM || rs->state == PST_STR) { int append = 0; if (rs->state == PST_STR) { if (c=='"') { // string is over Cell* vcell = (Cell*)cell->addr; vcell->size = (rs->sym_len); cell = reader_next_list_cell(cell, rs); } else { append = 1; } } else { if (c==')') { cell = reader_end_list(cell, rs); } else if (c==' ' || c==13 || c==10) { cell = reader_next_list_cell(cell, rs); } else if (rs->state == PST_SYM && (c>='0' && c<='9')) { Cell* vcell = (Cell*)cell->addr; // detect negative number if (((char*)vcell->addr)[0] == '-') { // we're actually not a symbol, correct the cell. rs->state = PST_NUM_NEG; vcell->tag = TAG_INT; vcell->value = -(c-'0'); } else { append = 1; } } else { append = 1; } } if (append) { // build symbol/string Cell* vcell = (Cell*)cell->addr; int idx = rs->sym_len; rs->sym_len++; if (rs->sym_len>=vcell->size-1) { // grow buffer vcell->addr = cell_realloc(vcell->addr, vcell->size, 2*vcell->size); memset(vcell->addr+vcell->size, 0, vcell->size); vcell->size = 2*vcell->size; } ((char*)vcell->addr)[idx] = c; } } else if (rs->state == PST_BYTES) { if (c==']') { Cell* vcell = (Cell*)cell->addr; vcell->size = (rs->sym_len)/2; cell = reader_next_list_cell(cell, rs); } else if ((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F')) { int n = c; if (n>='a') n-=('a'-'9'-1); // hex 'a' to 10 offset if (n>='A') n-=('A'-'9'-1); // hex 'a' to 10 offset n-='0'; // char to value Cell* vcell = (Cell*)cell->addr; int idx = rs->sym_len; rs->sym_len++; if (rs->sym_len>=(vcell->size/2)-1) { // grow buffer vcell->addr = cell_realloc(vcell->addr, vcell->size, 2*vcell->size); // TODO: check the math memset(vcell->addr+vcell->size, 0, vcell->size); vcell->size = 2*vcell->size; } if (idx%2==0) { // even digit ((uint8_t*)vcell->addr)[idx/2] = n<<4; // high nybble } else { // odd digit ((uint8_t*)vcell->addr)[idx/2] |= n; } } else if (c==' ' || c==13 || c==10) { // skip } else { rs->state = PST_ERR_UNEXP_JUNK_IN_BYTES; } } rs->cell = cell; return rs; } Cell* read_string(char* in) { ReaderState rs; Cell stack_root[100]; rs.state = PST_ATOM; rs.cell = 0; rs.level = 0; rs.stack = (void*)&stack_root; int i=0; int len = strlen(in); for (i=0; i=10) { //print("\n",rs.state,i); return alloc_error(ERR_SYNTAX); } //printf("rs %c: %d\n", in[i], rs.state); } if (rs.level!=0) { //print("\r\n",rs.level); return alloc_error(ERR_SYNTAX); } if (rs.state!=PST_ATOM) { //printf("\n"); //return alloc_error(ERR_SYNTAX); } Cell* root = *rs.stack; if (root) { Cell* ret = car(root); //if (root->next) free(root->next); //free(root); return ret; } return alloc_error(ERR_SYNTAX); } Cell* read_string_cell(Cell* in) { if (!in) return alloc_nil(); if (!in->size) return alloc_nil(); char* str = (char*)in->addr; str[in->size]=0; //printf("read[%s]\r\n",str); return read_string(str); }