mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
294 lines
5.7 KiB
Text
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));
|
|
}
|