From 11f8fd4418a068c76fc7c810967a6bf285ee74b6 Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 27 Oct 2025 09:06:05 -0500 Subject: add expression scaffold --- expression.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ expression.h | 42 +++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 expression.c create mode 100644 expression.h diff --git a/expression.c b/expression.c new file mode 100644 index 0000000..11904fc --- /dev/null +++ b/expression.c @@ -0,0 +1,110 @@ +#include +#include +#include "expression.h" + + +struct li_production_t * li_production_alloc(size_t seq_len) { + struct li_production_t *prod = malloc(sizeof(struct li_production_t)); + if (prod == NULL) { + fprintf(stderr, "failed to allocate production rule\n"); + return NULL; + } + prod->seq = malloc(seq_len * sizeof(int)); + if (prod->seq == NULL) { + fprintf(stderr, "failed to allocate production sequence buffer\n"); + free(prod); + return NULL; + } + prod->seq_len = seq_len; + prod->next = NULL; + return prod; +} + + +void li_production_free(struct li_production_t *prod) { + if (prod != NULL) { + li_production_free(prod->next); + free(prod->seq); + free(prod); + } +} + + +struct li_production_rule_t * li_prod_rule_alloc() { + struct li_production_rule_t *rule = malloc(sizeof(struct li_production_rule_t)); + if (rule == NULL) { + fprintf(stderr, "failed to allocate production rule\n"); + return NULL; +} + rule->num_productions = 0; + rule->head = NULL; + return rule; +} + + +void li_prod_rule_free(struct li_production_rule_t *rule) { + if (rule != NULL) { + li_production_free(rule->head); + free(rule); + } +} + + +int li_prod_rule_add( + struct li_production_rule_t *rule, size_t seq_len, int *seq +) { + struct li_production_t *prod = li_production_alloc(seq_len); + if (prod == NULL) { + return 1; + } + memcpy(prod->seq, seq, seq_len*sizeof(int)); + prod->next = rule->head; + rule->head = prod; + rule->num_productions += 1; + return 0; +} + + +li_grammar_t * li_grammar_alloc(size_t num_nonterminal) { + li_grammar_t *grammar = malloc(sizeof(li_grammar_t)); + if (grammar == NULL) { + fprintf(stderr, "failed to allocate grammar\n"); + return NULL; + } + grammar->rules = malloc(num_nonterminal * sizeof(struct li_production_rule_t)); + if (grammar->rules == NULL) { + fprintf(stderr, "failed to allocate grammar rules buffer\n"); + free(grammar); + return NULL; + } + for (size_t i=0; irules[i].num_productions = 0; + grammar->rules[i].head = NULL; + } + grammar->num_nonterminal = NULL; + return grammar; +} + + +void li_grammar_free(li_grammar_t *grammar) { + if (grammar != NULL) { + for (size_t i=0; inum_nonterminal; i++) { + li_production_free(grammar->rules[i].head); + } + free(grammar->rules); + free(grammar); + } +} + + +int li_grammar_rule_add( + li_grammar_t *grammar, int nonterminal, size_t seq_len, int *seq +) { + if (nonterminal < 0 || nonterminal >= grammar->num_nonterminal) { + return 2; + } + return li_prod_rule_add(grammar->rules + nonterminal, seq_len, seq); +} + + + diff --git a/expression.h b/expression.h new file mode 100644 index 0000000..36a0e02 --- /dev/null +++ b/expression.h @@ -0,0 +1,42 @@ +#ifndef LICHEN_EXPRESSION_H +#define LICHEN_EXPRESSION_H + +/**************************************************************** + * + * a grammar is built on both nonterminals and terminals. both are + * represented by integers; nonterminals must be less than MAX_NONTERMINAL + * and terminals must be greater. the intended way to do this is to define + * an enum with all symbols, and have a MAX_NONTERMINAL symbol dividing the + * (low) nonterminals from the (high) terminals. + * + **************************************************************** + */ + +struct li_production_t { + int *seq; + size_t seq_len; + struct li_production_t *next; +}; + +struct li_production_t * li_production_alloc(size_t seq_len); +void li_production_free(struct li_production_t *prod); + +struct li_production_rule_t { + size_t num_productions; + struct li_production_t *head; +}; + +struct li_production_rule_t * li_prod_rule_alloc(); +void li_prod_rule_free(struct li_production_rule_t *rule); +int li_prod_rule_add(struct li_production_rule_t *rule, size_t seq_len, int *seq); + +typedef struct li_grammar_t { + struct li_production_rule_t *rules; + size_t num_nonterminal; +} li_grammar_t; + +li_rammar_t * li_grammar_alloc(size_t num_nonterminal); +void li_grammar_free(li_grammar_t *grammar); +int li_grammar_rule_add(li_grammar_t *grammar, int nonterminal, size_t seq_len, int *seq); + +#endif -- cgit v1.2.1