#include #include #include #include #include #include "lexer.h" #include "misc.h" #include "preprocessor.h" stmt *lex_stmt(source *src, int dbg); char *skip_seperators(source *src, whitespace *wspace, int preserve_src, int dbg) { char *text = NULL; char *tmp = src->text; src->text = max(src->text, text); src->text = skip_whitespace(src, wspace, 1, 1, dbg); src->text = skip_comment(src, wspace, NULL, dbg); text = src->text; if (preserve_src) { src->text = tmp; } return text; } cond_stmt *lex_cond_stmt(source *src, int dbg) { const keyword *cond_keywords[] = { &(const keyword) {"do", COND_DO, NULL}, &(const keyword) {"for", COND_FOR, NULL}, &(const keyword) {"if", COND_IF, NULL}, &(const keyword) {"while", COND_WHILE, NULL}, }; char *text = src->text; char *key = NULL; size_t key_len = 0; cond_type type = COND_NONE; whitespace wsp = {0}; text = skip_seperators(src, &wsp, 1, dbg); key_len = strcspn(text, " \t\v\b"); key = calloc(key_len+1, sizeof(char)); memcpy(key, text, key_len); type = find_keyword(key, (keyword **)cond_keywords, NULL, NULL, dbg); free(key); text += key_len+1; if (type >= COND_NONE) { cond_stmt *cond = calloc(1, sizeof(cond_stmt)); cond->type = type; src->text = text; src->cur.column += key_len+1; if (type != COND_DO) { cond->expr = lex_expr(src, dbg); } cond->stmt = lex_stmt(src, dbg); if (type == COND_DO) { text = skip_seperators(src, &wsp, 1, dbg); key_len = strcspn(text, " \t\v\b"); key = calloc(key_len+1, sizeof(char)); memcpy(key, text, key_len); if (!strcmp(key, "while")) { text += key_len+1; src->text = text; src->cur.column += key_len+1; cond->expr = lex_expr(src, dbg); text = skip_seperators(src, &wsp, 1, dbg); if (*text++ != ';') { --text; throw_error(src, 1, "Missing \';\' after do while statement."); } else { src->text = text; ++src->cur.column; } } else { throw_error(src, 1, "Missing \'while\' after do while statement."); } free(key); } return cond; } } stmt *lex_comp_stmt(source *src, int dbg) { char *text = NULL; whitespace wsp = {0}; text = skip_seperators(src, &wsp, 0, dbg); if (*text++ == '{') { stmt *s; src->text = text; ++src->cur.column; for (s = lex_stmt(src, dbg); *src->text != '}' && *src->text != '\0'; s = s->next) { s->wsp = wsp; s->next = lex_stmt(src, dbg); text = skip_seperators(src, &wsp, 1, dbg); } text = src->text; if (*text++ == '}') { ++src->cur.column; } else { --text; throw_error(src, 1, "Missing terminating \'}\' in compound statement."); } src->text = text; return s; } return NULL; } stmt *lex_stmt(source *src, int dbg) { char *text = src->text; const alt_stmt alts[] = { {STMT_FUNC, offsetof(stmt, func), (lex_func *)lex_func}, {STMT_EXPR, offsetof(stmt, expr), (lex_func *)lex_exprs}, {STMT_COND, offsetof(stmt, cond_stmt), (lex_func *)lex_cond_stmt}, {STMT_COMP, offsetof(stmt, down), (lex_func *)lex_comp_stmt}, }; for (int i = 0; i < NUM_STMTS; ++i) { src->text = text; void *data = alts[i].lex(src, dbg); if (data != NULL) { stmt *s = calloc(1, sizeof(stmt)); char *stmt = (char *)s; *(void **)(stmt+alts[i].offset) = data; return s; } } src->text = text; return NULL; } void lex_library(source *src, int dbg) { src->root = lex_stmt(src, dbg); src->last = (src->last != NULL) ? src->last : src->root; for (stmt *s = src->root; s != NULL; s = lex_stmt(src, dbg)) { src->last->next = s; src->last = s; } }; int lex(source *src, int dbg) { char *text = src->text; lex_library(src, dbg); src->text = text; return (src->root != NULL && src->last != NULL); }