mariadb/storage/xtradb/fts/fts0pars.y
2015-05-04 19:15:28 +02:00

294 lines
5.7 KiB
Text

/*****************************************************************************
Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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; version 2 of the License.
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 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, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/**
* @file fts/fts0pars.y
* FTS parser: input file for the GNU Bison parser generator
*
* Created 2007/5/9 Sunny Bains
*/
%{
#include "mem0mem.h"
#include "fts0ast.h"
#include "fts0blex.h"
#include "fts0tlex.h"
#include "fts0pars.h"
extern int fts_lexer(YYSTYPE*, fts_lexer_t*);
extern int fts_blexer(YYSTYPE*, yyscan_t);
extern int fts_tlexer(YYSTYPE*, yyscan_t);
typedef int (*fts_scan)();
extern int ftserror(const char* p);
/* Required for reentrant parser */
#define ftslex fts_lexer
#define YYERROR_VERBOSE
/* For passing an argument to yyparse() */
#define YYPARSE_PARAM state
#define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer
typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
typedef int (*fts_scanner)();
struct fts_lexer_struct {
fts_scanner scanner;
void* yyscanner;
};
%}
%union {
int oper;
fts_ast_string_t* token;
fts_ast_node_t* node;
};
/* Enable re-entrant parser */
%pure_parser
%token<oper> FTS_OPER
%token<token> FTS_TEXT FTS_TERM FTS_NUMB
%type<node> prefix term text expr sub_expr expr_lst query
%nonassoc '+' '-' '~' '<' '>'
%%
query : expr_lst {
$$ = $1;
((fts_ast_state_t*) state)->root = $$;
}
;
expr_lst: /* Empty */ {
$$ = NULL;
}
| expr_lst expr {
$$ = $1;
if (!$$) {
$$ = fts_ast_create_node_list(state, $2);
} else {
fts_ast_add_node($$, $2);
}
}
| expr_lst sub_expr {
$$ = $1;
$$ = fts_ast_create_node_list(state, $1);
if (!$$) {
$$ = $2;
} else {
fts_ast_add_node($$, $2);
}
}
;
sub_expr: '(' expr_lst ')' {
$$ = $2;
if ($$) {
$$ = fts_ast_create_node_subexp_list(state, $$);
}
}
| prefix '(' expr_lst ')' {
$$ = fts_ast_create_node_list(state, $1);
if ($3) {
fts_ast_add_node($$,
fts_ast_create_node_subexp_list(state, $3));
}
}
;
expr : term {
$$ = $1;
}
| text {
$$ = $1;
}
| term '*' {
fts_ast_term_set_wildcard($1);
}
| text '@' FTS_NUMB {
fts_ast_term_set_distance($1, fts_ast_string_to_ul($3, 10));
fts_ast_string_free($3);
}
| prefix term '*' {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
fts_ast_term_set_wildcard($2);
}
| prefix term {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
}
| prefix text '@' FTS_NUMB {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
fts_ast_term_set_distance($2, fts_ast_string_to_ul($4, 10));
fts_ast_string_free($4);
}
| prefix text {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
}
;
prefix : '-' {
$$ = fts_ast_create_node_oper(state, FTS_IGNORE);
}
| '+' {
$$ = fts_ast_create_node_oper(state, FTS_EXIST);
}
| '~' {
$$ = fts_ast_create_node_oper(state, FTS_NEGATE);
}
| '<' {
$$ = fts_ast_create_node_oper(state, FTS_DECR_RATING);
}
| '>' {
$$ = fts_ast_create_node_oper(state, FTS_INCR_RATING);
}
;
term : FTS_TERM {
$$ = fts_ast_create_node_term(state, $1);
fts_ast_string_free($1);
}
| FTS_NUMB {
$$ = fts_ast_create_node_term(state, $1);
fts_ast_string_free($1);
}
/* Ignore leading '*' */
| '*' term {
$$ = $2;
}
;
text : FTS_TEXT {
$$ = fts_ast_create_node_text(state, $1);
fts_ast_string_free($1);
}
;
%%
/********************************************************************
*/
int
ftserror(
/*=====*/
const char* p)
{
fprintf(stderr, "%s\n", p);
return(0);
}
/********************************************************************
Create a fts_lexer_t instance.*/
fts_lexer_t*
fts_lexer_create(
/*=============*/
ibool boolean_mode,
const byte* query,
ulint query_len)
{
fts_lexer_t* fts_lexer = static_cast<fts_lexer_t*>(
ut_malloc(sizeof(fts_lexer_t)));
if (boolean_mode) {
fts0blex_init(&fts_lexer->yyscanner);
fts0b_scan_bytes((char*) query, query_len, fts_lexer->yyscanner);
fts_lexer->scanner = (fts_scan) fts_blexer;
/* FIXME: Debugging */
/* fts0bset_debug(1 , fts_lexer->yyscanner); */
} else {
fts0tlex_init(&fts_lexer->yyscanner);
fts0t_scan_bytes((char*) query, query_len, fts_lexer->yyscanner);
fts_lexer->scanner = (fts_scan) fts_tlexer;
}
return(fts_lexer);
}
/********************************************************************
Free an fts_lexer_t instance.*/
void
fts_lexer_free(
/*===========*/
fts_lexer_t* fts_lexer)
{
if (fts_lexer->scanner == (fts_scan) fts_blexer) {
fts0blex_destroy(fts_lexer->yyscanner);
} else {
fts0tlex_destroy(fts_lexer->yyscanner);
}
ut_free(fts_lexer);
}
/********************************************************************
Call the appropaiate scanner.*/
int
fts_lexer(
/*======*/
YYSTYPE* val,
fts_lexer_t* fts_lexer)
{
fts_scanner_alt func_ptr;
func_ptr = (fts_scanner_alt) fts_lexer->scanner;
return(func_ptr(val, fts_lexer->yyscanner));
}
/********************************************************************
Parse the query.*/
int
fts_parse(
/*======*/
fts_ast_state_t* state)
{
return(ftsparse(state));
}