2 * monoburg.c: an iburg like code generator generator
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
15 extern void yyparse (void);
17 static GHashTable *term_hash;
18 static GList *term_list;
19 static GHashTable *nonterm_hash;
20 static GList *nonterm_list;
21 static GList *rule_list;
28 static int dag_mode = 0;
29 static int predefined_terms = 0;
31 static void output (char *fmt, ...)
36 vfprintf (outputfd, fmt, ap);
41 create_rule (char *id, Tree *tree, char *code, char *cost, char *cfunc)
43 Rule *rule = g_new0 (Rule, 1);
48 rule->lhs = nonterm (id);
50 rule_list = g_list_append (rule_list, rule);
51 rule->cost = g_strdup (cost);
52 rule->cfunc = g_strdup (cfunc);
53 rule->code = g_strdup (code);
57 yyerror ("duplicated costs (constant costs and cost function)");
59 rule->cost = g_strdup_printf ("mono_burg_cost_%d (tree, data)",
60 g_list_length (rule_list));
63 rule->lhs->rules = g_list_append (rule->lhs->rules, rule);
66 tree->op->rules = g_list_append (tree->op->rules, rule);
68 tree->nonterm->chain = g_list_append (tree->nonterm->chain, rule);
72 create_tree (char *id, Tree *left, Tree *right)
74 int arity = (left != NULL) + (right != NULL);
75 Term *term = g_hash_table_lookup (term_hash, id);
76 Tree *tree = g_new0 (Tree, 1);
79 if (term->arity == -1)
82 if (term->arity != arity)
83 yyerror ("changed arity of terminal %s from %d to %d",
84 id, term->arity, arity);
90 tree->nonterm = nonterm (id);
97 check_term_num (char *key, Term *value, int num)
99 if (num != -1 && value->number == num)
100 yyerror ("duplicate terminal id \"%s\"", key);
104 create_term (char *id, int num)
109 yyerror ("terminal definition after nonterminal definition");
112 yyerror ("invalid terminal number %d", num);
115 term_hash = g_hash_table_new (g_str_hash , g_str_equal);
117 g_hash_table_foreach (term_hash, (GHFunc) check_term_num, (gpointer) num);
119 term = g_new0 (Term, 1);
121 term->name = g_strdup (id);
125 term_list = g_list_append (term_list, term);
127 g_hash_table_insert (term_hash, term->name, term);
136 nonterm_hash = g_hash_table_new (g_str_hash , g_str_equal);
138 if ((nterm = g_hash_table_lookup (nonterm_hash, id)))
141 nterm = g_new0 (NonTerm, 1);
143 nterm->name = g_strdup (id);
144 nonterm_list = g_list_append (nonterm_list, nterm);
145 nterm->number = g_list_length (nonterm_list);
147 g_hash_table_insert (nonterm_hash, nterm->name, nterm);
153 start_nonterm (char *id)
155 static gboolean start_def;
158 yyerror ("start symbol redeclared");
165 emit_tree_string (Tree *tree)
168 output ("%s", tree->op->name);
169 if (tree->op->arity) {
171 emit_tree_string (tree->left);
174 emit_tree_string (tree->right);
179 output ("%s", tree->nonterm->name);
183 emit_rule_string (Rule *rule, char *fill)
185 output ("%s/* ", fill);
187 output ("%s: ", rule->lhs->name);
189 emit_tree_string (rule->tree);
197 GList *l = term_list;
201 Term *t = (Term *)l->data;
202 if (t->number == i) {
212 term_compare_func (Term *t1, Term *t2)
214 return t1->number - t2->number;
222 output ("#include <glib.h>\n");
225 output ("#ifndef MBTREE_TYPE\n#error MBTREE_TYPE undefined\n#endif\n");
226 output ("#ifndef MBTREE_OP\n#define MBTREE_OP(t) ((t)->op)\n#endif\n");
227 output ("#ifndef MBTREE_LEFT\n#define MBTREE_LEFT(t) ((t)->left)\n#endif\n");
228 output ("#ifndef MBTREE_RIGHT\n#define MBTREE_RIGHT(t) ((t)->right)\n#endif\n");
229 output ("#ifndef MBTREE_STATE\n#define MBTREE_STATE(t) ((t)->state)\n#endif\n");
230 output ("#ifndef MBCGEN_TYPE\n#define MBCGEN_TYPE int\n#endif\n");
231 output ("#ifndef MBALLOC_STATE\n#define MBALLOC_STATE g_new (MBState, 1)\n#endif\n");
232 output ("#ifndef MBCOST_DATA\n#define MBCOST_DATA gpointer\n#endif\n");
234 output ("#define MBMAXCOST 32768\n");
237 output ("#define MBCOND(x) if (!(x)) return MBMAXCOST;\n");
241 for (l = term_list; l; l = l->next) {
242 Term *t = (Term *)l->data;
244 t->number = next_term_num ();
246 term_list = g_list_sort (term_list, (GCompareFunc)term_compare_func);
248 for (l = term_list; l; l = l->next) {
249 Term *t = (Term *)l->data;
251 t->number = next_term_num ();
253 if (predefined_terms)
254 output ("#define MB_TERM_%s\t %s\n", t->name, t->name);
256 output ("#define MB_TERM_%s\t %d\n", t->name, t->number);
268 for (l = nonterm_list; l; l = l->next) {
269 NonTerm *n = (NonTerm *)l->data;
270 output ("#define MB_NTERM_%s\t%d\n", n->name, n->number);
272 output ("#define MB_MAX_NTERMS\t%d\n", g_list_length (nonterm_list));
282 output ("typedef struct _MBState MBState;\n");
283 output ("struct _MBState {\n");
284 output ("\tint\t\t op;\n");
287 output ("\tMBTREE_TYPE\t *tree;\n");
288 output ("\tgint8 reg1, reg2, reg3;\n");
289 output ("\tunsigned spilled:1;\n");
292 output ("\tMBState\t\t*left, *right;\n");
293 output ("\tguint16\t\tcost[%d];\n", g_list_length (nonterm_list) + 1);
295 for (l = nonterm_list; l; l = l->next) {
296 NonTerm *n = (NonTerm *)l->data;
297 g_assert (g_list_length (n->rules) < 256);
298 i = g_list_length (n->rules);
302 output ("\tunsigned int\t rule_%s:%d;\n", n->name, j);
313 for (l = nonterm_list; l; l = l->next) {
314 NonTerm *n = (NonTerm *)l->data;
315 output ("const int mono_burg_decode_%s[] = {\n", n->name);
317 for (rl = n->rules; rl; rl = rl->next) {
318 Rule *rule = (Rule *)rl->data;
319 output ("\t%d,\n", g_list_index (rule_list, rule) + 1);
327 emit_tree_match (char *st, Tree *t)
331 if (predefined_terms)
332 output ("\t\t\t%sop == %s /* %s */", st, t->op->name, t->op->name);
334 output ("\t\t\t%sop == %d /* %s */", st, t->op->number, t->op->name);
336 if (t->left && t->left->op) {
337 tn = g_strconcat (st, "left->", NULL);
339 emit_tree_match (tn, t->left);
343 if (t->right && t->right->op) {
344 tn = g_strconcat (st, "right->", NULL);
346 emit_tree_match (tn, t->right);
352 emit_rule_match (Rule *rule)
354 Tree *t = rule->tree;
356 if ((t->left && t->left->op) ||
357 (t->right && t->right->op)) {
358 output ("\t\tif (\n");
359 emit_tree_match ("p->", t);
360 output ("\n\t\t)\n");
365 emit_costs (char *st, Tree *t)
372 tn = g_strconcat (st, "left->", NULL);
373 emit_costs (tn, t->left);
378 tn = g_strconcat (st, "right->", NULL);
379 emit_costs (tn, t->right);
382 output ("%scost[MB_NTERM_%s] + ", st, t->nonterm->name);
386 emit_cond_assign (Rule *rule, char *cost, char *fill)
391 rc = g_strconcat ("c + ", cost, NULL);
396 output ("%sif (%s < p->cost[MB_NTERM_%s]) {\n", fill, rc, rule->lhs->name);
398 output ("%s\tp->cost[MB_NTERM_%s] = %s;\n", fill, rule->lhs->name, rc);
400 output ("%s\tp->rule_%s = %d;\n", fill, rule->lhs->name,
401 g_list_index (rule->lhs->rules, rule) + 1);
403 if (rule->lhs->chain)
404 output ("%s\tclosure_%s (p, %s);\n", fill, rule->lhs->name, rc);
406 output ("%s}\n", fill);
419 output ("static void\n");
420 output ("mono_burg_label_priv (MBTREE_TYPE *tree, MBCOST_DATA *data, MBState *p) {\n");
422 output ("static MBState *\n");
423 output ("mono_burg_label_priv (MBTREE_TYPE *tree, MBCOST_DATA *data) {\n");
426 output ("\tint arity;\n");
427 output ("\tint c;\n");
429 output ("\tMBState *p;\n");
430 output ("\tMBState *left = NULL, *right = NULL;\n\n");
432 output ("\tswitch (mono_burg_arity [MBTREE_OP(tree)]) {\n");
433 output ("\tcase 0:\n");
434 output ("\t\tbreak;\n");
435 output ("\tcase 1:\n");
437 output ("\t\tleft = MBALLOC_STATE;\n");
438 output ("\t\tmono_burg_label_priv (MBTREE_LEFT(tree), data, left);\n");
440 output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
441 output ("\t\tright = NULL;\n");
443 output ("\t\tbreak;\n");
444 output ("\tcase 2:\n");
446 output ("\t\tleft = MBALLOC_STATE;\n");
447 output ("\t\tmono_burg_label_priv (MBTREE_LEFT(tree), data, left);\n");
448 output ("\t\tright = MBALLOC_STATE;\n");
449 output ("\t\tmono_burg_label_priv (MBTREE_RIGHT(tree), data, right);\n");
451 output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
452 output ("\t\tright = mono_burg_label_priv (MBTREE_RIGHT(tree), data);\n");
456 output ("\tarity = (left != NULL) + (right != NULL);\n");
457 output ("\tg_assert (arity == mono_burg_arity [MBTREE_OP(tree)]);\n\n");
460 output ("\tp = MBALLOC_STATE;\n");
462 output ("\tmemset (p, 0, sizeof (MBState));\n");
463 output ("\tp->op = MBTREE_OP(tree);\n");
464 output ("\tp->left = left;\n");
465 output ("\tp->right = right;\n");
468 output ("\tp->tree = tree;\n");
470 for (l = nonterm_list, i = 0; l; l = l->next) {
471 output ("\tp->cost [%d] = 32767;\n", ++i);
475 output ("\tswitch (MBTREE_OP(tree)) {\n");
476 for (l = term_list; l; l = l->next) {
477 Term *t = (Term *)l->data;
480 if (predefined_terms)
481 output ("\tcase %s: /* %s */\n", t->name, t->name);
483 output ("\tcase %d: /* %s */\n", t->number, t->name);
485 for (rl = t->rules; rl; rl = rl->next) {
486 Rule *rule = (Rule *)rl->data;
487 Tree *t = rule->tree;
489 emit_rule_string (rule, "\t\t");
491 emit_rule_match (rule);
495 output ("\t\t\tc = ");
499 output ("%s;\n", rule->cost);
501 emit_cond_assign (rule, NULL, "\t\t\t");
506 output ("\t\tbreak;\n");
509 output ("\tdefault:\n");
510 output ("\t\tg_error (\"unknown operator: 0x%%04x\", MBTREE_OP(tree));\n");
514 output ("\tMBTREE_STATE(tree) = p;\n");
515 output ("\treturn p;\n");
520 output ("MBState *\n");
521 output ("mono_burg_label (MBTREE_TYPE *tree, MBCOST_DATA *data)\n{\n");
523 output ("\tMBState *p = MBALLOC_STATE;\n");
524 output ("\tmono_burg_label_priv (tree, data, p);\n");
526 output ("\tMBState *p = mono_burg_label_priv (tree, data);\n");
528 output ("\treturn p->rule_%s ? p : NULL;\n", ((NonTerm *)nonterm_list->data)->name);
533 compute_kids (char *ts, Tree *tree, int *n)
538 return g_strdup_printf ("\t\tkids[%d] = %s;\n", (*n)++, ts);
539 } else if (tree->op && tree->op->arity) {
543 res = compute_kids (g_strdup_printf ("%s->left", ts),
545 if (tree->op->arity == 2)
546 res2 = compute_kids (g_strdup_printf ("%s->right", ts),
549 res = compute_kids (g_strdup_printf ("MBTREE_LEFT(%s)", ts),
551 if (tree->op->arity == 2)
552 res2 = compute_kids (g_strdup_printf ("MBTREE_RIGHT(%s)", ts),
556 return g_strconcat (res, res2, NULL);
569 output ("mono_burg_rule (MBState *state, int goal)\n{\n");
571 output ("\tg_return_val_if_fail (state != NULL, 0);\n");
572 output ("\tg_return_val_if_fail (goal > 0, 0);\n\n");
574 output ("\tswitch (goal) {\n");
576 for (nl = nonterm_list; nl; nl = nl->next) {
577 NonTerm *n = (NonTerm *)nl->data;
578 output ("\tcase MB_NTERM_%s:\n", n->name);
579 output ("\t\treturn mono_burg_decode_%s [state->rule_%s];\n",
583 output ("\tdefault: g_assert_not_reached ();\n");
585 output ("\treturn 0;\n");
590 output ("MBState **\n");
591 output ("mono_burg_kids (MBState *state, int rulenr, MBState *kids [])\n{\n");
592 output ("\tg_return_val_if_fail (state != NULL, NULL);\n");
593 output ("\tg_return_val_if_fail (kids != NULL, NULL);\n\n");
596 output ("MBTREE_TYPE **\n");
597 output ("mono_burg_kids (MBTREE_TYPE *tree, int rulenr, MBTREE_TYPE *kids [])\n{\n");
598 output ("\tg_return_val_if_fail (tree != NULL, NULL);\n");
599 output ("\tg_return_val_if_fail (kids != NULL, NULL);\n\n");
602 output ("\tswitch (rulenr) {\n");
604 n = g_list_length (rule_list);
605 sa = g_new0 (char *, n);
606 si = g_new0 (int, n);
608 /* compress the case statement */
609 for (l = rule_list, i = 0, c = 0; l; l = l->next) {
610 Rule *rule = (Rule *)l->data;
615 k = compute_kids ("state", rule->tree, &kn);
617 k = compute_kids ("tree", rule->tree, &kn);
619 for (j = 0; j < c; j++)
620 if (!strcmp (sa [j], k))
628 for (i = 0; i < c; i++) {
629 for (l = rule_list, j = 0; l; l = l->next, j++)
631 output ("\tcase %d:\n", j + 1);
632 output ("%s", sa [i]);
633 output ("\t\tbreak;\n");
636 output ("\tdefault:\n\t\tg_assert_not_reached ();\n");
638 output ("\treturn kids;\n");
649 for (l = rule_list, i = 0; l; l = l->next) {
650 Rule *rule = (Rule *)l->data;
653 output ("static void ");
655 emit_rule_string (rule, "");
658 output ("mono_burg_emit_%d (MBState *state, MBTREE_TYPE *tree, MBCGEN_TYPE *s)\n", i);
660 output ("mono_burg_emit_%d (MBTREE_TYPE *tree, MBCGEN_TYPE *s)\n", i);
662 output ("%s\n", rule->code);
668 output ("MBEmitFunc const mono_burg_func [] = {\n");
669 output ("\tNULL,\n");
670 for (l = rule_list, i = 0; l; l = l->next) {
671 Rule *rule = (Rule *)l->data;
673 output ("\tmono_burg_emit_%d,\n", i);
675 output ("\tNULL,\n");
687 for (l = rule_list, i = 0; l; l = l->next) {
688 Rule *rule = (Rule *)l->data;
691 output ("inline static guint16\n");
693 emit_rule_string (rule, "");
695 output ("mono_burg_cost_%d (MBTREE_TYPE *tree, MBCOST_DATA *data)\n", i + 1);
697 output ("%s\n", rule->cfunc);
709 for (l = nonterm_list; l; l = l->next) {
710 NonTerm *n = (NonTerm *)l->data;
713 output ("static void closure_%s (MBState *p, int c);\n", n->name);
718 for (l = nonterm_list; l; l = l->next) {
719 NonTerm *n = (NonTerm *)l->data;
722 output ("static void\n");
723 output ("closure_%s (MBState *p, int c)\n{\n", n->name);
724 for (rl = n->chain; rl; rl = rl->next) {
725 Rule *rule = (Rule *)rl->data;
727 emit_rule_string (rule, "\t");
728 emit_cond_assign (rule, rule->cost, "\t");
736 compute_nonterms (Tree *tree)
742 return g_strdup_printf ("MB_NTERM_%s, ", tree->nonterm->name);
744 return g_strconcat (compute_nonterms (tree->left),
745 compute_nonterms (tree->right), NULL);
756 if (predefined_terms) {
757 output ("guint8 mono_burg_arity [MBMAX_OPCODES];\n");
759 output ("void\nmono_burg_init (void)\n{\n");
761 for (l = term_list, i = 0; l; l = l->next) {
762 Term *t = (Term *)l->data;
764 output ("\tmono_burg_arity [%s] = %d; /* %s */\n", t->name, t->arity, t->name);
771 output ("const guint8 mono_burg_arity [] = {\n");
772 for (l = term_list, i = 0; l; l = l->next) {
773 Term *t = (Term *)l->data;
775 while (i < t->number) {
780 output ("\t%d, /* %s */\n", t->arity, t->name);
786 output ("const char *const mono_burg_term_string [] = {\n");
787 output ("\tNULL,\n");
788 for (l = term_list, i = 0; l; l = l->next) {
789 Term *t = (Term *)l->data;
790 output ("\t\"%s\",\n", t->name);
795 output ("const char * const mono_burg_rule_string [] = {\n");
796 output ("\tNULL,\n");
797 for (l = rule_list, i = 0; l; l = l->next) {
798 Rule *rule = (Rule *)l->data;
799 output ("\t\"%s: ", rule->lhs->name);
800 emit_tree_string (rule->tree);
805 n = g_list_length (rule_list);
806 sa = g_new0 (char *, n);
807 si = g_new0 (int, n);
809 /* compress the _nts array */
810 for (l = rule_list, i = 0, c = 0; l; l = l->next) {
811 Rule *rule = (Rule *)l->data;
812 char *s = compute_nonterms (rule->tree);
814 for (j = 0; j < c; j++)
815 if (!strcmp (sa [j], s))
820 output ("static const guint16 mono_burg_nts_%d [] = { %s0 };\n", c, s);
826 output ("const guint16 *const mono_burg_nts [] = {\n");
828 for (l = rule_list, i = 0; l; l = l->next) {
829 Rule *rule = (Rule *)l->data;
830 output ("\tmono_burg_nts_%d, ", si [i++]);
831 emit_rule_string (rule, "");
840 output ("typedef void (*MBEmitFunc) (MBState *state, MBTREE_TYPE *tree, MBCGEN_TYPE *s);\n\n");
842 output ("typedef void (*MBEmitFunc) (MBTREE_TYPE *tree, MBCGEN_TYPE *s);\n\n");
844 output ("extern const char * const mono_burg_term_string [];\n");
845 output ("extern const char * const mono_burg_rule_string [];\n");
846 output ("extern const guint16 *const mono_burg_nts [];\n");
847 output ("extern MBEmitFunc const mono_burg_func [];\n");
849 output ("MBState *mono_burg_label (MBTREE_TYPE *tree, MBCOST_DATA *data);\n");
850 output ("int mono_burg_rule (MBState *state, int goal);\n");
853 output ("MBState **mono_burg_kids (MBState *state, int rulenr, MBState *kids []);\n");
855 output ("MBTREE_TYPE **mono_burg_kids (MBTREE_TYPE *tree, int rulenr, MBTREE_TYPE *kids []);\n");
857 output ("extern void mono_burg_init (void);\n");
861 static void check_reach (NonTerm *n);
864 mark_reached (Tree *tree)
866 if (tree->nonterm && !tree->nonterm->reached)
867 check_reach (tree->nonterm);
869 mark_reached (tree->left);
871 mark_reached (tree->right);
875 check_reach (NonTerm *n)
880 for (l = n->rules; l; l = l->next) {
881 Rule *rule = (Rule *)l->data;
882 mark_reached (rule->tree);
891 for (l = term_list; l; l = l->next) {
892 Term *term = (Term *)l->data;
893 if (term->arity == -1)
894 g_warning ("unused terminal \"%s\"",term->name);
897 check_reach (((NonTerm *)nonterm_list->data));
899 for (l = nonterm_list; l; l = l->next) {
900 NonTerm *n = (NonTerm *)l->data;
902 g_error ("unreachable nonterm \"%s\"", n->name);
910 "Usage is: monoburg -d file.h -s file.c [inputfile] \n");
915 warning_handler (const gchar *log_domain,
916 GLogLevelFlags log_level,
917 const gchar *message,
920 (void) fprintf ((FILE *) user_data, "** WARNING **: %s\n", message);
924 main (int argc, char *argv [])
927 char *deffile = NULL;
931 g_log_set_handler (NULL, G_LOG_LEVEL_WARNING, warning_handler, stderr);
933 for (i = 1; i < argc; i++){
934 if (argv [i][0] == '-'){
935 if (argv [i][1] == 'h') {
937 } else if (argv [i][1] == 'e') {
939 } else if (argv [i][1] == 'p') {
940 predefined_terms = 1;
941 } else if (argv [i][1] == 'd') {
942 deffile = argv [++i];
943 } else if (argv [i][1] == 's') {
957 if (!(deffd = fopen (deffile, "w"))) {
958 perror ("cant open header output file");
962 output ("#ifndef _MONO_BURG_DEFS_\n");
963 output ("#define _MONO_BURG_DEFS_\n\n");
969 if (!(inputfd = fopen (infile, "r"))) {
970 perror ("cant open input file");
982 g_error ("no start symbol found");
990 output ("#endif /* _MONO_BURG_DEFS_ */\n");
996 if (!(cfd = fopen (cfile, "w"))) {
997 perror ("cant open c output file");
998 (void) remove (deffile);
1005 output ("#include \"%s\"\n\n", deffile);
1010 emit_emitter_func ();