feat: made the firsts system for parser (not yet populated)
This commit is contained in:
parent
32e182bd50
commit
da1a73c264
3 changed files with 129 additions and 22 deletions
|
|
@ -1,30 +1,105 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
|
|
||||||
// === Includes
|
// === Includes
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
|
|
||||||
#include "../utils/hash_map/hash_map.h"
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "grammar_basic.h"
|
#include "grammar_basic.h"
|
||||||
|
|
||||||
// === Static variables
|
// === Static variables
|
||||||
|
|
||||||
static struct hash_map *firsts_map = NULL;
|
// rule-indexed array containing firsts
|
||||||
|
static struct firsts_list *firsts_map = NULL;
|
||||||
|
|
||||||
// === Static functions
|
// === Static functions
|
||||||
static enum token_type first(enum rule r)
|
|
||||||
|
/* @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)
|
||||||
{
|
{
|
||||||
// TODO
|
if (firsts_map == NULL || firsts_map[r].tokens == NULL)
|
||||||
return TOKEN_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
|
// === Functions
|
||||||
|
|
||||||
bool grammar_init(void)
|
bool grammar_init(void)
|
||||||
{
|
{
|
||||||
// Create firsts hashmap
|
// Initialize the firsts map
|
||||||
// TODO
|
bool success = init_firsts_map();
|
||||||
|
if (success != true)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Populate the hashmap
|
// Populate the firsts map
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -32,7 +107,16 @@ bool grammar_init(void)
|
||||||
|
|
||||||
void grammar_close(void)
|
void grammar_close(void)
|
||||||
{
|
{
|
||||||
// TODO free hashmap
|
// 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)
|
struct ast *parse_input(struct lexer_context *ctx)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
// === Structures
|
// === Structures
|
||||||
|
|
||||||
enum rule {
|
enum rule {
|
||||||
RULE_NULL,
|
RULE_NULL = 0,
|
||||||
RULE_INPUT,
|
RULE_INPUT,
|
||||||
RULE_LIST,
|
RULE_LIST,
|
||||||
RULE_AND_OR,
|
RULE_AND_OR,
|
||||||
|
|
@ -36,7 +36,13 @@ enum rule {
|
||||||
RULE_SHELL_COMMAND,
|
RULE_SHELL_COMMAND,
|
||||||
RULE_IF,
|
RULE_IF,
|
||||||
RULE_COMPOUND_LIST,
|
RULE_COMPOUND_LIST,
|
||||||
RULE_ELSE_CLAUSE
|
RULE_ELSE_CLAUSE,
|
||||||
|
NUMBER_OF_RULES
|
||||||
|
};
|
||||||
|
|
||||||
|
struct firsts_list {
|
||||||
|
struct token* tokens; // Heap allocated array
|
||||||
|
size_t list_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
// === Functions
|
// === Functions
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,24 @@
|
||||||
* ends by a newline
|
* ends by a newline
|
||||||
*
|
*
|
||||||
* @code list = and_or { ';' and_or } [ ';' ] ;
|
* @code list = and_or { ';' and_or } [ ';' ] ;
|
||||||
|
*
|
||||||
|
* @first first(and_or)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_list(struct lexer_context *ctx);
|
struct ast *parse_list(struct lexer_context *ctx);
|
||||||
|
|
||||||
/* @brief Only parses a pipeline rule for the moment
|
/* @brief Only parses a pipeline rule for the moment
|
||||||
*
|
*
|
||||||
* @code and_or = pipeline { ( '&&' | '||' ) {'\n'} pipeline } ;
|
* @code and_or = pipeline { ( '&&' | '||' ) {'\n'} pipeline } ;
|
||||||
|
*
|
||||||
|
* @first first(pipeline)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_and_or(struct lexer_context *ctx);
|
struct ast *parse_and_or(struct lexer_context *ctx);
|
||||||
|
|
||||||
/* @brief Only parses a command rule for the moment
|
/* @brief Only parses a command rule for the moment
|
||||||
*
|
*
|
||||||
* @code pipeline = command ;
|
* @code pipeline = command ;
|
||||||
|
*
|
||||||
|
* @first first(command)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_pipeline(struct lexer_context *ctx);
|
struct ast *parse_pipeline(struct lexer_context *ctx);
|
||||||
|
|
||||||
|
|
@ -34,6 +40,7 @@ struct ast *parse_pipeline(struct lexer_context *ctx);
|
||||||
* @code command = simple_command
|
* @code command = simple_command
|
||||||
* | shell_command
|
* | shell_command
|
||||||
* ;
|
* ;
|
||||||
|
* @first first(simple_command), first(shell_command)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_command(struct lexer_context *ctx);
|
struct ast *parse_command(struct lexer_context *ctx);
|
||||||
|
|
||||||
|
|
@ -41,18 +48,24 @@ struct ast *parse_command(struct lexer_context *ctx);
|
||||||
* ending by a separator
|
* ending by a separator
|
||||||
*
|
*
|
||||||
* @code simple_command = WORD { element } ;
|
* @code simple_command = WORD { element } ;
|
||||||
|
*
|
||||||
|
* @first WORD
|
||||||
*/
|
*/
|
||||||
struct ast *parse_simple_command(struct lexer_context *ctx);
|
struct ast *parse_simple_command(struct lexer_context *ctx);
|
||||||
|
|
||||||
/* @brief Only parses if rules for the moment
|
/* @brief Only parses if rules for the moment
|
||||||
*
|
*
|
||||||
* @code shell_command = if_rule ;
|
* @code shell_command = if_rule ;
|
||||||
|
*
|
||||||
|
* @first first(if_rule)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_shell_command(struct lexer_context *ctx);
|
struct ast *parse_shell_command(struct lexer_context *ctx);
|
||||||
|
|
||||||
/* @brief Parses a if rule (condition, then-clause, elif-clause, else-clause)
|
/* @brief Parses a if rule (condition, then-clause, elif-clause, else-clause)
|
||||||
*
|
*
|
||||||
* @code if_rule = 'if' compound_list 'then' compound_list [else_clause] 'fi' ;
|
* @code if_rule = 'if' compound_list 'then' compound_list [else_clause] 'fi' ;
|
||||||
|
*
|
||||||
|
* @first TOKEN_IF
|
||||||
*/
|
*/
|
||||||
struct ast *parse_if_rule(struct lexer_context *ctx);
|
struct ast *parse_if_rule(struct lexer_context *ctx);
|
||||||
|
|
||||||
|
|
@ -61,6 +74,8 @@ struct ast *parse_if_rule(struct lexer_context *ctx);
|
||||||
*
|
*
|
||||||
* @code compound_list = {'\n'} and_or { ( ';' | '\n' ) {'\n'} and_or } [';']
|
* @code compound_list = {'\n'} and_or { ( ';' | '\n' ) {'\n'} and_or } [';']
|
||||||
* {'\n'} ;
|
* {'\n'} ;
|
||||||
|
*
|
||||||
|
* @first TOKEN_NEWLINE, first(and_or)
|
||||||
*/
|
*/
|
||||||
struct ast *parse_compound_list(struct lexer_context *ctx);
|
struct ast *parse_compound_list(struct lexer_context *ctx);
|
||||||
|
|
||||||
|
|
@ -69,6 +84,8 @@ struct ast *parse_compound_list(struct lexer_context *ctx);
|
||||||
* @code else_clause = 'else' compound_list
|
* @code else_clause = 'else' compound_list
|
||||||
* | 'elif' compound_list 'then' compound_list [else_clause]
|
* | 'elif' compound_list 'then' compound_list [else_clause]
|
||||||
* ;
|
* ;
|
||||||
|
*
|
||||||
|
* @first TOKEN_ELSE, TOKEN_ELIF
|
||||||
*/
|
*/
|
||||||
struct ast *parse_else_clause(struct lexer_context *ctx);
|
struct ast *parse_else_clause(struct lexer_context *ctx);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue