Warning, /libraries/kdb/src/parser/KDbSqlScanner.l is written in an unsupported language. File is not indexed.
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Lucijan Busch <lucijan@kde.org> 0003 Copyright (C) 2004-2018 Jarosław Staniek <staniek@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 %{ 0022 #include "sqlparser.h" 0023 #include "KDb.h" 0024 #include "KDbExpression.h" 0025 #include "KDbParser.h" 0026 #include "KDbSqlTypes.h" 0027 #include "kdb_debug.h" 0028 0029 extern int globalCurrentPos; 0030 extern QByteArray globalToken; 0031 0032 #define YY_NO_UNPUT 0033 #define ECOUNT globalCurrentPos += yyleng; globalToken = yytext 0034 0035 extern void setError(const QString& errDesc); 0036 extern void setError(const QString& errName, const QString& errDesc); 0037 0038 /* Only quotes the input if it does not start with a quote character, otherwise 0039 it would be too hard to read with some fonts. */ 0040 static QString maybeQuote(const QString& string) 0041 { 0042 QString first(string.left(1)); 0043 if (first == QLatin1Char('\'') || first == QLatin1Char('"') || first == QLatin1Char('`')) { 0044 return string; 0045 } 0046 return QStringLiteral("\"%1\"").arg(string); 0047 } 0048 %} 0049 0050 /* *** Please reflect changes to this file in ../driver_p.cpp *** */ 0051 0052 %option case-insensitive 0053 %option noyywrap 0054 %option never-interactive 0055 0056 %x DATE_OR_TIME 0057 0058 whitespace [ \t\n] 0059 whitespace_1_line [ \t] 0060 digit [0-9] 0061 e_str1 (\\\'|\'\'|[^']) 0062 e_str2 (\\\"|\"\"|[^"]) 0063 string (\'{e_str1}*\'|\"{e_str2}*\") 0064 /*identifier [a-zA-Z_][a-zA-Z_0-9]* */ 0065 identifier [a-zA-Z_0-9]+ 0066 /* quoted_identifier (\"[a-zA-Z_0-9]+\") */ 0067 query_parameter \[[^\[\]]+\] 0068 0069 integer {digit}+ 0070 decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*)) 0071 real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+)) 0072 0073 %% 0074 0075 int DATE_OR_TIME_caller = 0; 0076 0077 "<>" { 0078 ECOUNT; 0079 return NOT_EQUAL; 0080 } 0081 0082 "!=" { 0083 ECOUNT; 0084 return NOT_EQUAL2; 0085 } 0086 0087 "==" { 0088 ECOUNT; 0089 return '='; 0090 } 0091 0092 "<=" { 0093 ECOUNT; 0094 return LESS_OR_EQUAL; 0095 } 0096 0097 ">=" { 0098 ECOUNT; 0099 return GREATER_OR_EQUAL; 0100 } 0101 0102 "IN" { 0103 ECOUNT; 0104 return SQL_IN; 0105 } 0106 0107 {integer} { 0108 //! @todo what about hex or octal values? 0109 //we're using QString:toLongLong() here because atoll() is not so portable: 0110 ECOUNT; 0111 bool ok; 0112 yylval.integerValue = QByteArray(yytext).toLongLong(&ok); 0113 if (!ok) { 0114 setError(KDbParser::tr("Invalid integer number"), KDbParser::tr("This integer number may be too large.")); 0115 return SCAN_ERROR; 0116 } 0117 return INTEGER_CONST; 0118 } 0119 0120 {decimal} { 0121 ECOUNT; 0122 yylval.binaryValue = new QByteArray(yytext, yyleng); 0123 return REAL_CONST; 0124 } 0125 0126 /* --- DATE_OR_TIME --- */ 0127 # { 0128 ECOUNT; 0129 sqlParserDebug() << "### begin DATE_OR_TIME" << yytext << "(" << yyleng << ")"; 0130 DATE_OR_TIME_caller = YYSTATE; 0131 BEGIN(DATE_OR_TIME); 0132 return '#'; 0133 } 0134 0135 <DATE_OR_TIME>{ 0136 0137 [-+/:] { // year prefix or / or - or : separator 0138 ECOUNT; 0139 return yytext[0]; 0140 } 0141 0142 {integer} { // year, month, day, hour, minute or second 0143 ECOUNT; 0144 yylval.binaryValue = new QByteArray(yytext, yyleng); 0145 return DATE_TIME_INTEGER; 0146 } 0147 0148 {whitespace_1_line}+ { 0149 ECOUNT; 0150 return TABS_OR_SPACES; 0151 } 0152 0153 {whitespace_1_line}*(?i:AM) { 0154 ECOUNT; 0155 return TIME_AM; 0156 } 0157 0158 {whitespace_1_line}*(?i:PM) { 0159 ECOUNT; 0160 return TIME_PM; 0161 } 0162 0163 # { 0164 ECOUNT; 0165 sqlParserDebug() << "### end DATE_OR_TIME" << yytext << "(" << yyleng << ")"; 0166 BEGIN(DATE_OR_TIME_caller); 0167 return '#'; 0168 } 0169 0170 0171 . { // fallback rule to avoid flex's default action that prints the character to stdout 0172 // without notifying the scanner. 0173 ECOUNT; 0174 const QString string(QString::fromUtf8(yytext, yyleng)); 0175 setError(KDbParser::tr("Unexpected character %1 in date/time").arg(maybeQuote(string))); 0176 return SCAN_ERROR; 0177 } 0178 0179 } 0180 /* -- end of DATE_OR_TIME --- */ 0181 0182 ("AND"|"&&") { 0183 ECOUNT; 0184 return AND; 0185 } 0186 0187 "AS" { 0188 ECOUNT; 0189 return AS; 0190 } 0191 0192 "CREATE" { 0193 ECOUNT; 0194 return CREATE; 0195 } 0196 0197 "FROM" { 0198 ECOUNT; 0199 return FROM; 0200 } 0201 0202 "INTEGER" { 0203 ECOUNT; 0204 return SQL_TYPE; 0205 } 0206 0207 "JOIN" { 0208 ECOUNT; 0209 return JOIN; 0210 } 0211 0212 "LEFT" { 0213 ECOUNT; 0214 return LEFT; 0215 } 0216 0217 "LIKE" { 0218 ECOUNT; 0219 return LIKE; 0220 } 0221 0222 "NOT"{whitespace}+"LIKE" { 0223 ECOUNT; 0224 return NOT_LIKE; 0225 } 0226 0227 "BETWEEN" { 0228 ECOUNT; 0229 return BETWEEN; 0230 } 0231 0232 "NOT"{whitespace}+"BETWEEN" { 0233 ECOUNT; 0234 return NOT_BETWEEN; 0235 } 0236 0237 "NOT"{whitespace}+"SIMILAR"{whitespace}+"TO" { 0238 ECOUNT; 0239 return NOT_SIMILAR_TO; 0240 } 0241 0242 "SIMILAR"{whitespace}+"TO" { 0243 ECOUNT; 0244 return SIMILAR_TO; 0245 } 0246 0247 "IS"{whitespace}+"NOT"{whitespace}+"NULL" { 0248 ECOUNT; 0249 return SQL_IS_NOT_NULL; 0250 } 0251 0252 "IS"{whitespace}+"NULL" { 0253 ECOUNT; 0254 return SQL_IS_NULL; 0255 } 0256 0257 "NOT" { 0258 ECOUNT; 0259 return NOT; 0260 } 0261 0262 "IS" { 0263 ECOUNT; 0264 return SQL_IS; 0265 } 0266 0267 "NULL" { 0268 ECOUNT; 0269 return SQL_NULL; 0270 } 0271 0272 "TRUE" { 0273 ECOUNT; 0274 return SQL_TRUE; 0275 } 0276 0277 "FALSE" { 0278 ECOUNT; 0279 return SQL_FALSE; 0280 } 0281 0282 "ON" { 0283 ECOUNT; 0284 return SQL_ON; 0285 } 0286 0287 "OR" { 0288 ECOUNT; 0289 return OR; 0290 } 0291 0292 "||" { /* also means OR for numbers (mysql) */ 0293 ECOUNT; 0294 return CONCATENATION; 0295 } 0296 0297 "<<" { 0298 ECOUNT; 0299 return BITWISE_SHIFT_LEFT; 0300 } 0301 0302 ">>" { 0303 ECOUNT; 0304 return BITWISE_SHIFT_RIGHT; 0305 } 0306 0307 "XOR" { 0308 ECOUNT; 0309 return XOR; 0310 } 0311 0312 "RIGHT" { 0313 ECOUNT; 0314 return RIGHT; 0315 } 0316 0317 "SELECT" { 0318 ECOUNT; 0319 return SELECT; 0320 } 0321 0322 "TABLE" { 0323 ECOUNT; 0324 return TABLE; 0325 } 0326 0327 "WHERE" { 0328 ECOUNT; 0329 return WHERE; 0330 } 0331 0332 "ORDER" { 0333 ECOUNT; 0334 return ORDER; 0335 } 0336 0337 "BY" { 0338 ECOUNT; 0339 return BY; 0340 } 0341 0342 "ASC" { 0343 ECOUNT; 0344 return ASC; 0345 } 0346 0347 "DESC" { 0348 ECOUNT; 0349 return DESC; 0350 } 0351 0352 {string} { 0353 ECOUNT; 0354 sqlParserDebug() << "{string} yytext: '" << yytext << "' (" << yyleng << ")"; 0355 int errorPosition; 0356 const QString unescaped( 0357 KDb::unescapeString(QString::fromUtf8(yytext+1, yyleng-2), yytext[0], &errorPosition)); 0358 if (errorPosition >= 0) { // sanity check 0359 setError(KDbParser::tr("Invalid string"), 0360 KDbParser::tr("Invalid character in string")); 0361 return SCAN_ERROR; 0362 } 0363 yylval.stringValue = new QString(unescaped); 0364 return CHARACTER_STRING_LITERAL; 0365 0366 /* "ZZZ" sentinel for script */ 0367 } 0368 0369 {identifier} { 0370 sqlParserDebug() << "{identifier} yytext: '" << yytext << "' (" << yyleng << ")"; 0371 ECOUNT; 0372 if (yytext[0]>='0' && yytext[0]<='9') { 0373 setError(KDbParser::tr("Invalid identifier"), 0374 KDbParser::tr("Identifiers should start with a letter or '_' character")); 0375 return SCAN_ERROR; 0376 } 0377 yylval.stringValue = new QString(QString::fromUtf8(yytext, yyleng)); 0378 return IDENTIFIER; 0379 } 0380 0381 {query_parameter} { 0382 sqlParserDebug() << "{query_parameter} yytext: '" << yytext << "' (" << yyleng << ")"; 0383 ECOUNT; 0384 yylval.stringValue = new QString(QString::fromUtf8(yytext+1, yyleng-2)); 0385 return QUERY_PARAMETER; 0386 } 0387 0388 {whitespace}+ { 0389 ECOUNT; 0390 } 0391 0392 [\~\!\@\#\^\&\|\`\?,()\[\]\.;\:\+\-\*\/\%\^\<\>\=] { 0393 sqlParserDebug() << "char: '" << yytext[0] << "'"; 0394 ECOUNT; 0395 return yytext[0]; 0396 } 0397 0398 . { // fallback rule to avoid flex's default action that prints the character to stdout 0399 // without notifying the scanner. 0400 ECOUNT; 0401 const QString string(QString::fromUtf8(yytext, yyleng)); 0402 setError(KDbParser::tr("Unexpected character %1").arg(maybeQuote(string))); 0403 return SCAN_ERROR; 0404 } 0405 0406 %% 0407 0408 void tokenize(const char *data) 0409 { 0410 yy_switch_to_buffer(yy_scan_string(data)); 0411 globalToken.clear(); 0412 globalCurrentPos = 0; 0413 } 0414