#include #include #include #include #include // Last error from reader static char last_err[256] = {0}; fzl_reader_t *fzl_mkreader(char *source) { fzl_reader_ll_t *first_node = malloc(sizeof(fzl_reader_ll_t)); first_node->token = NULL; first_node->next = NULL; fzl_reader_t *reader = malloc(sizeof(fzl_reader_t)); reader->first = first_node; reader->last = first_node; reader->source = source; reader->size = strlen(source); reader->position = 0; reader->at_end = true; return reader; } // --- Read zone --- // Try parse name fzl_token_t *parse_name(fzl_reader_t *reader) { size_t lpos = reader->position; size_t size = 0; do { lpos++; size++; } while ((reader->source[lpos] >= 'A' && reader->source[lpos] <= 'Z') || (reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z')); char *value = malloc(size); memcpy(value, reader->source + reader->position, size); size_t start = reader->position; reader->position += size; fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NAME, start, reader->position - 1, value, size); free(value); return tok; } // Try parse string literal fzl_token_t *parse_string_literal(fzl_reader_t *reader) { size_t lpos = reader->position; size_t size = 0; if (reader->source[lpos] != '\'' && reader->source[lpos] != '"') return NULL; char open_symbol = reader->source[lpos]; char close_symbol = '\0'; do { lpos++; size++; if (reader->source[lpos] == open_symbol) close_symbol = open_symbol; } while (reader->source[lpos] != open_symbol && lpos < reader->size); size++; if (close_symbol != open_symbol) return NULL; if (size == 2) { fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->position, reader->position + 1, "", 0); reader->position += 2; return tok; } char *value = malloc(size - 2); memcpy(value, reader->source + reader->position + 1, size - 2); fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->position, lpos, value, size - 2); free(value); reader->position += size; return tok; } int fzl_read(fzl_reader_t *reader) { if (reader->position >= reader->size) return 0; do { size_t p = reader->position; fzl_token_t *token; char curr = reader->source[p]; if (curr == '\n' || curr == ' ' || curr == '\r') { reader->position++; continue; } if (curr == '\'' || curr == '"') token = parse_string_literal(reader); else if (curr == '(') { token = fzl_mktoken(FZL_TOKTYPE_LPAIR, p, p, NULL, 0); reader->position++; } else if (curr == ')') { token = fzl_mktoken(FZL_TOKTYPE_RPAIR, p, p, NULL, 0); reader->position++; } else if (curr >= 'A' && curr <= 'Z' || curr >= 'a' && curr <= 'z') token = parse_name(reader); else { sprintf(last_err, "undefined token '%c'", curr); return -1; } if (!token) { size_t line = 1, linepos = 1; for (size_t i = 0; i < p; i++) { char sym = reader->source[i]; if (sym == '\n') { linepos = 1; line++; } else linepos++; } sprintf(last_err, "cannot parse token (%ld:%ld)", line, linepos); return -1; } fzl_reader_ll_t *tok_node = malloc(sizeof(fzl_reader_ll_t)); tok_node->token = token; reader->last->next = tok_node; reader->last = tok_node; } while (reader->position < reader->size); reader->at_end = true; return 0; } // --- Read zone end --- char *fzl_reader_geterror() { return last_err; } void free_node_and_next(fzl_reader_ll_t *node) { if (!node) return; if (node->next) free_node_and_next(node->next); if (node->token) fzl_freetoken(node->token); free(node); } void fzl_freereader(fzl_reader_t *reader) { if (!reader) return; if (reader->first) free_node_and_next(reader->first); free(reader); }