From: Quentin Young Date: Thu, 7 Jul 2016 20:35:52 +0000 (+0000) Subject: lib: Start implementing DFA X-Git-Tag: frr-3.0-branchpoint~129^2~291 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=782d97897eb26c18721d268b7fa22226d170ee0d;p=matthieu%2Ffrr.git lib: Start implementing DFA Signed-off-by: Quentin Young --- diff --git a/lib/cmdtree.c b/lib/cmdtree.c index 921c6d9cc6..5bb76cce3a 100644 --- a/lib/cmdtree.c +++ b/lib/cmdtree.c @@ -1,41 +1,44 @@ -#include -#include +/* + * Command DFA module. + * Provides a DFA data structure and associated functions for manipulating it. + * Used to match user command line input. + * + * @author Quentin Young + */ -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 index 0000000000..77d2e0aa34 --- /dev/null +++ b/lib/cmdtree.h @@ -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); diff --git a/lib/command.lex b/lib/command.lex index 35450cd45f..ae97265ff7 100644 --- a/lib/command.lex +++ b/lib/command.lex @@ -2,7 +2,7 @@ #include #include -#include "command.tab.h" +#include "command.h" %} WORD [a-z][-_a-z0-9]+ diff --git a/lib/command.y b/lib/command.y index 9bc45b5419..1394ef4214 100644 --- a/lib/command.y +++ b/lib/command.y @@ -2,95 +2,161 @@ #include #include #include +#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 WORD -%token IPV4 -%token IPV4_PREFIX -%token IPV6 -%token IPV6_PREFIX -%token VARIABLE -%token RANGE -%token NUMBER +%{ +// last top-level node +struct graph_node *topnode, +// + *optnode, + *selnode; +%} + +%token WORD +%token IPV4 +%token IPV4_PREFIX +%token IPV6 +%token IPV6_PREFIX +%token VARIABLE +%token RANGE +%token NUMBER + +%type start +%type sentence_root +%type cmd_token +%type literal_token +%type placeholder_token +%type option_token +%type selector_token +%type option +%type selector +%type selector_token_seq +%type 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);} +; /* 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; +} + +