File indexing completed on 2024-12-01 04:18:56
0001 #!/bin/bash 0002 # 0003 # Copyright (C) 2006-2015 Jarosław Staniek <staniek@kde.org> 0004 # 0005 # This program is free software; you can redistribute it and/or 0006 # modify it under the terms of the GNU 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 program 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 # General Public License for more details. 0014 # 0015 # You should have received a copy of the GNU General Public License 0016 # along with this program; see the file COPYING. If not, write to 0017 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 # Boston, MA 02110-1301, USA. 0019 # 0020 # Generates parser and lexer code using bison and flex 0021 # 0022 0023 me=generate_parser_code.sh 0024 0025 BISON_MIN=3.0.4 # keep updated for best results 0026 BISON_MIN_NUM=30004 # keep updated for best results 0027 FLEX_MIN=2.5.37 # keep updated for best results 0028 FLEX_MIN_NUM=20537 # keep updated for best results 0029 0030 # Check minimum version of bison 0031 bisonv=`bison --version | head -n 1| cut -f4 -d" "` 0032 bisonv1=`echo $bisonv | cut -f1 -d.` 0033 bisonv2=`echo $bisonv | cut -f2 -d.` 0034 bisonv3=`echo $bisonv | cut -f3 -d.` 0035 if [ -z $bisonv3 ] ; then bisonv3=0; fi 0036 bisonvnum=`expr $bisonv1 \* 10000 + $bisonv2 \* 100 + $bisonv3` 0037 if [ $bisonvnum -lt $BISON_MIN_NUM ] ; then 0038 echo "$bisonv is too old bison version, the minimum is $BISON_MIN." 0039 exit 1 0040 fi 0041 0042 # Check minimum version of flex 0043 flexv=`flex --version | head -n 1| cut -f2 -d" "` 0044 flexv1=`echo $flexv | cut -f1 -d.` 0045 flexv2=`echo $flexv | cut -f2 -d.` 0046 flexv3=`echo $flexv | cut -f3 -d.` 0047 flexvnum=`expr $flexv1 \* 10000 + $flexv2 \* 100 + $flexv3` 0048 if [ $flexvnum -lt $FLEX_MIN_NUM ] ; then 0049 echo "$flexv is too old flex version, the minimum is $FLEX_MIN." 0050 exit 1 0051 fi 0052 0053 # Generate lexer and parser 0054 builddir=$PWD 0055 srcdir=`dirname $0` 0056 cd $srcdir 0057 0058 flex -ogenerated/sqlscanner.cpp KDbSqlScanner.l 0059 # Correct a few yy_size_t vs size_t vs int differences that some bisons cause 0060 sed --in-place 's/int yyleng/yy_size_t yyleng/g;s/int yyget_leng/yy_size_t yyget_leng/g;s/yyleng = (int)/yyleng = (size_t)/g;' generated/sqlscanner.cpp 0061 bison -d KDbSqlParser.y -Wall -fall -rall --report-file=$builddir/KDbSqlParser.output 0062 0063 # postprocess 0064 cat << EOF > generated/sqlparser.h 0065 /**************************************************************************** 0066 * Created by $me 0067 * WARNING! All changes made in this file will be lost! 0068 ****************************************************************************/ 0069 #ifndef KDBSQLPARSER_H 0070 #define KDBSQLPARSER_H 0071 0072 #include "KDbDateTime.h" 0073 #include "KDbExpression.h" 0074 #include "KDbField.h" 0075 #include "KDbOrderByColumn.h" 0076 0077 struct OrderByColumnInternal; 0078 struct SelectOptionsInternal; 0079 0080 EOF 0081 0082 # Fine-tune the code: extra functions and remove trailing white space 0083 cat KDbSqlParser.tab.h >> generated/sqlparser.h 0084 echo '#endif' >> generated/sqlparser.h 0085 sed --in-place 's/[[:space:]]\+$//;s/\t/ /g' generated/sqlparser.h 0086 0087 cat KDbSqlParser.tab.c | sed -e "s/KDbSqlParser\.tab\.c/sqlparser.cpp/g" > generated/sqlparser.cpp 0088 cat << EOF >> generated/sqlparser.cpp 0089 KDB_TESTING_EXPORT const char* g_tokenName(unsigned int offset) { 0090 const int t = YYTRANSLATE(offset); 0091 if (t >= YYTRANSLATE(::SQL_TYPE)) { 0092 return yytname[t]; 0093 } 0094 return nullptr; 0095 } 0096 0097 //static 0098 const int KDbToken::maxCharTokenValue = 253; 0099 0100 //static 0101 const int KDbToken::maxTokenValue = YYMAXUTOK; 0102 EOF 0103 sed --in-place 's/[[:space:]]\+$//;s/\t/ /g' generated/sqlparser.cpp 0104 0105 # Extract table of SQL tokens 0106 # unused ./extract_tokens.sh > generated/tokens.cpp 0107 rm -f KDbSqlParser.tab.h KDbSqlParser.tab.c 0108 0109 # Create KDbToken.h 0110 cat << EOF > generated/KDbToken.h 0111 /**************************************************************************** 0112 * Created by $me 0113 * WARNING! All changes made in this file will be lost! 0114 ****************************************************************************/ 0115 /* This file is part of the KDE project 0116 Copyright (C) 2015-2018 Jarosław Staniek <staniek@kde.org> 0117 0118 This library is free software; you can redistribute it and/or 0119 modify it under the terms of the GNU Library General Public 0120 License as published by the Free Software Foundation; either 0121 version 2 of the License, or (at your option) any later version. 0122 0123 This library is distributed in the hope that it will be useful, 0124 but WITHOUT ANY WARRANTY; without even the implied warranty of 0125 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0126 Library General Public License for more details. 0127 0128 You should have received a copy of the GNU Library General Public License 0129 along with this library; see the file COPYING.LIB. If not, write to 0130 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0131 * Boston, MA 02110-1301, USA. 0132 */ 0133 0134 #ifndef KDB_TOKEN_H 0135 #define KDB_TOKEN_H 0136 0137 #include "kdb_export.h" 0138 0139 #include <QDebug> 0140 0141 class KDbDriver; 0142 0143 /*! @brief A type-safe KDbSQL token 0144 It can be used in KDb expressions 0145 @see KDbExpression */ 0146 class KDB_EXPORT KDbToken 0147 { 0148 public: 0149 //! @todo add KDbToken(const QByteArray &name) 0150 0151 //! Creates an invalid token 0152 inline KDbToken() : v(0) {} 0153 0154 KDbToken(const KDbToken &other) : v(other.v) {} 0155 0156 //! Creates a single-character token 0157 //! Only characters that belong to the grammar are accepted: 0158 EOF 0159 (echo -n " //! "; grep "\"'.'\"," generated/sqlparser.cpp \ 0160 | sed -e "s/\"\('.'\)\",/\1/g;s/\"[0-9A-Za-z_$]*\",[ ]*//g;" | tr --delete '\n' \ 0161 | sed -e "s/ $//g;") >> generated/KDbToken.h 0162 0163 cat << EOF >> generated/KDbToken.h 0164 0165 //! Invalid KDbToken is created for character that is not accepted. 0166 KDbToken(char charToken); 0167 0168 //! @return true if this token is valid 0169 inline bool isValid() const { return v != 0; } 0170 0171 //! @return name of this token 0172 //! Useful for debugging. 0173 //! For example "NOT_EQUAL" string is returned for the NOT_EQUAL token. 0174 //! A single character is returned for printable single-character tokens. 0175 //! A number is returned for non-printable single-character. 0176 //! "<INVALID_TOKEN>" is returned for an invalid string. 0177 QString name() const; 0178 0179 //! @return string interpretation of this token (as visibe to the user) 0180 //! For example "<>" is returned for the NOT_EQUAL token. 0181 //! Empty string is returned for an invalid string 0182 //! The result may depend on the optional @a driver parameter. 0183 //! If @a driver is @c nullptr, representation for portable KDbSQL dialect is returned. 0184 QString toString(const KDbDriver *driver = nullptr) const; 0185 0186 //! Like toString(const KDbDriver *driver) 0187 static QString toString(KDbToken token, const KDbDriver *driver = nullptr); 0188 0189 //! Maximum character token value (253) 0190 static const int maxCharTokenValue; 0191 0192 //! Maximum character token value 0193 static const int maxTokenValue; 0194 0195 //! @return character equivalent of this token 0196 //! Only character-based tokens are supported this way (toInt() <= maxCharTokenValue). 0197 //! For unsupported tokens @c nullptr is returned. 0198 inline char toChar() const { return v <= maxCharTokenValue ? v : 0; } 0199 0200 //! @return numeric value of this token 0201 inline int value() const { return v; } 0202 0203 //! @return true if this token is equal to @a other token 0204 inline bool operator==(KDbToken other) const { return v == other.v; } 0205 0206 //! @return true if this token is not equal to @a other token 0207 inline bool operator!=(KDbToken other) const { return v != other.v; } 0208 0209 //! @return true if this token is equal to @a other token 0210 inline bool operator==(char charToken) const { return v == charToken; } 0211 0212 //! @return true if this token is not equal to @a other token 0213 inline bool operator!=(char charToken) const { return v != charToken; } 0214 0215 static QList<KDbToken> allTokens(); 0216 0217 // -- constants go here -- 0218 EOF 0219 0220 function extractTokens() 0221 { 0222 grep -E " [A-Z0-9_]+ = [[:digit:]]+" generated/sqlparser.h \ 0223 | sed -e "s/^ //g;s/ = / /g;s/,//g" 0224 } 0225 0226 extractTokens | while read token value; do 0227 echo " static const KDbToken $token;" 0228 done >> generated/KDbToken.h 0229 0230 function customTokens() 0231 { 0232 cat << EOF 0233 BETWEEN_AND 0x1001 0234 NOT_BETWEEN_AND 0x1002 0235 EOF 0236 } 0237 0238 echo " //! Custom tokens are not used in parser but used as an extension in expression classes." >> generated/KDbToken.h 0239 0240 customTokens | while read token value; do 0241 echo " static const KDbToken $token;" 0242 done >> generated/KDbToken.h 0243 0244 cat << EOF >> generated/KDbToken.h 0245 // -- end of constants -- 0246 0247 class List; 0248 private: 0249 inline KDbToken(int value) : v(value) {} 0250 int v; 0251 }; 0252 0253 //! Sends information about token @a token to debug output @a dbg. 0254 KDB_EXPORT QDebug operator<<(QDebug dbg, KDbToken token); 0255 0256 #endif 0257 EOF 0258 0259 cat << EOF > generated/KDbToken.cpp 0260 /**************************************************************************** 0261 * Created by $me 0262 * WARNING! All changes made in this file will be lost! 0263 ****************************************************************************/ 0264 /* This file is part of the KDE project 0265 Copyright (C) 2015-2018 Jarosław Staniek <staniek@kde.org> 0266 0267 This library is free software; you can redistribute it and/or 0268 modify it under the terms of the GNU Library General Public 0269 License as published by the Free Software Foundation; either 0270 version 2 of the License, or (at your option) any later version. 0271 0272 This library is distributed in the hope that it will be useful, 0273 but WITHOUT ANY WARRANTY; without even the implied warranty of 0274 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0275 Library General Public License for more details. 0276 0277 You should have received a copy of the GNU Library General Public License 0278 along with this library; see the file COPYING.LIB. If not, write to 0279 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0280 * Boston, MA 02110-1301, USA. 0281 */ 0282 0283 #include "KDbToken.h" 0284 #include "KDbDriver.h" 0285 #include "KDbDriver_p.h" 0286 #include "KDbDriverBehavior.h" 0287 #include "sqlparser.h" 0288 #include "parser/KDbParser_p.h" 0289 0290 #include <QGlobalStatic> 0291 0292 KDbToken::KDbToken(char charToken) 0293 : v(g_tokenName(charToken) == nullptr ? 0 : charToken) 0294 { 0295 } 0296 0297 QString KDbToken::name() const 0298 { 0299 if (!isValid()) { 0300 return QLatin1String("<INVALID_TOKEN>"); 0301 } 0302 if (v > maxCharTokenValue) { 0303 return QLatin1String(g_tokenName(v)); 0304 } 0305 if (isprint(v)) { 0306 return QString(QLatin1Char(char(v))); 0307 } 0308 else { 0309 return QLatin1String(QByteArray::number(v)); 0310 } 0311 } 0312 0313 QString KDbToken::toString(const KDbDriver *driver) const 0314 { 0315 if (toChar() > 0) { 0316 return name(); 0317 } 0318 // other arithmetic operations: << >> 0319 // NOTE: only include cases that have toString() != name() or are dependent on driver 0320 switch (v) { 0321 case ::BITWISE_SHIFT_RIGHT: return QLatin1String(">>"); 0322 case ::BITWISE_SHIFT_LEFT: return QLatin1String("<<"); 0323 // other relational operations: <= >= <> (or !=) LIKE IN 0324 case ::NOT_EQUAL: return QLatin1String("<>"); 0325 case ::NOT_EQUAL2: return QLatin1String("!="); 0326 case ::LESS_OR_EQUAL: return QLatin1String("<="); 0327 case ::GREATER_OR_EQUAL: return QLatin1String(">="); 0328 case ::LIKE: return driver ? KDbDriverPrivate::behavior(driver)->LIKE_OPERATOR : QLatin1String("LIKE"); 0329 case ::NOT_LIKE: 0330 return driver 0331 ? (QString::fromLatin1("NOT ") + KDbDriverPrivate::behavior(driver)->LIKE_OPERATOR) 0332 : QString::fromLatin1("NOT LIKE"); 0333 case ::SQL_IN: return QLatin1String("IN"); 0334 // other logical operations: OR (or ||) AND (or &&) XOR 0335 case ::SIMILAR_TO: return QLatin1String("SIMILAR TO"); 0336 case ::NOT_SIMILAR_TO: return QLatin1String("NOT SIMILAR TO"); 0337 // other string operations: || (as CONCATENATION) 0338 case ::CONCATENATION: return QLatin1String("||"); 0339 // SpecialBinary "pseudo operators": 0340 /* not handled here */ 0341 default:; 0342 } 0343 const QString s = name(); 0344 if (!s.isEmpty()) { 0345 return s; 0346 } 0347 return QString::fromLatin1("<INVALID_TOKEN#%1> ").arg(v); 0348 } 0349 0350 //static 0351 QString KDbToken::toString(KDbToken token, const KDbDriver *driver) 0352 { 0353 return token.toString(driver); 0354 } 0355 0356 KDB_EXPORT QDebug operator<<(QDebug dbg, KDbToken token) 0357 { 0358 QDebugStateSaver saver(dbg); 0359 dbg.nospace().noquote() << token.name(); 0360 return dbg.maybeSpace(); 0361 } 0362 0363 //! @internal 0364 class KDbToken::List 0365 { 0366 public: 0367 List() 0368 { 0369 for (int i = 0; i < KDbToken::maxTokenValue; ++i) { 0370 if (g_tokenName(i)) { 0371 data.append(KDbToken(i)); 0372 } 0373 } 0374 } 0375 QList<KDbToken> data; 0376 }; 0377 0378 Q_GLOBAL_STATIC(KDbToken::List, g_allTokens) 0379 0380 //static 0381 QList<KDbToken> KDbToken::allTokens() 0382 { 0383 return g_allTokens->data; 0384 } 0385 0386 EOF 0387 0388 extractTokens | while read token value; do 0389 echo "const KDbToken KDbToken::$token(::$token);" 0390 done >> generated/KDbToken.cpp 0391 0392 customTokens | while read token value; do 0393 echo "const KDbToken KDbToken::$token($value);" 0394 done >> generated/KDbToken.cpp