#include "compiler/fzl_token.h" #include #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->line_n = 1; reader->line_start = 0; return reader; } // --- Read zone --- // Move cursor forward static size_t move(fzl_reader_t *reader, size_t len) { if (!reader) return 0; char *src = reader->source; for (size_t i = 0; i < len; i++) { if (src[reader->position + i] == '\n') { reader->line_n++; reader->line_start = reader->position + i + 1; } } return reader->position += len; } // 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') || (reader->source[lpos] >= '0' && reader->source[lpos] <= '9') || (reader->source[lpos] == '_')); char *value = malloc(size + 1); memcpy(value, reader->source + reader->position, size); value[size] = '\0'; size_t start = reader->position; move(reader, size); fzl_token_t *tok; size_t line = reader->line_n; size_t pos = start - reader->line_start; if (strcmp(value, "if") == 0) tok = fzl_mktoken(FZL_TOKTYPE_IF, line, pos, value, size); else if (strcmp(value, "else") == 0) tok = fzl_mktoken(FZL_TOKTYPE_ELSE, line, pos, value, size); else if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) tok = fzl_mktoken(FZL_TOKTYPE_BOOL_LITERAL, line, pos, value, size); else if (strcmp(value, "str") == 0 || strcmp(value, "char") == 0 || strcmp(value, "bool") == 0 || strcmp(value, "uint") == 0 || strcmp(value, "int") == 0 || strcmp(value, "i8") == 0 || strcmp(value, "i16") == 0 || strcmp(value, "i32") == 0 || strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 || strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 || strcmp(value, "u64") == 0) tok = fzl_mktoken(FZL_TOKTYPE_TYPE, line, pos, value, size); else tok = fzl_mktoken(FZL_TOKTYPE_NAME, line, pos, 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) { snprintf(last_err, sizeof(last_err), "unterminated string at %ld:%ld", reader->line_n, reader->position - reader->line_start); return NULL; } if (size == 2) { fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, reader->line_n, reader->position - reader->line_start, "", 0); move(reader, 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->line_n, lpos - reader->line_start, value, size - 2); free(value); move(reader, size); return tok; } // Parse numeric literal fzl_token_t *parse_number(fzl_reader_t *reader) { if (!reader) return NULL; size_t size = 0; size_t lpos = reader->position; do { size++; lpos++; } while ((reader->source[lpos] >= '0' && reader->source[lpos] <= '9') && lpos < reader->size); char *value = malloc(size * sizeof(char) + 1); memcpy(value, reader->source + reader->position, size); value[size] = '\0'; fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NUM_LITERAL, reader->line_n, lpos - reader->line_start, value, size); free(value); if (!tok) return NULL; move(reader, size); return tok; } // Add single-char token fzl_token_t *add_single(fzl_reader_t *reader, fzl_toktype_t type) { size_t p = move(reader, 1); return fzl_mktoken(type, reader->line_n, p - reader->line_start, NULL, 0); } // Add double-char token fzl_token_t *add_double(fzl_reader_t *reader, fzl_toktype_t type) { size_t p = move(reader, 2); return fzl_mktoken(type, reader->line_n, p - reader->line_start, NULL, 0); } 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') { move(reader, 1); continue; } if (curr == '\'' || curr == '"') token = parse_string_literal(reader); else if (curr == '=' && reader->source[p + 1] == '=') token = add_double(reader, FZL_TOKTYPE_EQEQ); else if (curr == '>' && reader->source[p + 1] == '=') token = add_double(reader, FZL_TOKTYPE_REQ); else if (curr == '<' && reader->source[p + 1] == '=') token = add_double(reader, FZL_TOKTYPE_LEQ); else if (curr == '!' && reader->source[p + 1] == '=') token = add_double(reader, FZL_TOKTYPE_NEQ); else if (curr == '|' && reader->source[p + 1] == '|') token = add_double(reader, FZL_TOKTYPE_DVBAR); else if (curr == '&' && reader->source[p + 1] == '&') token = add_double(reader, FZL_TOKTYPE_DAMPERSAND); else if (curr == '>') token = add_single(reader, FZL_TOKTYPE_RANGLE); else if (curr == '<') token = add_single(reader, FZL_TOKTYPE_LANGLE); else if (curr == '!') token = add_single(reader, FZL_TOKTYPE_NOT); else if (curr == ';') token = add_single(reader, FZL_TOKTYPE_SEMICOLON); else if (curr == '{') token = add_single(reader, FZL_TOKTYPE_LBRACE); else if (curr == '}') token = add_single(reader, FZL_TOKTYPE_RBRACE); else if (curr == '(') token = add_single(reader, FZL_TOKTYPE_LPAREN); else if (curr == ')') token = add_single(reader, FZL_TOKTYPE_RPAREN); else if (curr == ',') token = add_single(reader, FZL_TOKTYPE_COMMA); else if (curr == '*') token = add_single(reader, FZL_TOKTYPE_STAR); else if (curr == '/') token = add_single(reader, FZL_TOKTYPE_SLASH); else if (curr == '+') token = add_single(reader, FZL_TOKTYPE_PLUS); else if (curr == '-') token = add_single(reader, FZL_TOKTYPE_MINUS); else if (curr == '^') token = add_single(reader, FZL_TOKTYPE_CARET); else if (curr == '%') token = add_single(reader, FZL_TOKTYPE_PERCENT); else if (curr == '=') token = add_single(reader, FZL_TOKTYPE_EQ); else if (curr >= 'A' && curr <= 'Z' || curr >= 'a' && curr <= 'z' || curr == '_') token = parse_name(reader); else if (curr >= '0' && curr <= '9') token = parse_number(reader); else { sprintf(last_err, "undefined token '%c' at %ld:%ld", curr, reader->line_n, p - reader->line_start); return -1; } if (!token) { if (!last_err[0]) sprintf(last_err, "cannot parse token at %ld:%ld", reader->line_n, p - reader->line_start); 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); 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); }