]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Fix some DFA construction bugs
authorQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 18 Jul 2016 16:16:36 +0000 (16:16 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 18 Jul 2016 16:16:36 +0000 (16:16 +0000)
Options get null paths, parser state is properly
cleaned up, caller passes start node

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/cmdtree.c
lib/cmdtree.h
lib/command_parse.y
lib/grammar_sandbox.c

index c7bdf381c76686e53cc2a253068a98eb6d32b173..da647a7ae3d9f33a760e8347db484bc8a4f968d8 100644 (file)
@@ -29,7 +29,7 @@ add_node(struct graph_node *parent, struct graph_node *child)
 int
 cmp_node(struct graph_node *first, struct graph_node *second)
 {
-  return 1;
+  return 0;
 }
 
 struct graph_node *
@@ -44,3 +44,55 @@ new_node(enum graph_node_type type)
 
   return node;
 }
+
+void
+walk_graph(struct graph_node *start, int level)
+{
+  // print this node
+  switch (start->type) {
+    case WORD_GN:
+    case IPV4_GN:
+    case IPV4_PREFIX_GN:
+    case IPV6_GN:
+    case IPV6_PREFIX_GN:
+    case VARIABLE_GN:
+    case RANGE_GN:
+      fprintf(stderr, "%s", start->text);
+      break;
+    case NUMBER_GN:
+      fprintf(stderr, "%d", start->value);
+      break;
+    case SELECTOR_GN:
+      fprintf(stderr, "<>");
+      break;
+    case OPTION_GN:
+      fprintf(stderr, "[]");
+      break;
+    case NUL_GN:
+      fprintf(stderr, "NUL");
+      break;
+    default:
+      fprintf(stderr, "ERROR");
+  }
+  fprintf(stderr, "[%d] ", vector_active(start->children));
+
+  if (vector_active(start->children))
+    for (unsigned int i = 0; i < vector_active(start->children); i++) {
+      struct graph_node *r = vector_slot(start->children, i);
+      if (!r) {
+        fprintf(stderr, "Child seems null?\n");
+        break;
+      }
+      else {
+        if (start->type == OPTION_GN || start->type == SELECTOR_GN) {
+          fprintf(stderr, "\n");
+          for (int i = 0; i < level+1; i++)
+            fprintf(stderr, "\t");
+        }
+        walk_graph(r, level+1);
+      }
+    }
+  else {
+    fprintf(stderr, "\n");
+  }
+}
index e9a10d7ec56878c002365b49ad6bd960bbe06ae1..9b512e3bb9d85306335964539ac040145c50c66e 100644 (file)
@@ -53,3 +53,6 @@ cmp_node(struct graph_node *first, struct graph_node *second);
 
 extern struct graph_node *
 new_node(enum graph_node_type type);
+
+extern void
+walk_graph(struct graph_node *, int);
index 1f519e27fa17aa903e1b2d2b1a05cfb0838bcf92..7bdec6dca120105648934bdd3361f8f5a39bfaee 100644 (file)
@@ -8,7 +8,7 @@ extern void yyerror(const char *);
 #define YYDEBUG 1
 %}
 %code provides {
-extern struct graph_node *cmd_parse_format_new(const char *, const char *);
+extern struct graph_node *cmd_parse_format_new(const char *, const char *, struct graph_node *);
 extern void set_buffer_string(const char *);
 }
 
@@ -19,18 +19,16 @@ extern void set_buffer_string(const char *);
 }
 
 %{
-// last top-level node
 struct graph_node *startnode,       // command root node
                   *currnode,        // current node
-                  *tmpnode,         // temp node pointer
                   *seqhead;         // sequence head
 
 
-struct graph_node *optnode_start = NULL,   // start node for option set
-                  *optnode_end = NULL;     // end node for option set
+struct graph_node *optnode_start,   // start node for option set
+                  *optnode_end;     // end node for option set
 
-struct graph_node *selnode_start = NULL,   // start node for selector set
-                  *selnode_end = NULL;     // end node for selector set
+struct graph_node *selnode_start,   // start node for selector set
+                  *selnode_end;     // end node for selector set
 %}
 
 %token <node> WORD
@@ -65,7 +63,12 @@ start: sentence_root
 
 sentence_root: WORD
 {
-  currnode = new_node(WORD_GN);
+  $$ = new_node(WORD_GN);
+  $$->text = strdup(yylval.string);
+  fprintf(stderr, ">>>>>>>> YYLVAL.STRING: %s\n", yylval.string);
+  fprintf(stderr, ">>>>>>>> TEXT: %s\n", $$->text);
+
+  currnode = $$;
   currnode->is_root = 1;
   add_node(startnode, currnode);
 };
