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