107 lines
2.4 KiB
C
107 lines
2.4 KiB
C
#include "tokenlist.h"
|
|
#include "error.h"
|
|
#include "lexer.h"
|
|
#include <stdlib.h>
|
|
|
|
error_t *tokenlist_alloc(tokenlist_t **output) {
|
|
*output = nullptr;
|
|
|
|
tokenlist_t *list = calloc(1, sizeof(tokenlist_t));
|
|
if (list == nullptr)
|
|
return err_allocation_failed;
|
|
|
|
list->head = nullptr;
|
|
list->tail = nullptr;
|
|
|
|
*output = list;
|
|
return nullptr;
|
|
}
|
|
|
|
error_t *tokenlist_entry_alloc(tokenlist_entry_t **output) {
|
|
*output = nullptr;
|
|
|
|
tokenlist_entry_t *entry = calloc(1, sizeof(tokenlist_entry_t));
|
|
if (entry == nullptr)
|
|
return err_allocation_failed;
|
|
|
|
entry->next = nullptr;
|
|
entry->prev = nullptr;
|
|
|
|
*output = entry;
|
|
return nullptr;
|
|
}
|
|
|
|
void tokenlist_append(tokenlist_t *list, tokenlist_entry_t *entry) {
|
|
if (list->head == nullptr) {
|
|
list->head = entry;
|
|
list->tail = entry;
|
|
entry->next = nullptr;
|
|
entry->prev = nullptr;
|
|
} else {
|
|
entry->prev = list->tail;
|
|
entry->next = nullptr;
|
|
list->tail->next = entry;
|
|
list->tail = entry;
|
|
}
|
|
}
|
|
|
|
void tokenlist_entry_free(tokenlist_entry_t *entry) {
|
|
lexer_token_cleanup(&entry->token);
|
|
free(entry);
|
|
}
|
|
|
|
void tokenlist_free(tokenlist_t *list) {
|
|
if (list == nullptr)
|
|
return;
|
|
|
|
tokenlist_entry_t *current = list->head;
|
|
while (current) {
|
|
tokenlist_entry_t *next = current->next;
|
|
tokenlist_entry_free(current);
|
|
current = next;
|
|
}
|
|
|
|
free(list);
|
|
}
|
|
|
|
error_t *tokenlist_fill(tokenlist_t *list, lexer_t *lex) {
|
|
error_t *err = nullptr;
|
|
lexer_token_t token = {};
|
|
while ((err = lexer_next(lex, &token)) == nullptr) {
|
|
tokenlist_entry_t *entry;
|
|
err = tokenlist_entry_alloc(&entry);
|
|
if (err) {
|
|
lexer_token_cleanup(&token);
|
|
return err;
|
|
}
|
|
entry->token = token;
|
|
tokenlist_append(list, entry);
|
|
}
|
|
if (err != err_eof)
|
|
return err;
|
|
return nullptr;
|
|
}
|
|
|
|
bool is_trivia(tokenlist_entry_t *trivia) {
|
|
switch (trivia->token.id) {
|
|
case TOKEN_WHITESPACE:
|
|
case TOKEN_COMMENT:
|
|
case TOKEN_NEWLINE:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
tokenlist_entry_t *tokenlist_skip_trivia(tokenlist_entry_t *current) {
|
|
while (current && is_trivia(current))
|
|
current = current->next;
|
|
return current;
|
|
}
|
|
|
|
tokenlist_entry_t *tokenlist_next(tokenlist_entry_t *current) {
|
|
if (!current)
|
|
return nullptr;
|
|
return tokenlist_skip_trivia(current->next);
|
|
}
|