summaryrefslogtreecommitdiffstats
path: root/lib/command_parse.y
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2016-11-16 07:03:51 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2016-12-01 18:45:27 +0100
commite9484f70b21ed49d0ca6dbf2899b3a6306ffd2e9 (patch)
tree1148e8457c5599449c13d7b7a012d9f16af8e3da /lib/command_parse.y
parentlib: parser: wrap state in struct parser_ctx (diff)
downloadfrr-e9484f70b21ed49d0ca6dbf2899b3a6306ffd2e9.tar.xz
frr-e9484f70b21ed49d0ca6dbf2899b3a6306ffd2e9.zip
lib: parser: use reentrant mode on flex & bison
This removes remaining global variables from the lexer, pushing the lexer state into struct parser_ctx too. At the same time, "cmd_yy" is used as prefix for all parser & lexer routines. The result is that (a) there is no collision anymore if a program uses flex/bison and links libzebra, and (b) the parser is fully encapsulated and could be called in parallel from multiple threads. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib/command_parse.y')
-rw-r--r--lib/command_parse.y50
1 files changed, 29 insertions, 21 deletions
diff --git a/lib/command_parse.y b/lib/command_parse.y
index aac4a7466..d084ddd73 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -23,10 +23,18 @@
*/
%{
+
+typedef union CMD_YYSTYPE CMD_YYSTYPE;
+#define YYSTYPE CMD_YYSTYPE
+#include "command_lex.h"
+
// compile with debugging facilities
#define YYDEBUG 1
%}
+%define api.pure full
+%define api.prefix {cmd_yy}
+
/* names for generated header and parser files */
%defines "command_parse.h"
%output "command_parse.c"
@@ -39,16 +47,9 @@
#include "log.h"
#include "graph.h"
- extern int
- yylex (void);
-
- extern void
- set_lexer_string (const char *);
-
- extern void
- cleanup_lexer (void);
-
struct parser_ctx {
+ yyscan_t scanner;
+
struct cmd_element *el;
struct graph *graph;
@@ -61,7 +62,6 @@
/* functionality this unit exports */
%code provides {
-
/* maximum length of a number, lexer will not match anything longer */
#define DECIMAL_STRLEN_MAX 20
}
@@ -99,9 +99,13 @@
%type <subgraph> compound_token
%code {
+
+ extern void set_lexer_string (yyscan_t *scn, const char *string);
+ extern void cleanup_lexer (yyscan_t *scn);
+
/* bison declarations */
void
- yyerror (struct parser_ctx *ctx, char const *msg);
+ cmd_yyerror (struct parser_ctx *ctx, char const *msg);
/* subgraph semantic value */
struct subgraph {
@@ -133,10 +137,13 @@
static void
cleanup (struct parser_ctx *ctx);
+
+ #define scanner ctx->scanner
}
/* yyparse parameters */
-%parse-param { struct parser_ctx *ctx }
+%lex-param {yyscan_t scanner}
+%parse-param {struct parser_ctx *ctx}
/* called automatically before yyparse */
%initial-action {
@@ -145,9 +152,6 @@
ctx->startnode = vector_slot (ctx->graph->nodes, 0);
- /* set string to parse */
- set_lexer_string (ctx->el->string);
-
/* copy docstring and keep a pointer to the copy */
if (ctx->el->doc)
{
@@ -272,7 +276,7 @@ placeholder_token:
token->max = strtoll (yylval.string, &yylval.string, 10);
// validate range
- if (token->min > token->max) yyerror (ctx, "Invalid range.");
+ if (token->min > token->max) cmd_yyerror (ctx, "Invalid range.");
free ($1);
}
@@ -399,6 +403,8 @@ option_token:
%%
+#undef scanner
+
void
command_parse_format (struct graph *graph, struct cmd_element *cmd)
{
@@ -407,8 +413,13 @@ command_parse_format (struct graph *graph, struct cmd_element *cmd)
// set to 1 to enable parser traces
yydebug = 0;
+ set_lexer_string (&ctx.scanner, cmd->string);
+
// parse command into DFA
- yyparse (&ctx);
+ cmd_yyparse (&ctx);
+
+ /* cleanup lexer */
+ cleanup_lexer (&ctx.scanner);
// cleanup
cleanup (&ctx);
@@ -430,9 +441,6 @@ cleanup (struct parser_ctx *ctx)
/* free resources */
free (ctx->docstr_start);
- /* cleanup lexer */
- cleanup_lexer ();
-
/* clear state pointers */
ctx->currnode = NULL;
ctx->docstr_start = ctx->docstr = NULL;
@@ -453,7 +461,7 @@ terminate_graph (struct parser_ctx *ctx, struct graph_node *finalnode)
graph_new_node (ctx->graph, element, (void (*)(void *)) &del_cmd_element);
if (node_adjacent (finalnode, end_token_node))
- yyerror (ctx, "Duplicate command.");
+ cmd_yyerror (ctx, "Duplicate command.");
graph_add_edge (finalnode, end_token_node);
graph_add_edge (end_token_node, end_element_node);