summaryrefslogtreecommitdiff
path: root/src/grammar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar.c')
-rw-r--r--src/grammar.c118
1 files changed, 101 insertions, 17 deletions
diff --git a/src/grammar.c b/src/grammar.c
index 9265ef5..fd38ac8 100644
--- a/src/grammar.c
+++ b/src/grammar.c
@@ -10,7 +10,14 @@ struct Rule_s {
List *right;
};
-TNT *new_tnt(int type, ...)
+struct Grammar_s {
+ List *rules;
+ /* a list of names of non-terminals */
+ List *names;
+};
+
+TNT *
+new_tnt(int type, ...)
{
va_list args;
va_start(args, type);
@@ -26,10 +33,11 @@ TNT *new_tnt(int type, ...)
return result;
}
-Rule *new_rule(NT left, List *right)
+Rule *
+new_rule(NT left, List *right)
{
if (!right) return NULL;
-
+
Rule *rule = MYALLOC(Rule, 1);
rule->left = left;
@@ -38,7 +46,22 @@ Rule *new_rule(NT left, List *right)
return rule;
}
-void print_tnt(void *element)
+Grammar *
+new_grammar()
+{
+ Grammar *g = MYALLOC(Grammar, 1);
+ return g;
+}
+
+void
+build_grammar(Grammar *g, List *rules, List *names)
+{
+ g->rules = rules;
+ g->names = names;
+}
+
+void
+print_tnt(void *element)
{
TNT *tnt = (TNT*) element;
@@ -48,35 +71,55 @@ void print_tnt(void *element)
printf("T %lu, ", tnt->data.t);
}
-void print_rule(void *r)
+void
+print_rule(void *r)
{
- Rule *rule = (Rule *)r;
- printf("Rule: NT %u => ", rule->left);
-
+ Rule *rule = (Rule *) r;
+ printf("Rule: %u => ", rule->left);
+
map_list(rule->right, print_tnt);
printf("\n");
}
-void print_grammar(Grammar g)
+/* a local function pointer */
+void
+print_name(void *element)
+{
+ char *str = (char *) element;
+ printf("%s", str);
+}
+
+/* a local function pointer */
+void
+print_sep()
+{
+ printf(", ");
+}
+
+void
+print_grammar(Grammar *g)
{
printf("Printing a grammar:\n");
- map_list(g, print_rule);
+ map_list_between(g->names, print_name, print_sep);
+ printf("\n");
+ map_list(g->rules, print_rule);
printf("\n");
}
-List *new_tnt_string(char *format, int format_len, ...)
+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':
@@ -99,8 +142,49 @@ List *new_tnt_string(char *format, int format_len, ...)
return result;
}
-void destroy_rule(Rule *rule)
+void
+destroy_rule(void *rule, int flag)
{
- destroy_list(rule->right, 1);
+ Rule * r = (Rule *) rule;
+ destroy_list(r->right, flag);
free(rule);
}
+
+void
+destroy_rule_and_free_all(void *rule)
+{
+ destroy_rule(rule, 1);
+}
+
+void
+destroy_rule_and_free_first(void *rule)
+{
+ destroy_rule(rule, 2);
+}
+
+void
+destroy_rule_no_free(void *rule)
+{
+ destroy_rule(rule, 0);
+}
+
+void
+destroy_grammar(void *grammar, int flag)
+{
+ Grammar *g = (Grammar *) grammar;
+
+ switch (flag) {
+ case 0:
+ map_list(g->rules, destroy_rule_no_free);
+ break;
+ case 1:
+ map_list(g->rules, destroy_rule_and_free_all);
+ break;
+ default:
+ map_list(g->rules, destroy_rule_and_free_first);
+ break;
+ }
+
+ destroy_list(g->rules, 0);
+ destroy_list(g->names, flag);
+}