]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Start implementing DFA
authorQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 7 Jul 2016 20:35:52 +0000 (20:35 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 12 Jul 2016 15:05:05 +0000 (15:05 +0000)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/cmdtree.c
lib/cmdtree.h [new file with mode: 0644]
lib/command.lex
lib/command.y

index 921c6d9cc6cb006044de0df077b61603f8e1929e..5bb76cce3aaef57deb14c94d838f52c57a636a86 100644 (file)
@@ -1,41 +1,44 @@
-#include <command.h>
-#include <vector.h>
+/*
+ * Command DFA module.
+ * Provides a DFA data structure and associated functions for manipulating it.
+ * Used to match user command line input.
+ *
+ * @author Quentin Young <qlyoung@cumulusnetworks.com>
+ */
 
-enum tree_node_type
-{
-  WORD_TN,
-  IPV4_TN,
-  IPV4_PREFIX_TN,
-  IPV6_TN,
-  IPV6_PREFIX_TN,
-  VARIABLE_TN,
-  RANGE_TN,
-  NUMBER_TN,
-  SELECTOR_TN,
-  OPTION_TN
-}
-
-struct tree_node
-{
-  enum tree_node_type type;
-  vector children;
-  int leaf;
-  (int) (*func(struct cmd_info *, struct vty *, int, const char *[]));
-}
+#include "memory.h"
+#include "cmdtree.h"
 
-void add_node(struct tree_node *parent, struct tree_node *child)
+struct graph_node *
+add_node(struct graph_node *parent, struct graph_node *child)
 {
+  int index;
+  struct graph_node *p_child;
 
+  for (index = 0; index < vector_active(parent->children); index++)
+  {
+    *p_child = vector_slot(parent->children, index);
+    if (cmp_node(child, p_child))
+      return p_child;
+  }
+  vector_set(parent->children, child);
+  return child;
 }
 
-// checks nodes for equivalence; definition of equivalence depends
-// on node type (WORD_TN strcmps words, etc)
-int cmp_node(struct tree_node *first, struct tree_node *second)
+int
+cmp_node(struct graph_node *first, struct graph_node *second)
 {
-  
 }
 
-int merge_tree(struct tree_node *first, struct tree_node *second)
+struct graph_node *
+new_node(enum graph_node_type type)
 {
+  struct graph_node *node = XMALLOC(MTYPE_TMP, sizeof(graph_node));
+  node->type = type;
+  node->children = vector_init(VECTOR_MIN_SIZE);
+  node->is_leaf = 0;
+  node->is_root = 0;
+  node->func = NULL;
 
+  return node;
 }
diff --git a/lib/cmdtree.h b/lib/cmdtree.h
new file mode 100644 (file)
index 0000000..77d2e0a
--- /dev/null
@@ -0,0 +1,43 @@
+#include "vector.h"
+
+enum graph_node_type
+{
+  WORD_GN,
+  IPV4_GN,
+  IPV4_PREFIX_GN,
+  IPV6_GN,
+  IPV6_PREFIX_GN,
+  VARIABLE_GN,
+  RANGE_GN,
+  NUMBER_GN,
+  SELECTOR_GN,
+  OPTION_GN,
+  NUL_GN
+};
+
+struct graph_node
+{
+  enum graph_node_type type;
+  vector children;
+  int is_leaf, is_root;
+  // int (*func(struct cmd_info *, struct vty *, int, const char *[]));
+};
+
+/*
+ * Adds a child to a node. If the node already has the exact same
+ * child, nothing is done.
+ */
+struct graph_node *
+add_node(struct graph_node *, struct graph_node *);
+
+/*
+ * Compares two nodes for equivalence.
+ * What exactly constitutes two nodes being equal depends on the
+ * node type.
+ * @return 0 if equal, nonzero otherwise.
+ */
+int
+cmp_node(struct graph_node *first, struct graph_node *second);
+
+struct graph_node *
+new_node(enum graph_node_type type);
index 35450cd45f47b59f8343dbd7aadfc5560491a627..ae97265ff74a983f238855a4d1822ef61ae5ba80 100644 (file)
@@ -2,7 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include "command.tab.h"
+#include "command.h"
 %}
 
 WORD            [a-z][-_a-z0-9]+
index 9bc45b541931f86bc09a064b18793297cbb4963f..1394ef4214a0ed8c1d5875cebd5984e9708cfef1 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include "cmdtree.h"
 
 extern int yylex(void);
-extern void yyerror(const char *);
+void yyerror(const char *);
+
+// turn on debug
+#define YYDEBUG 1
 %}
 
 %union{
   int integer;
   char *string;
+  struct graph_node *node;
 }
 
