Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgssqlstatementlexer.ll 3 : : -------------------- 4 : : begin : April 2016 5 : : copyright : (C) 2011 by Martin Dobias 6 : : copyright : (C) 2016 by Even Rouault 7 : : email : even.rouault at spatialys.com 8 : : *************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : 17 : : %option noyywrap 18 : : %option case-insensitive 19 : : %option never-interactive 20 : : %option nounput 21 : : %option prefix="sqlstatement_" 22 : : // this makes flex generate lexer with context + init/destroy functions 23 : : %option reentrant 24 : : // this makes Bison send yylex another argument to use instead of using the global variable yylval 25 : : %option bison-bridge 26 : : 27 : : // ensure that lexer will be 8-bit (and not just 7-bit) 28 : : %option 8bit 29 : : 30 : : %{ 31 : : 32 : : #include "qgssqlstatement.h" 33 : : struct sqlstatement_parser_context; 34 : : #include "qgssqlstatementparser.hpp" 35 : : #include <QLocale> 36 : : 37 : : // if not defined, searches for isatty() 38 : : // which doesn't in MSVC compiler 39 : : #define YY_NEVER_INTERACTIVE 1 40 : : 41 : : #ifndef YY_NO_UNPUT 42 : : #define YY_NO_UNPUT // unused 43 : : #endif 44 : : 45 : : #ifdef _MSC_VER 46 : : #define YY_NO_UNISTD_H 47 : : #endif 48 : : 49 : : #define B_OP(x) yylval->b_op = QgsSQLStatement::x 50 : : #define U_OP(x) yylval->u_op = QgsSQLStatement::x 51 : : #define TEXT yylval->text = new QString( QString::fromUtf8(yytext) ); 52 : : #define TEXT_FILTER(filter_fn) yylval->text = new QString( filter_fn( QString::fromUtf8(yytext) ) ); 53 : : 54 : 0 : static QString stripText(QString text) 55 : : { 56 : : // strip single quotes on start,end 57 : 0 : text = text.mid( 1, text.length() - 2 ); 58 : : 59 : : // make single "single quotes" from double "single quotes" 60 : 0 : text.replace( "''", "'" ); 61 : : 62 : : // strip \n \' etc. 63 : 0 : int index = 0; 64 : 0 : while (( index = text.indexOf( '\\', index ) ) != -1 ) 65 : : { 66 : 0 : text.remove( index, 1 ); // delete backslash 67 : 0 : QChar chr; 68 : 0 : switch ( text[index].toLatin1() ) // evaluate backslashed character 69 : : { 70 : 0 : case 'n': chr = '\n'; break; 71 : 0 : case 't': chr = '\t'; break; 72 : 0 : case '\\': chr = '\\'; break; 73 : 0 : case '\'': chr = '\''; break; 74 : 0 : default: chr = '?'; break; 75 : : } 76 : 0 : text[index++] = chr; // set new character and push index +1 77 : : } 78 : 0 : return text; 79 : 0 : } 80 : : 81 : : // C locale for correct parsing of numbers even if the system locale is different 82 : 0 : Q_GLOBAL_STATIC_WITH_ARGS(QLocale, cLocale, ("C") ) 83 : : 84 : : %} 85 : : 86 : : white [ \t\r\n]+ 87 : : 88 : : non_ascii [\x80-\xFF] 89 : : 90 : : identifier_first [A-Za-z_]|{non_ascii} 91 : : identifier_next [A-Za-z0-9_]|{non_ascii} 92 : : identifier {identifier_first}{identifier_next}* 93 : : 94 : : identifier_str_char "\"\""|[^\"] 95 : : identifier_quoted "\""{identifier_str_char}*"\"" 96 : : 97 : : ms_identifier_quoted "\["[^.]*"\]" 98 : : 99 : : dig [0-9] 100 : : num_int [-]?{dig}+{identifier_first}* 101 : : num_float [-]?{dig}*(\.{dig}+([eE][-+]?{dig}+)?|[eE][-+]?{dig}+) 102 : : boolean "TRUE"|"FALSE" 103 : : 104 : : str_char ('')|(\\.)|[^'\\] 105 : : string "'"{str_char}*"'"|"#"{str_char}*"#" 106 : : 107 : : %% 108 : : 109 : : "NOT" { U_OP(uoNot); return NOT; } 110 : : "AND" { B_OP(boAnd); return AND; } 111 : : "OR" { B_OP(boOr); return OR; } 112 : : 113 : : "=" { B_OP(boEQ); return EQ; } 114 : : "!=" { B_OP(boNE); return NE; } 115 : : "<=" { B_OP(boLE); return LE; } 116 : : ">=" { B_OP(boGE); return GE; } 117 : : "<>" { B_OP(boNE); return NE; } 118 : : "<" { B_OP(boLT); return LT; } 119 : : ">" { B_OP(boGT); return GT; } 120 : : 121 : : "LIKE" { B_OP(boLike); return LIKE; } 122 : : "NOT"{white}"LIKE" { B_OP(boNotLike); return LIKE; } 123 : : "ILIKE" { B_OP(boILike); return LIKE; } 124 : : "NOT"{white}"ILIKE" { B_OP(boNotILike); return LIKE; } 125 : : "IS" { B_OP(boIs); return IS; } 126 : : "IS"{white}"NOT" { B_OP(boIsNot); return IS; } 127 : : "||" { B_OP(boConcat); return CONCAT; } 128 : : 129 : : "+" { B_OP(boPlus); return PLUS; } 130 : : "-" { B_OP(boMinus); return MINUS; } 131 : : "*" { B_OP(boMul); return MUL_OR_STAR; } 132 : : "//" { B_OP(boIntDiv); return INTDIV; } 133 : : "/" { B_OP(boDiv); return DIV; } 134 : : "%" { B_OP(boMod); return MOD; } 135 : : "^" { B_OP(boPow); return POW; } 136 : : 137 : : "IN" { return IN; } 138 : : "BETWEEN" { return BETWEEN; } 139 : : 140 : : "NULL" { return NULLVALUE; } 141 : : 142 : : "SELECT" { return SELECT; } 143 : : "ALL" { return ALL; } 144 : : "DISTINCT" { return DISTINCT; } 145 : : "CAST" { return CAST; } 146 : : "AS" { return AS; } 147 : : "FROM" { return FROM; } 148 : : "JOIN" { return JOIN; } 149 : : "ON" { return ON; } 150 : : "USING" { return USING; } 151 : : "WHERE" { return WHERE; } 152 : : "ORDER" { return ORDER; } 153 : : "BY" { return BY; } 154 : : "ASC" { return ASC; } 155 : : "DESC" { return DESC; } 156 : : "LEFT" { return LEFT; } 157 : : "RIGHT" { return RIGHT; } 158 : : "INNER" { return INNER; } 159 : : "OUTER" { return OUTER; } 160 : : "CROSS" { return CROSS; } 161 : : "FULL" { return FULL; } 162 : : "NATURAL" { return NATURAL; } 163 : : "UNION" { return UNION; } 164 : : 165 : : [().] { return yytext[0]; } 166 : : 167 : : "," { return COMMA; } 168 : : 169 : : {num_float} { yylval->numberFloat = cLocale()->toDouble( QString::fromLatin1(yytext) ); return NUMBER_FLOAT; } 170 : : {num_int} { 171 : : bool ok; 172 : : yylval->numberInt = cLocale()->toInt( QString::fromLatin1(yytext), &ok ); 173 : : if( ok ) 174 : : return NUMBER_INT; 175 : : 176 : : yylval->numberInt64 = cLocale()->toLongLong( QString::fromLatin1(yytext), &ok ); 177 : : if( ok ) 178 : : return NUMBER_INT64; 179 : : 180 : : yylval->numberFloat = cLocale()->toDouble( QString::fromLatin1(yytext), &ok ); 181 : : if( ok ) 182 : : return NUMBER_FLOAT; 183 : : 184 : : return Unknown_CHARACTER; 185 : : } 186 : : 187 : : {boolean} { yylval->boolVal = QString( yytext ).compare( "true", Qt::CaseInsensitive ) == 0; return BOOLEAN; } 188 : : 189 : : {string} { TEXT_FILTER(stripText); return STRING; } 190 : : 191 : : {identifier} { TEXT; return IDENTIFIER; } 192 : : 193 : : {identifier_quoted} { TEXT_FILTER(QgsSQLStatement::stripQuotedIdentifier); return IDENTIFIER; } 194 : : 195 : : {ms_identifier_quoted} { TEXT_FILTER(QgsSQLStatement::stripMsQuotedIdentifier); return IDENTIFIER; } 196 : : 197 : : {white} /* skip blanks and tabs */ 198 : : 199 : : . { return Unknown_CHARACTER; } 200 : : 201 : : 202 : : %%