42sh/src/parser/grammar.c

126 lines
2.7 KiB
C
Raw Normal View History

// === Includes
#include "grammar.h"
#include <stdio.h>
#include <stdlib.h>
#include "grammar_basic.h"
// === Static variables
// rule-indexed array containing firsts
static struct firsts_list *firsts_map = NULL;
// === Static functions
/* @brief get the first accepted tokens of a rule
*
* @arg r the rule
* @return the accepted tokens as a firsts_list struct
*/
static struct firsts_list *first(enum rule r)
{
if (firsts_map == NULL || firsts_map[r].tokens == NULL)
{
puts("Internal error: attempted to get the firsts of a rule without "
"properly initializing the firsts map");
return NULL;
}
return &firsts_map[r];
}
/* @brief Add a token to a rule's firsts (in firsts_map)
*
* @arg rule the rule to which add a first
* @arg token the token to add to the rule's firsts
* @return true on success, false on error
*/
static bool add_first(enum rule rule, struct token token)
{
struct firsts_list *item = &firsts_map[rule];
if (item->tokens != NULL)
{
// Check for duplicates
for (size_t i = 0; i < item->list_length; i++)
{
if (item->tokens[i].type == token.type)
return true;
}
// Append
item->list_length++;
item->tokens = realloc(
item->tokens, (item->list_length) * sizeof(struct firsts_list));
}
else
{
// Create entry
item->tokens =
calloc(item->list_length + 1, sizeof(struct firsts_list));
}
// Check for alloc error
if (item->tokens == NULL)
{
item->list_length = 0;
return false;
}
// Fill
item->list_length++;
item->tokens[item->list_length - 1] = token;
return true;
}
/* @brief initializes the firsts_map static variable (does not populate it)
* @return true on success, false on error
*/
static bool init_firsts_map(void)
{
firsts_map = calloc(NUMBER_OF_RULES, sizeof(struct firsts_list));
if (firsts_map == NULL)
{
puts("Internal error: couldn't create the firsts_map (is your memory "
"full ?)");
return false;
}
return true;
}
// === Functions
bool grammar_init(void)
{
// Initialize the firsts map
bool success = init_firsts_map();
if (success != true)
return false;
// Populate the firsts map
// TODO
return true;
}
void grammar_close(void)
{
// Deep free firsts map
for (int i = 0; i < NUMBER_OF_RULES; i++)
{
if (firsts_map[i].tokens != NULL)
{
free(firsts_map[i].tokens);
}
}
free(firsts_map);
firsts_map = NULL;
}
struct ast *parse_input(struct lexer_context *ctx)
{
return parse_list(ctx);
}