#include #include #include #include #include #include #include #include #include // Last error from reader char last_err[256]; fzl_reader_t *fzl_mkreader(fzl_linked_t *linked) { 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->linked = linked; reader->source = linked->source; reader->size = linked->total_sz; reader->position = 0; memset(last_err, 0, sizeof(last_err)); return reader; } int fzl_read(fzl_reader_t *reader) { if (reader->position >= reader->size) return 0; bool is_format_str = false; do { size_t p = reader->position; fzl_token_t *token; char curr = reader->source[p]; if (is_format_str) { token = rd_fmtstr(reader); if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END) is_format_str = false; } else if (curr == '\n' || curr == ' ' || curr == '\r') { move(reader, 1); continue; } else if (curr == '\'' || curr == '"') token = rd_string_literal(reader); else if (curr == '/' && reader->source[p + 1] == '/') { rd_comment(reader); continue; } else if (curr == '=' && reader->source[p + 1] == '=') token = rd_double(reader, FZL_TOKTYPE_EQEQ); else if (curr == '>' && reader->source[p + 1] == '=') token = rd_double(reader, FZL_TOKTYPE_REQ); else if (curr == '<' && reader->source[p + 1] == '=') token = rd_double(reader, FZL_TOKTYPE_LEQ); else if (curr == '!' && reader->source[p + 1] == '=') token = rd_double(reader, FZL_TOKTYPE_NEQ); else if (curr == '|' && reader->source[p + 1] == '|') token = rd_double(reader, FZL_TOKTYPE_DVBAR); else if (curr == '&' && reader->source[p + 1] == '&') token = rd_double(reader, FZL_TOKTYPE_DAMPERSAND); else if (curr == '>') token = rd_single(reader, FZL_TOKTYPE_RANGLE); else if (curr == '<') token = rd_single(reader, FZL_TOKTYPE_LANGLE); else if (curr == '!') token = rd_single(reader, FZL_TOKTYPE_NOT); else if (curr == ';') token = rd_single(reader, FZL_TOKTYPE_SEMICOLON); else if (curr == '{') token = rd_single(reader, FZL_TOKTYPE_LBRACE); else if (curr == '}') token = rd_single(reader, FZL_TOKTYPE_RBRACE); else if (curr == '(') token = rd_single(reader, FZL_TOKTYPE_LPAREN); else if (curr == ')') token = rd_single(reader, FZL_TOKTYPE_RPAREN); else if (curr == ',') token = rd_single(reader, FZL_TOKTYPE_COMMA); else if (curr == '.') token = rd_single(reader, FZL_TOKTYPE_DOT); else if (curr == '*') token = rd_single(reader, FZL_TOKTYPE_STAR); else if (curr == '/') token = rd_single(reader, FZL_TOKTYPE_SLASH); else if (curr == '+') token = rd_single(reader, FZL_TOKTYPE_PLUS); else if (curr == '-') token = rd_single(reader, FZL_TOKTYPE_MINUS); else if (curr == '^') token = rd_single(reader, FZL_TOKTYPE_CARET); else if (curr == '%') token = rd_single(reader, FZL_TOKTYPE_PERCENT); else if (curr == '=') token = rd_single(reader, FZL_TOKTYPE_EQ); else if (curr == '$' && reader->source[p + 1] == '"') { move(reader, 2); is_format_str = true; token = fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_START, 0, 0, NULL, 0, ""); } else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') || curr == '_') token = rd_name(reader); else if (curr >= '0' && curr <= '9') token = rd_number(reader); else { fzl_file_loc l; bool ok = fzl_linked_getpos(reader->linked, p, &l); if (!ok) { snprintf(last_err, sizeof(last_err), "failed to locate line:col"); return -1; } sprintf(last_err, "'%s': undefined token '%c' at %ld:%ld", l.filename, curr, l.line, l.col); return -1; } if (!token) { if (!last_err[0]) { fzl_file_loc l; bool ok = fzl_linked_getpos(reader->linked, p, &l); if (!ok) { snprintf(last_err, sizeof(last_err), "failed to locate line:col"); return -1; } sprintf(last_err, "'%s': cannot parse token at %ld:%ld", l.filename, l.line, l.col); } return -1; } fzl_reader_ll_t *tok_node = malloc(sizeof(fzl_reader_ll_t)); tok_node->next = NULL; tok_node->token = token; reader->last->next = tok_node; reader->last = tok_node; } while (reader->position < reader->size); return 0; } 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); }