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