120 lines
3.1 KiB
C
120 lines
3.1 KiB
C
#include <compiler/fzl_analyzer.h>
|
|
#include <compiler/fzl_parser.h>
|
|
#include <compiler/fzl_token.h>
|
|
#include <compiler/internals/analyzer.h>
|
|
#include <compiler/utils/fzl_symtable.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
char aerrors[256][256];
|
|
size_t aerrors_top;
|
|
|
|
char awarnings[256][256];
|
|
size_t awarnings_top;
|
|
|
|
char an_problem[256];
|
|
|
|
fzl_analyzer_t *fzl_mkanalyzer(fzl_node_t *node)
|
|
{
|
|
if (!node)
|
|
return NULL;
|
|
|
|
fzl_analyzer_t *analyzer = malloc(sizeof(fzl_analyzer_t));
|
|
if (!analyzer)
|
|
return NULL;
|
|
|
|
analyzer->root = node;
|
|
analyzer->warnings_top = 0;
|
|
analyzer->errors_top = 0;
|
|
analyzer->symbols_top = 0;
|
|
analyzer->alloc_names_top = 0;
|
|
|
|
memset(analyzer->errors, 0, sizeof(analyzer->errors));
|
|
memset(analyzer->warnings, 0, sizeof(analyzer->warnings));
|
|
memset(analyzer->symbols, 0, sizeof(analyzer->symbols));
|
|
memset(analyzer->alloc_names, 0, sizeof(analyzer->alloc_names));
|
|
|
|
memset(aerrors, 0, sizeof(aerrors));
|
|
memset(awarnings, 0, sizeof(awarnings));
|
|
|
|
return analyzer;
|
|
}
|
|
|
|
bool an_push_error(fzl_analyzer_t *analyzer, fzl_token_t *tok, char *error)
|
|
{
|
|
if (analyzer->errors_top >= 256 || !analyzer || !error)
|
|
return false;
|
|
|
|
size_t ei = aerrors_top++;
|
|
if (tok != NULL)
|
|
snprintf(aerrors[ei], sizeof(aerrors[ei]), "'%s':%zu:%zu => %s",
|
|
tok->filename, tok->ln, tok->cn, error);
|
|
else
|
|
snprintf(aerrors[ei], sizeof(aerrors[ei]), "<unknown location> => %s",
|
|
error);
|
|
|
|
analyzer->errors[analyzer->errors_top++] = aerrors[ei];
|
|
return true;
|
|
}
|
|
|
|
bool an_push_warning(fzl_analyzer_t *analyzer, fzl_token_t *tok, char *warning)
|
|
{
|
|
if (analyzer->warnings_top >= 256 || !analyzer || !warning)
|
|
return false;
|
|
|
|
size_t wi = awarnings_top++;
|
|
if (tok != NULL)
|
|
snprintf(awarnings[wi], sizeof(awarnings[wi]), "'%s':%zu:%zu => %s",
|
|
tok->filename, tok->ln, tok->cn, warning);
|
|
else
|
|
snprintf(awarnings[wi], sizeof(awarnings[wi]), "<unknown location> => %s",
|
|
warning);
|
|
|
|
analyzer->warnings[analyzer->warnings_top++] = awarnings[wi];
|
|
return true;
|
|
}
|
|
|
|
void fzl_analyze(fzl_analyzer_t *analyzer)
|
|
{
|
|
if (!analyzer)
|
|
return;
|
|
|
|
if (an_nest_ctx(analyzer, FZL_AN_CTX_TYPE_UNNECESSARY) == NULL)
|
|
{
|
|
an_push_error(analyzer, NULL, "failed to make global context");
|
|
return;
|
|
}
|
|
|
|
fzl_node_t *current = analyzer->root;
|
|
while (current != NULL)
|
|
{
|
|
fzl_an_res_t res = analyze_common(analyzer, current);
|
|
if (res.error)
|
|
break;
|
|
|
|
current = current->next;
|
|
}
|
|
|
|
for (ssize_t i = analyzer->symbols_top; i > 0; i--)
|
|
an_fin_ctx(analyzer);
|
|
}
|
|
|
|
void fzl_freeanalyzer(fzl_analyzer_t *analyzer)
|
|
{
|
|
if (!analyzer)
|
|
return;
|
|
|
|
if (analyzer->alloc_names_top > 0)
|
|
for (ssize_t i = analyzer->alloc_names_top - 1; i >= 0; i--)
|
|
free(analyzer->alloc_names[i]);
|
|
|
|
memset(analyzer->errors, 0, sizeof(analyzer->errors));
|
|
memset(analyzer->warnings, 0, sizeof(analyzer->warnings));
|
|
memset(analyzer->symbols, 0, sizeof(analyzer->symbols));
|
|
memset(analyzer->alloc_names, 0, sizeof(analyzer->alloc_names));
|
|
free(analyzer);
|
|
}
|