* @author Quentin Young <qlyoung@cumulusnetworks.com>
*/
-#include "memory.h"
+#include <zebra.h>
#include "cmdtree.h"
+#include "memory.h"
struct graph_node *
add_node(struct graph_node *parent, struct graph_node *child)
{
- int index;
+ unsigned int index;
struct graph_node *p_child;
for (index = 0; index < vector_active(parent->children); index++)
{
- *p_child = vector_slot(parent->children, index);
+ p_child = vector_slot(parent->children, index);
if (cmp_node(child, p_child))
return p_child;
}
int
cmp_node(struct graph_node *first, struct graph_node *second)
{
+ return 1;
}
struct graph_node *
new_node(enum graph_node_type type)
{
- struct graph_node *node = XMALLOC(MTYPE_TMP, sizeof(graph_node));
+ struct graph_node *node = malloc(sizeof(struct graph_node));
node->type = type;
node->children = vector_init(VECTOR_MIN_SIZE);
node->is_leaf = 0;
+#include "vty.h"
#include "vector.h"
enum graph_node_type
enum graph_node_type type;
vector children;
int is_leaf, is_root;
- // int (*func(struct cmd_info *, struct vty *, int, const char *[]));
+ int (*func)(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 *
+extern struct graph_node *
add_node(struct graph_node *, struct graph_node *);
/*
* node type.
* @return 0 if equal, nonzero otherwise.
*/
-int
+extern int
cmp_node(struct graph_node *first, struct graph_node *second);
-struct graph_node *
+extern struct graph_node *
new_node(enum graph_node_type type);
+++ /dev/null
-%{
-#include <string.h>
-#include <stdlib.h>
-
-#include "command.h"
-%}
-
-WORD [a-z][-_a-z0-9]+
-IPV4 A\.B\.C\.D
-IPV4_PREFIX A\.B\.C\.D\/M
-IPV6 X:X::X:X
-IPV6_PREFIX X:X::X:X\/M
-VARIABLE [A-Z][A-Z_]+
-NUMBER [0-9]{1,20}
-RANGE \({NUMBER}\-{NUMBER}\)
-
-/* yytext shall be a pointer */
-%pointer
-%option noyywrap
-
-%%
-"<" return '<';
-">" return '>';
-
-[ /t] /* ignore whitespace */;
-{WORD} {yylval.string = strdup(yytext); return WORD;}
-{IPV4} {yylval.string = strdup(yytext); return IPV4;}
-{IPV4_PREFIX} {yylval.string = strdup(yytext); return IPV4_PREFIX;}
-{IPV6} {yylval.string = strdup(yytext); return IPV6;}
-{IPV6_PREFIX} {yylval.string = strdup(yytext); return IPV6_PREFIX;}
-{VARIABLE} {yylval.string = strdup(yytext); return VARIABLE;}
-{NUMBER} {yylval.integer = atoi(yytext); return NUMBER;}
-{RANGE} {yylval.string = strdup(yytext); return RANGE;}
-. {return yytext[0];}
-%%
+++ /dev/null
-%{
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "cmdtree.h"
-
-extern int yylex(void);
-void yyerror(const char *);
-
-// turn on debug
-#define YYDEBUG 1
-%}
-
-%union{
- int integer;
- char *string;
- struct graph_node *node;
-}
-
-%{
-// 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
- cmd_token_seq;
-
-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 {$$ = 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 '>' {
- //$$ = 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 ']';
-
-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)
-{
- 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;
-}
-
-
--- /dev/null
+%{
+#include "command_parse.h"
+
+extern void set_buffer_string(const char *);
+%}
+
+WORD [a-z][-_a-z0-9]+
+IPV4 A\.B\.C\.D
+IPV4_PREFIX A\.B\.C\.D\/M
+IPV6 X:X::X:X
+IPV6_PREFIX X:X::X:X\/M
+VARIABLE [A-Z][A-Z_]+
+NUMBER [0-9]{1,20}
+RANGE \({NUMBER}\-{NUMBER}\)
+
+/* yytext shall be a pointer */
+%pointer
+%option noyywrap
+%option nounput
+%option noinput
+%option outfile="command_lex.c"
+
+%%
+[ /t] /* ignore whitespace */;
+{WORD} {yylval.string = strdup(yytext); return WORD;}
+{IPV4} {yylval.string = strdup(yytext); return IPV4;}
+{IPV4_PREFIX} {yylval.string = strdup(yytext); return IPV4_PREFIX;}
+{IPV6} {yylval.string = strdup(yytext); return IPV6;}
+{IPV6_PREFIX} {yylval.string = strdup(yytext); return IPV6_PREFIX;}
+{VARIABLE} {yylval.string = strdup(yytext); return VARIABLE;}
+{NUMBER} {yylval.integer = atoi(yytext); return NUMBER;}
+{RANGE} {yylval.string = strdup(yytext); return RANGE;}
+. {return yytext[0];}
+%%
+
+void
+set_buffer_string(const char *string)
+{
+ yy_scan_string(string);
+}
--- /dev/null
+%{
+#include "cmdtree.h"
+
+extern int yylex(void);
+extern void yyerror(const char *);
+extern int cmd_parse_format(const char *, const char *);
+extern void set_buffer_string(const char *);
+
+// compile with debugging facilities
+#define YYDEBUG 1
+%}
+
+%union{
+ int integer;
+ char *string;
+ struct graph_node *node;
+}
+
+%{
+// last top-level node
+struct graph_node *topnode, // command root node
+ *currnode; // current node
+
+struct graph_node *optnode_start, // start node for option set
+ *optnode_end, // end node for option set
+ *optnode_el; // start node for an option set element
+
+struct graph_node *selnode_start, // start node for selector set
+ *selnode_end, // end node for selector set
+ *selnode_el; // start node for an selector set element
+%}
+
+%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> 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
+
+%defines "command_parse.h"
+%output "command_parse.c"
+
+/* grammar proper */
+%%
+
+start: sentence_root
+ cmd_token_seq;
+
+sentence_root: WORD
+ {
+ currnode = new_node(WORD_GN);
+ currnode->is_root = 1;
+ add_node(topnode, currnode);
+ };
+
+/* valid top level tokens */
+cmd_token:
+ placeholder_token
+ { currnode = add_node(currnode, $1); }
+| literal_token
+ { currnode = add_node(currnode, $1); }
+| selector
+ {
+ add_node(currnode, selnode_start);
+ currnode = selnode_end;
+ }
+| option
+ {
+ add_node(currnode, optnode_start);
+ currnode = optnode_end;
+ }
+;
+
+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 '>'
+{
+ $$ = new_node(SELECTOR_GN);
+ // attach subtree here
+};
+
+selector_part:
+ selector_part '|' selector_element
+| selector_element
+;
+
+selector_element:
+ WORD selector_token_seq;
+
+selector_token_seq:
+ %empty {$$ = NULL;}
+| selector_token_seq selector_token
+{
+ currnode = add_node(currnode, $2);
+}
+;
+
+selector_token:
+ literal_token
+| placeholder_token
+| option
+;
+
+/* [option|set] productions */
+option: '[' option_part ']'
+{
+ $$ = new_node(OPTION_GN);
+ // attach subtree here
+};
+
+option_part:
+ option_part '|' option_token_seq
+| option_token_seq
+;
+
+option_token_seq:
+ option_token_seq option_token
+| option_token
+{
+ printf("Matched singular option token in sequence, type: %d\n", $1->type);
+}
+;
+
+option_token:
+ literal_token
+{
+ // optnode_el points to root of option element
+ if (optnode_el == NULL) {
+ optnode_el = $1;
+ currnode = $1;
+ }
+ else
+ add_node(currnode, $1);
+}
+| placeholder_token
+{
+ // optnode_el points to root of option element
+ if (optnode_el == NULL) {
+ optnode_el = $1;
+ currnode = $1;
+ }
+ else
+ add_node(currnode, $1);
+}
+;
+
+%%
+
+int
+main (void)
+{
+ 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)
+{
+ // make flex read from a string
+ set_buffer_string(string);
+ // initialize the start node of this command dfa
+ topnode = new_node(NUL_GN);
+ // parse command into DFA
+ yyparse();
+ // topnode points to command DFA
+ return 0;
+}