badvpn/predicate/BPredicate.y
2012-07-24 10:26:30 +00:00

346 lines
6.9 KiB
Plaintext

/**
* @file BPredicate.y
* @author Ambroz Bizjak <ambrop7@gmail.com>
*
* @section LICENSE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS 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 AUTHOR 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.
*
* @section DESCRIPTION
*
* {@link BPredicate} grammar file.
*/
%{
#include <stdlib.h>
#include <predicate/BPredicate_internal.h>
#include <predicate/BPredicate_parser.h>
#define YYLEX_PARAM scanner
static struct predicate_node * make_constant (int val)
{
struct predicate_node *n = (struct predicate_node *)malloc(sizeof(*n));
if (!n) {
return NULL;
}
n->type = NODE_CONSTANT;
n->constant.val = val;
return n;
}
static struct predicate_node * make_negation (struct predicate_node *op)
{
if (!op) {
goto fail;
}
struct predicate_node *n = (struct predicate_node *)malloc(sizeof(*n));
if (!n) {
goto fail;
}
n->type = NODE_NEG;
n->neg.op = op;
return n;
fail:
if (op) {
free_predicate_node(op);
}
return NULL;
}
static struct predicate_node * make_conjunction (struct predicate_node *op1, struct predicate_node *op2)
{
if (!op1 || !op2) {
goto fail;
}
struct predicate_node *n = (struct predicate_node *)malloc(sizeof(*n));
if (!n) {
goto fail;
}
n->type = NODE_CONJUNCT;
n->conjunct.op1 = op1;
n->conjunct.op2 = op2;
return n;
fail:
if (op1) {
free_predicate_node(op1);
}
if (op2) {
free_predicate_node(op2);
}
return NULL;
}
static struct predicate_node * make_disjunction (struct predicate_node *op1, struct predicate_node *op2)
{
if (!op1 || !op2) {
goto fail;
}
struct predicate_node *n = (struct predicate_node *)malloc(sizeof(*n));
if (!n) {
goto fail;
}
n->type = NODE_DISJUNCT;
n->disjunct.op1 = op1;
n->disjunct.op2 = op2;
return n;
fail:
if (op1) {
free_predicate_node(op1);
}
if (op2) {
free_predicate_node(op2);
}
return NULL;
}
static struct predicate_node * make_function (char *name, struct arguments_node *args, int need_args)
{
if (!name || (!args && need_args)) {
goto fail;
}
struct predicate_node *n = (struct predicate_node *)malloc(sizeof(*n));
if (!n) {
goto fail;
}
n->type = NODE_FUNCTION;
n->function.name = name;
n->function.args = args;
return n;
fail:
if (name) {
free(name);
}
if (args) {
free_arguments_node(args);
}
return NULL;
}
static struct arguments_node * make_arguments (struct arguments_arg arg, struct arguments_node *next, int need_next)
{
if (arg.type == ARGUMENT_INVALID || (!next && need_next)) {
goto fail;
}
struct arguments_node *n = (struct arguments_node *)malloc(sizeof(*n));
if (!n) {
goto fail;
}
n->arg = arg;
n->next = next;
return n;
fail:
free_argument(arg);
if (next) {
free_arguments_node(next);
}
return NULL;
}
static struct arguments_arg make_argument_predicate (struct predicate_node *pr)
{
struct arguments_arg ret;
if (!pr) {
goto fail;
}
ret.type = ARGUMENT_PREDICATE;
ret.predicate = pr;
return ret;
fail:
ret.type = ARGUMENT_INVALID;
return ret;
}
static struct arguments_arg make_argument_string (char *string)
{
struct arguments_arg ret;
if (!string) {
goto fail;
}
ret.type = ARGUMENT_STRING;
ret.string = string;
return ret;
fail:
ret.type = ARGUMENT_INVALID;
return ret;
}
%}
%pure-parser
%locations
%parse-param {void *scanner}
%parse-param {struct predicate_node **result}
%union {
char *text;
struct predicate_node *node;
struct arguments_node *arg_node;
struct predicate_node nfaw;
struct arguments_arg arg_arg;
};
// token types
%token <text> STRING NAME
%token PEER1_NAME PEER2_NAME AND OR NOT SPAR EPAR CONSTANT_TRUE CONSTANT_FALSE COMMA
// string token destructor
%destructor {
free($$);
} STRING NAME
// return values
%type <node> predicate constant parentheses neg conjunct disjunct function
%type <arg_node> arguments
%type <arg_arg> argument
// predicate node destructor
%destructor {
if ($$) {
free_predicate_node($$);
}
} predicate constant parentheses neg conjunct disjunct function
// argument node destructor
%destructor {
if ($$) {
free_arguments_node($$);
}
} arguments
// argument argument destructor
%destructor {
free_argument($$);
} argument
%left OR
%left AND
%nonassoc NOT
%right COMMA
%%
input:
predicate {
*result = $1;
}
;
predicate: constant | parentheses | neg | conjunct | disjunct | function;
constant:
CONSTANT_TRUE {
$$ = make_constant(1);
}
|
CONSTANT_FALSE {
$$ = make_constant(0);
}
;
parentheses:
SPAR predicate EPAR {
$$ = $2;
}
;
neg:
NOT predicate {
$$ = make_negation($2);
}
;
conjunct:
predicate AND predicate {
$$ = make_conjunction($1, $3);
}
;
disjunct:
predicate OR predicate {
$$ = make_disjunction($1, $3);
}
;
function:
NAME SPAR EPAR {
$$ = make_function($1, NULL, 0);
}
|
NAME SPAR arguments EPAR {
$$ = make_function($1, $3, 1);
}
;
arguments:
argument {
$$ = make_arguments($1, NULL, 0);
}
|
argument COMMA arguments {
$$ = make_arguments($1, $3, 1);
}
;
argument:
predicate {
$$ = make_argument_predicate($1);
}
|
STRING {
$$ = make_argument_string($1);
}
;