%{ /* ** OSSP cfg - Configuration Parsing ** Copyright (c) 1999-2002 Ralf S. Engelschall ** Copyright (c) 1999-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP cfg, a configuration parsing ** library which can be found at http://www.ossp.org/pkg/lib/cfg/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** cfg_syn_parse.y: context free grammar specification for GNU Bison ** ** ATTENTION: This requires GNU Bison 1.30 or newer! */ #include #include #include "cfg.h" #include "cfg_syn.h" /* make sure yyparse() accepts a context pointer and passes through its inlined scanner context to yylex() */ #define CTX ((cfg_syn_ctx_t *)ctx) #define YYPARSE_PARAM ctx #define YYLEX_PARAM CTX->yyscan /* provide an explicit prototype for the yylex() function but use "void *" instead of correct type because at this point in the generation process we have the types still not available */ extern int yylex(/*YYSTYPE*/ void *lvalp, /*YYLTYPE*/ void *llocp, cfg_syn_ctx_t *ctx); /* generate verbose error messages and remember them inside the context */ #undef yyerror #define yyerror(msg) \ cfg_syn_error(CTX, CFG_ERR_SYN, &yylloc, msg) #define YYERROR_VERBOSE /* scanner state transition */ extern void cfg_syn_scan_push(cfg_syn_ctx_t *, const char *state); extern void cfg_syn_scan_pop(cfg_syn_ctx_t *); %} /* parser options */ %pure_parser %locations %defines /* the YYSTYPE: parser token value */ %union { char *cpString; cfg_node_t *npNode; } /* assign YYSTYPE elements to parser rules */ %type sequence %type directives %type directive %type tokens %type token %type string /* list of scanner tokens */ %token T_SEP %token T_OPEN %token T_CLOSE %token T_STRING /* operator association */ %right T_SEP %right T_OPEN %right T_CLOSE /* grammar start rule (technically redundant but explicit to be sure) */ %start configuration %% configuration : sequence { CTX->node = $1; } ; sequence : directives { cfg_node_t *n; cfg_node_create(&n); cfg_node_set(n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_SEQ); cfg_node_set(n, CFG_NODE_ATTR_CHILD1, $1); $$ = n; } ; directives : /* empty */ { $$ = NULL; } | directive { $$ = $1; } | directive T_SEP directives { cfg_node_set($1, CFG_NODE_ATTR_RBROTH, $3); $$ = $1; } ; directive : tokens { cfg_node_t *n; cfg_node_create(&n); cfg_node_set(n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_DIR); cfg_node_set(n, CFG_NODE_ATTR_CHILD1, $1); $$ = n; } ; tokens : token { $$ = $1; } | token tokens { cfg_node_set($1, CFG_NODE_ATTR_RBROTH, $2); $$ = $1; } ; token : T_OPEN sequence T_CLOSE { $$ = $2; } | string { $$ = $1; } ; string : T_STRING { cfg_node_t *n; cfg_node_create(&n); cfg_node_set(n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_TOK); cfg_node_set(n, CFG_NODE_ATTR_TOKEN, $1); $$ = n; } ; %%