/* search-parser.l - Parser for search criteria strings.
 *
 * Copyright (C) 2005, 2007  Oskar Liljeblad
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

%{

#include <config.h>
#include <stdbool.h>		/* Gnulib/C99 */
#include "xalloc.h"		/* Gnulib */
#include "gmediaserver.h"
#include "search-parser.h"
#include "search-lexer.h"

static void
yyerror(yyscan_t scanner, SearchCriteriaParseData *data, const char *error)
{
    data->error = error;
}

/* XXX: disabled %name-prefix="search_criteria_" */
%}

%defines
%pure-parser
%lex-param { yyscan_t scanner }
%parse-param { yyscan_t scanner }
%parse-param { SearchCriteriaParseData *data }

%union{
    char *str;
    int token;
    SearchExpr *expr;
    SearchCriteria *criteria;
    bool boolval;
}

%token T_EXISTS
%token <boolval> T_TRUE T_FALSE
%token <str> T_STRING T_PROPERTY
%left <token> T_EQ T_NE T_LT T_LE T_GT T_GE T_CONTAINS T_DOES_NOT_CONTAIN T_DERIVED_FROM
%left <token> T_OR
%left <token> T_AND
%type <criteria> input
%type <expr> search_expr
%type <token> binop
%type <boolval> boolval

%destructor { free($$); } T_STRING T_PROPERTY
%destructor { free_search_expr($$); } search_expr
/* %destructor { free_search_criteria($$); } input */ /* don't free the input! */

%%

input:		  '*'
		  {
		    $$ = xmalloc(sizeof(SearchCriteria));
		    $$->expr = NULL;
		    data->criteria = $$;
		  }
		| search_expr
		  {
		    $$ = xmalloc(sizeof(SearchCriteria));
		    $$->expr = $1;
		    data->criteria = $$;
		  }
		;

search_expr:	  '(' search_expr ')'
		  {
		    $$ = $2;
		  }
		| search_expr T_AND search_expr
		  {
		    $$ = xmalloc(sizeof(SearchExpr));
		    $$->type = T_AND;
		    $$->u.logical.expr1 = $1;
		    $$->u.logical.expr2 = $3;
		  }
		| search_expr T_OR search_expr
		  {
		    $$ = xmalloc(sizeof(SearchExpr));
		    $$->type = T_OR;
		    $$->u.logical.expr1 = $1;
		    $$->u.logical.expr2 = $3;
		  }
		| T_PROPERTY binop T_STRING
		  {
		    $$ = xmalloc(sizeof(SearchExpr));
		    $$->type = $2;
		    $$->u.binary.property = $1;
		    $$->u.binary.value = $3;
		  }
		| T_PROPERTY T_EXISTS boolval
		  {
		    $$ = xmalloc(sizeof(SearchExpr));
		    $$->type = T_EXISTS;
		    $$->u.exists.property = $1;
		    $$->u.exists.must_exist = $3;
		  }
		;

binop:		  T_EQ 			{ $$ = T_EQ; }
		| T_NE			{ $$ = T_NE; }
		| T_LT			{ $$ = T_LT; }
		| T_LE			{ $$ = T_LE; }
		| T_GT			{ $$ = T_GT; }
		| T_GE			{ $$ = T_GE; }
		| T_CONTAINS		{ $$ = T_CONTAINS; }
		| T_DOES_NOT_CONTAIN	{ $$ = T_DOES_NOT_CONTAIN; }
		| T_DERIVED_FROM	{ $$ = T_DERIVED_FROM; }
		;

boolval:	  T_FALSE		{ $$ = false; }
		| T_TRUE		{ $$ = true; }
		;

%%
