summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--expression.c110
-rw-r--r--expression.h42
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