@@ -98,18 +101,34 @@ cmd_token_seq:
 
 placeholder_token:
   IPV4
-{ $$ = new_node(IPV4_GN); }
+{
+  $$ = new_node(IPV4_GN);
+  $$->text = strdup(yylval.string);
+}
 | IPV4_PREFIX
-{ $$ = new_node(IPV4_PREFIX_GN); }
+{ 
+  $$ = new_node(IPV4_PREFIX_GN);
+  $$->text = strdup(yylval.string);
+}
 | IPV6
-{ $$ = new_node(IPV6_GN); }
+{ 
+  $$ = new_node(IPV6_GN);
+  $$->text = strdup(yylval.string);
+}
 | IPV6_PREFIX
-{ $$ = new_node(IPV6_PREFIX_GN); }
+{ 
+  $$ = new_node(IPV6_PREFIX_GN);
+  $$->text = strdup(yylval.string);
+}
 | VARIABLE
-{ $$ = new_node(VARIABLE_GN); }
+{ 
+  $$ = new_node(VARIABLE_GN);
+  $$->text = strdup(yylval.string);
+}
 | RANGE
 {
   $$ = new_node(RANGE_GN);
+  $$->text = strdup(yylval.string);
 
   // get the numbers out
   strsep(&yylval.string, "(-)");
@@ -128,6 +147,8 @@ literal_token:
 {
   $$ = new_node(WORD_GN);
   $$->text = strdup(yylval.string);
+  fprintf(stderr, ">>>>>>>> YYLVAL.STRING: %s\n", yylval.string);
+  fprintf(stderr, ">>>>>>>> TEXT: %s\n", $$->text);
 }
 | NUMBER
 {
@@ -136,7 +157,7 @@ literal_token:
 }
 ;
 
-/* <selector|token> productions */
+/* <selector|set> productions */
 selector:
   '<' selector_part '|' selector_element '>'
 {
@@ -201,7 +222,14 @@ selector_token:
 
 /* [option|set] productions */
 option: '[' option_part ']'
-{ $$ = optnode_start; };
+{
+  // add null path
+  struct graph_node *nullpath = new_node(NUL_GN);
+  add_node(optnode_start, nullpath);
+  add_node(nullpath, optnode_end);
+
+  $$ = optnode_start;
+};
 
 option_part:
   option_part '|' option_element
@@ -234,30 +262,28 @@ option_token:
 ;
 
 %%
-/*
-int
-main (void)
-{
-  const char* input = "show [random conf NAME] thing";
-  printf("Parsing:\n\t%s\n", input);
-  return cmd_parse_format_new(input, "description");
-}
-*/
+
 void yyerror(char const *message) {
   printf("Grammar error: %s\n", message);
   exit(EXIT_FAILURE);
 }
 
 struct graph_node *
-cmd_parse_format_new(const char *string, const char *desc)
+cmd_parse_format_new(const char *string, const char *desc, struct graph_node *start)
 {
   fprintf(stderr, "parsing: %s\n", string);
 
+  /* clear state pointers */
+  startnode = currnode = seqhead = NULL;
+  selnode_start = selnode_end = NULL;
+  optnode_start = optnode_end = NULL;
+
+  // trace parser
   yydebug = 1;
   // make flex read from a string
   set_buffer_string(string);
   // initialize the start node of this command dfa
-  startnode = new_node(NUL_GN);
+  startnode = start;
   // parse command into DFA
   yyparse();
   // startnode points to command DFA
index fd0eec02d62db8f6932c3ca432ae990d2fa509c3..0cc6896d8e0225529f626fb9d11525a8e3f95b4d 100644 (file)
@@ -1,5 +1,6 @@
 #include "command.h"
 #include "command_parse.h"
+#include "cmdtree.h"
 
 #define GRAMMAR_STR "CLI grammar sandbox\n"
 
@@ -21,8 +22,12 @@ DEFUN (grammar_test,
       strcat(cat, " ");
   }
 
-  cmd_parse_format_new((const char*) cat, "lol");
-
+  struct graph_node *result = new_node(NUL_GN);
+  /* cmd_parse_format_new((const char*) cat, "lol", result);*/
+  cmd_parse_format_new ("test <command|options> lol", "lol", result);
+  cmd_parse_format_new ("test <command|options> lol", "lol", result);
+  walk_graph(result, 0);
+  
   return CMD_SUCCESS;
 }