summaryrefslogtreecommitdiff
path: root/src/grammar.c
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-11-08 16:37:57 +0800
committerJSDurand <mmemmew@gmail.com>2021-11-08 16:37:57 +0800
commit9594210f02572681ed581c5197ace4c207db0917 (patch)
tree08bf1bf079d111c64cf3128dd68323abdce78228 /src/grammar.c
initial commit
Now the rough framework is established and the grammar class is sort of ready. It remains to write a general input reading mechanism.
Diffstat (limited to 'src/grammar.c')
-rw-r--r--src/grammar.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/grammar.c b/src/grammar.c
new file mode 100644
index 0000000..9265ef5
--- /dev/null
+++ b/src/grammar.c
@@ -0,0 +1,106 @@
+#include "grammar.h"
+
+struct TNT_s {
+ int type; /* 0 => T and NT otherwise */
+ union { T t; NT nt; } data;
+};
+
+struct Rule_s {
+ NT left;
+ List *right;
+};
+
+TNT *new_tnt(int type, ...)
+{
+ va_list args;
+ va_start(args, type);
+
+ TNT *result = MYALLOC(TNT, 1);
+ result->type = type;
+
+ if (type) result->data.nt = va_arg(args, NT);
+ else result->data.t = va_arg(args, T);
+
+ va_end(args);
+
+ return result;
+}
+
+Rule *new_rule(NT left, List *right)
+{
+ if (!right) return NULL;
+
+ Rule *rule = MYALLOC(Rule, 1);
+
+ rule->left = left;
+ rule->right = right;
+
+ return rule;
+}
+
+void print_tnt(void *element)
+{
+ TNT *tnt = (TNT*) element;
+
+ if (tnt->type)
+ printf("NT %u, ", tnt->data.nt);
+ else
+ printf("T %lu, ", tnt->data.t);
+}
+
+void print_rule(void *r)
+{
+ Rule *rule = (Rule *)r;
+ printf("Rule: NT %u => ", rule->left);
+
+ map_list(rule->right, print_tnt);
+
+ printf("\n");
+}
+
+void print_grammar(Grammar g)
+{
+ printf("Printing a grammar:\n");
+ map_list(g, print_rule);
+ printf("\n");
+}
+
+List *new_tnt_string(char *format, int format_len, ...)
+{
+ /* FORMAT_LEN does not include the terminating null byte, so it
+ should be > 0. */
+
+ if (format_len <= 0) return NULL;
+
+ List *result = new_list();
+
+ va_list args;
+ va_start(args, format_len);
+
+ for (int point = 0; point < format_len; point++) {
+ switch (*(format+point)) {
+ case 'n':
+ add_to_list(result, new_tnt(1, va_arg(args, NT)));
+ break;
+ case 't':
+ add_to_list(result, new_tnt(0, va_arg(args, T)));
+ break;
+ default:
+ eprintf("Wront character: %c\n", *(format+point));
+ destroy_list(result, 1);
+ va_end(args);
+ return NULL;
+ break;
+ }
+ }
+
+ va_end(args);
+
+ return result;
+}
+
+void destroy_rule(Rule *rule)
+{
+ destroy_list(rule->right, 1);
+ free(rule);
+}