From 67e5b2fee0e4ceff7fab9375065e737eda12dfe0 Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Fri, 7 Jun 2013 16:30:16 +0200
Subject: [PATCH] add DFA pretty-printer

---
 src/backends/lalr.c | 99 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 4 deletions(-)

diff --git a/src/backends/lalr.c b/src/backends/lalr.c
index 509f76d2..15236f5e 100644
--- a/src/backends/lalr.c
+++ b/src/backends/lalr.c
@@ -317,6 +317,93 @@ HParseResult *h_lr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
 
 
 
+/* Pretty-printers */
+
+void h_pprint_lritem(FILE *f, const HCFGrammar *g, const HLRItem *item)
+{
+  h_pprint_symbol(f, g, item->lhs);
+  fputs(" ->", f);
+
+  HCFChoice **x = item->rhs;
+  HCFChoice **mark = item->rhs + item->mark;
+  if(*x == NULL) {
+    fputs("\"\"", f);
+  } else {
+    while(*x) {
+      if(x == mark)
+        fputc('.', f);
+      else
+        fputc(' ', f);
+
+      if((*x)->type == HCF_CHAR) {
+        // condense character strings
+        fputc('"', f);
+        h_pprint_char(f, (*x)->chr);
+        for(x++; *x; x++) {
+          if(x == mark)
+            break;
+          if((*x)->type != HCF_CHAR)
+            break;
+          h_pprint_char(f, (*x)->chr);
+        }
+        fputc('"', f);
+      } else {
+        h_pprint_symbol(f, g, *x);
+        x++;
+      }
+    }
+    if(x == mark)
+      fputs(".", f);
+  }
+}
+
+void h_pprint_lrstate(FILE *f, const HCFGrammar *g,
+                      const HLRState *state, unsigned int indent)
+{
+  bool first = true;
+  const HHashTable *ht = state;
+  for(size_t i=0; i < ht->capacity; i++) {
+    for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
+      if(hte->key == NULL)
+        continue;
+  
+      const HLRItem *item = hte->key;
+
+      if(!first)
+        for(unsigned int i=0; i<indent; i++) fputc(' ', f);
+      first = false;
+      h_pprint_lritem(f, g, item);
+      fputc('\n', f);
+    }
+  }
+}
+
+void pprint_transition(FILE *f, const HCFGrammar *g, const HLRTransition *t)
+{
+  fputs("-", f);
+  h_pprint_symbol(f, g, t->symbol);
+  fprintf(f, "->%lu", t->to);
+}
+
+void h_pprint_lrdfa(FILE *f, const HCFGrammar *g,
+                    const HLRDFA *dfa, unsigned int indent)
+{
+  for(size_t i=0; i<dfa->nstates; i++) {
+    unsigned int indent2 = indent + fprintf(f, "%4lu: ", i);
+    h_pprint_lrstate(f, g, dfa->states[i], indent2);
+    for(HSlistNode *x = dfa->transitions->head; x; x = x->next) {
+      const HLRTransition *t = x->elem;
+      if(t->from == i) {
+        for(unsigned int i=0; i<indent2-2; i++) fputc(' ', f);
+        pprint_transition(f, g, t);
+        fputc('\n', f);
+      }
+    }
+  }
+}
+
+
+
 
 HParserBackendVTable h__lalr_backend_vtable = {
   .compile = h_lalr_compile,
@@ -346,6 +433,7 @@ int test_lalr(void)
   HParser *B = h_sequence(Y, h_ch('b'), NULL);
   HParser *p = h_choice(A, B, NULL);
 
+  printf("\n==== G R A M M A R ====\n");
   HCFGrammar *g = h_cfgrammar(&system_allocator, p);
   if(g == NULL) {
     fprintf(stderr, "h_cfgrammar failed\n");
@@ -353,18 +441,21 @@ int test_lalr(void)
   }
   h_pprint_grammar(stdout, g, 0);
 
+  printf("\n==== D F A ====\n");
   HLRDFA *dfa = h_lalr_dfa(g);
-  if(dfa) {
-    // print states of the LR(0) automaton
-  }
+  if(dfa)
+    h_pprint_lrdfa(stdout, g, dfa, 0);
+  else
+    fprintf(stderr, "h_lalr_dfa failed\n");
 
+  printf("\n==== L A L R  T A B L E ====\n");
   if(h_compile(p, PB_LALR, NULL)) {
     fprintf(stderr, "does not compile\n");
     return 2;
   }
   // print LALR(1) table
 
-
+  printf("\n==== P A R S E  R E S U L T ====\n");
   HParseResult *res = h_parse(p, (uint8_t *)"xyya", 4);
   if(res)
     h_pprint(stdout, res->ast, 0, 2);
-- 
GitLab