ossp-pkg/cfg/cfg_syn_parse.y
%{
/*
** OSSP cfg - Configuration Parsing
** Copyright (c) 2002-2006 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 2002-2006 The OSSP Project (http://www.ossp.org/)
**
** 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.875 or newer!
*/
#include <stdio.h>
#include <stdlib.h>
#include "cfg.h"
#include "cfg_global.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, "%s", msg)
/* 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 */
%error-verbose
%pure_parser
%locations
%defines
/* the YYSTYPE: parser token value */
%union {
char *cpString;
cfg_node_t *npNode;
}
/* assign YYSTYPE elements to parser rules */
%type <npNode> sequence
%type <npNode> directives
%type <npNode> directive
%type <npNode> tokens
%type <npNode> token
%type <npNode> string
/* list of scanner tokens */
%token T_SEP
%token T_OPEN
%token T_CLOSE
%token <cpString> 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(CTX->cfg, &n);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_SEQ);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_CHILD1, $1);
$$ = n;
}
;
directives
: /* empty */ {
$$ = NULL;
}
| directive {
$$ = $1;
}
| directive T_SEP directives {
cfg_node_set(CTX->cfg, $1, CFG_NODE_ATTR_RBROTH, $3);
$$ = $1;
}
;
directive
: tokens {
cfg_node_t *n;
cfg_node_create(CTX->cfg, &n);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_DIR);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_CHILD1, $1);
$$ = n;
}
;
tokens
: token {
$$ = $1;
}
| token tokens {
cfg_node_set(CTX->cfg, $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(CTX->cfg, &n);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_ARG);
cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TOKEN|CFG_ATTR_GIFT, $1);
$$ = n;
}
;
%%