summaryrefslogtreecommitdiff
path: root/src/grammar.c
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-11-09 20:03:23 +0800
committerJSDurand <mmemmew@gmail.com>2021-11-09 20:03:23 +0800
commit53b8b6ffab5a968db75e9babddf4e2dbb2c688a3 (patch)
tree4ff55ae0027544b06702d24ec4840a2011f724e9 /src/grammar.c
parent87b6bad500702b0fcd708ee5b1d99f61a29ec7e6 (diff)
save point: representation of grammar might be too rough.
The current representation of the grammar is the most primitive BNF. This is the simplest to implement, but is difficult to cope with user requirements. Moreover, I find another paper describing the GLR algorithm, so I need to think about the representation of the grammar more. In particular, I would like the generation of the grammar to be incremental, so per chance its data type should be adapted accordingly.
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);
+}