diff options
| author | sanine <sanine.not@pm.me> | 2025-10-27 09:06:05 -0500 | 
|---|---|---|
| committer | sanine <sanine.not@pm.me> | 2025-10-27 09:06:05 -0500 | 
| commit | 11f8fd4418a068c76fc7c810967a6bf285ee74b6 (patch) | |
| tree | 91af900e76dc5352f3073d38602914c8ef69b950 | |
| parent | 54555ad0e37fe4dcba970f8ef6b7e496efcca44f (diff) | |
add expression scaffold
| -rw-r--r-- | expression.c | 110 | ||||
| -rw-r--r-- | expression.h | 42 | 
2 files changed, 152 insertions, 0 deletions
| 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 <stdlib.h> +#include <stdio.h> +#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; i<num_nonterminal; i++) { +    grammar->rules[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; i<grammar->num_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 | 
