346 lines
6.9 KiB
Plaintext
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);
|
||
|
}
|
||
|
;
|