-%token <string>     WORD
-%token <string>     IPV4
-%token <string>     IPV4_PREFIX
-%token <string>     IPV6
-%token <string>     IPV6_PREFIX
-%token <string>     VARIABLE
-%token <string>     RANGE
-%token <integer>    NUMBER
+%{
+// last top-level node
+struct graph_node *topnode,
+// 
+                  *optnode,
+                  *selnode;
+%}
+
+%token <string>  WORD
+%token <string>  IPV4
+%token <string>  IPV4_PREFIX
+%token <string>  IPV6
+%token <string>  IPV6_PREFIX
+%token <string>  VARIABLE
+%token <string>  RANGE
+%token <integer> NUMBER
+
+%type <node> start
+%type <node> sentence_root
+%type <node> cmd_token
+%type <node> literal_token
+%type <node> placeholder_token
+%type <node> option_token
+%type <node> selector_token
+%type <node> option
+%type <node> selector
+%type <node> selector_token_seq
+%type <node> option_token_seq
+
+%output "command.c"
+%defines
 
 /* grammar proper */
 %%
 
-start: sentence_root                    {printf("Matched sentence root\n");}
-       cmd_token_seq                    {printf("Matched sentence\n");};
+start: sentence_root
+       cmd_token_seq;
 
-sentence_root: WORD                     {printf("Sentence root: %s\n", $1);};
+sentence_root: WORD                     {
+                                          currnode = new_node(WORD_GN);
+                                          currnode->is_root = 1;
+                                        };
 
 /* valid top level tokens */
-cmd_token: placeholder_token
-         | literal_token
-         | selector
-         | option
-         ;
-cmd_token_seq: /* empty */
-             | cmd_token_seq cmd_token;
-
-placeholder_token: IPV4                 {printf("Matched placeholder\n");}
-                 | IPV4_PREFIX          {printf("Matched placeholder\n");}
-                 | IPV6                 {printf("Matched placeholder\n");}
-                 | IPV6_PREFIX          {printf("Matched placeholder\n");}
-                 | VARIABLE             {printf("Matched placeholder\n");}
-                 | RANGE                {printf("Matched placeholder\n");}
-
-literal_token: WORD
-             | NUMBER
-             ;
-/* range: '(' NUMBER '-' NUMBER ')'        {printf("Matched range\n");}; */
+cmd_token:
+  placeholder_token
+| literal_token
+| selector
+| option
+;
 
+cmd_token_seq:
+  %empty
+| cmd_token_seq cmd_token
+;
+
+placeholder_token:
+  IPV4                                  {$$ = new_node(IPV4_GN);}
+| IPV4_PREFIX                           {$$ = new_node(IPV4_PREFIX_GN);}
+| IPV6                                  {$$ = new_node(IPV6_GN);}
+| IPV6_PREFIX                           {$$ = new_node(IPV6_PREFIX_GN);}
+| VARIABLE                              {$$ = new_node(VARIABLE_GN);}
+| RANGE                                 {$$ = new_node(RANGE_GN);}
+;
+
+literal_token:
+  WORD                                  {$$ = new_node(WORD_GN);}
+| NUMBER                                {$$ = new_node(NUMBER_GN);}
+;
 
 /* <selector|token> productions */
-selector: '<' selector_part '|'
-              selector_element '>'      {printf("Matched selector\n");};
-selector_part: selector_part '|'
-               selector_element
-             | selector_element
-                                        {printf("Matched selector part\n");};
-selector_element: WORD
-                  selector_token_seq
-selector_token_seq: /* empty */
-                  | selector_token_seq
-                    selector_token
-                  ;
-selector_token: literal_token
-              | placeholder_token
-              | option
-              ;
+selector:
+  '<' selector_part '|'
+      selector_element '>'              {
+                                        //$$ = new_node(SELECTOR_GN);
+                                        //add_node($$, $4);
+                                        };
+
+selector_part:
+  selector_part '|' selector_element    
+| selector_element
+;
+
+selector_element:
+  WORD selector_token_seq;
+
+selector_token_seq:
+  %empty
+| selector_token_seq selector_token     {
+                                        //add_node(currnode, $2);
+                                        //currnode = $2;
+                                        }
+;
+
+selector_token:
+  literal_token
+| placeholder_token
+| option
+;
 
 /* [option|set] productions */
-option: '[' option_part ']'             {printf("Matched option\n");};
-option_part: option_part '|'
-             option_element_seq
-           | option_element_seq
-           ;
-option_element_seq: option_token
-                  | option_element_seq
-                    option_token
-                  ;
-option_token: literal_token
-            | placeholder_token
-            ;
+option: '[' option_part ']';
+
+option_part:
+  option_part '|' option_token_seq
+| option_token_seq
+;
+
+option_token_seq:
+  option_token
+| option_token_seq option_token
+;
+
+option_token:
+  literal_token
+| placeholder_token
+;
+
 %%
 
 int
 main (void)
 {
-  return yyparse ();
+  yydebug = 1;
+  const char* input = "show [random conf NAME] thing";
+  printf("Parsing:\n\t%s\n", input);
+  return cmd_parse_format(input, "description");
 }
 
 void yyerror(char const *message) {
   printf("Grammar error: %s\n", message);
   exit(EXIT_FAILURE);
 }
+
+int
+cmd_parse_format(const char *string, const char *desc)
+{
+  yy_scan_string(string);
+  yyparse();
+  return 0;
+}
+
+