lib: Add docstring support

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
Quentin Young 2016-08-05 16:41:42 +00:00
parent 39fb395f7d
commit 0aa2c2ff01
3 changed files with 61 additions and 4 deletions

View File

@ -27,7 +27,8 @@ struct graph_node
vector children; // this node's children vector children; // this node's children
struct graph_node * end; // pointer to end for SELECTOR_GN & OPTION_GN struct graph_node * end; // pointer to end for SELECTOR_GN & OPTION_GN
char* text; // for WORD_GN and VARIABLE_GN char *text; // original format text
char *doc; // docstring for this node
long long value; // for NUMBER_GN long long value; // for NUMBER_GN
long long min, max; // for RANGE_GN long long min, max; // for RANGE_GN

View File

@ -15,6 +15,8 @@ struct graph_node *
node_exists(struct graph_node *, struct graph_node *); node_exists(struct graph_node *, struct graph_node *);
struct graph_node * struct graph_node *
node_replace(struct graph_node *, struct graph_node *); node_replace(struct graph_node *, struct graph_node *);
char *
doc_next(void);
#define DECIMAL_STRLEN_MAX 20 #define DECIMAL_STRLEN_MAX 20
@ -55,6 +57,7 @@ struct graph_node *selnode_start, // start node for selector set
*selnode_end; // end node for selector set *selnode_end; // end node for selector set
struct cmd_element *command; // command we're parsing struct cmd_element *command; // command we're parsing
char *docstring;
%} %}
%token <string> WORD %token <string> WORD
@ -128,6 +131,7 @@ sentence_root: WORD
{ {
struct graph_node *root = new_node(WORD_GN); struct graph_node *root = new_node(WORD_GN);
root->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); root->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
root->doc = doc_next();
if ((currnode = node_replace(startnode, root)) != root) if ((currnode = node_replace(startnode, root)) != root)
free (root); free (root);
@ -173,36 +177,42 @@ placeholder_token:
{ {
$$ = new_node(IPV4_GN); $$ = new_node(IPV4_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| IPV4_PREFIX | IPV4_PREFIX
{ {
$$ = new_node(IPV4_PREFIX_GN); $$ = new_node(IPV4_PREFIX_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| IPV6 | IPV6
{ {
$$ = new_node(IPV6_GN); $$ = new_node(IPV6_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| IPV6_PREFIX | IPV6_PREFIX
{ {
$$ = new_node(IPV6_PREFIX_GN); $$ = new_node(IPV6_PREFIX_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| VARIABLE | VARIABLE
{ {
$$ = new_node(VARIABLE_GN); $$ = new_node(VARIABLE_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| RANGE | RANGE
{ {
$$ = new_node(RANGE_GN); $$ = new_node(RANGE_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
// get the numbers out // get the numbers out
yylval.string++; yylval.string++;
@ -222,12 +232,16 @@ literal_token:
{ {
$$ = new_node(WORD_GN); $$ = new_node(WORD_GN);
$$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1); $$->text = XSTRDUP(MTYPE_CMD_TOKENS, $1);
$$->doc = doc_next();
free ($1); free ($1);
} }
| NUMBER | NUMBER
{ {
$$ = new_node(NUMBER_GN); $$ = new_node(NUMBER_GN);
$$->value = yylval.integer; $$->value = yylval.integer;
$$->text = XCALLOC(MTYPE_CMD_TOKENS, DECIMAL_STRLEN_MAX+1);
snprintf($$->text, DECIMAL_STRLEN_MAX, "%lld", $$->value);
$$->doc = doc_next();
} }
; ;
@ -354,12 +368,17 @@ parse_command_format(struct graph_node *start, struct cmd_element *cmd)
// trace parser // trace parser
yydebug = 0; yydebug = 0;
// command string // command element
command = cmd; command = cmd;
// copy docstring and keep a pointer to the copy
char *doc = docstring = cmd->doc ? XSTRDUP(MTYPE_TMP, cmd->doc) : NULL;
// make flex read from a string // make flex read from a string
set_buffer_string(command->string); set_buffer_string(command->string);
// parse command into DFA // parse command into DFA
yyparse(); yyparse();
// cleanup
free (doc);
doc = NULL;
// startnode points to command DFA // startnode points to command DFA
return startnode; return startnode;
} }
@ -386,3 +405,12 @@ node_replace(struct graph_node *parent, struct graph_node *child)
return existing; return existing;
} }
char *
doc_next()
{
char *piece = NULL;
if (!docstring || !(piece = strsep(&docstring, "\n")))
return NULL;
return XSTRDUP(MTYPE_CMD_TOKENS, piece);
}

View File

@ -24,6 +24,33 @@ DEFUN (grammar_test,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (grammar_test_doc,
grammar_test_doc_cmd,
"grammar test docstring",
GRAMMAR_STR
"Test function for docstring\n"
"Command end\n")
{
struct cmd_element *cmd = malloc(sizeof(struct cmd_element));
cmd->string = "test docstring <example|selector follow> (1-255) end VARIABLE [OPTION|set lol] . VARARG";
cmd->doc = "Test stuff\n"
"docstring thing\n"
"first example\n"
"second example\n"
"follow\n"
"random range\n"
"end thingy\n"
"variable\n"
"optional variable\n"
"optional set\n"
"optional lol\n"
"vararg!\n";
cmd->func = NULL;
cmd->tokens = vector_init(VECTOR_MIN_SIZE);
parse_command_format(nodegraph, cmd);
return CMD_SUCCESS;
}
DEFUN (grammar_test_show, DEFUN (grammar_test_show,
grammar_test_show_cmd, grammar_test_show_cmd,
"grammar tree", "grammar tree",
@ -52,7 +79,7 @@ DEFUN (grammar_test_complete,
else else
{ {
fprintf(stderr, "%% Matched full input, possible completions:\n"); fprintf(stderr, "%% Matched full input, possible completions:\n");
char* desc = malloc(50); char* desc = malloc(30);
struct listnode *node; struct listnode *node;
struct graph_node *cnode; struct graph_node *cnode;
// print possible next hops, if any // print possible next hops, if any
@ -60,7 +87,7 @@ DEFUN (grammar_test_complete,
if (cnode->type == END_GN) if (cnode->type == END_GN)
fprintf(stderr, "<cr> %p\n", cnode->element->func); fprintf(stderr, "<cr> %p\n", cnode->element->func);
else else
fprintf(stderr, "%s\n", describe_node(cnode, desc, 50)); fprintf(stderr, "%-30s%s\n", describe_node(cnode, desc, 30), cnode->doc);
} }
free(desc); free(desc);
} }
@ -118,4 +145,5 @@ void grammar_sandbox_init() {
install_element (ENABLE_NODE, &grammar_test_show_cmd); install_element (ENABLE_NODE, &grammar_test_show_cmd);
install_element (ENABLE_NODE, &grammar_test_match_cmd); install_element (ENABLE_NODE, &grammar_test_match_cmd);
install_element (ENABLE_NODE, &grammar_test_complete_cmd); install_element (ENABLE_NODE, &grammar_test_complete_cmd);
install_element (ENABLE_NODE, &grammar_test_doc_cmd);
} }