Eneboo - Documentación para desarrolladores
|
00001 /**************************************************************************** 00002 ** $Id: qslexer.h 1.1.5 edited 2006-02-23T15:39:57$ 00003 ** 00004 ** Copyright (C) 2001-2006 Trolltech AS. All rights reserved. 00005 ** 00006 ** This file is part of the Qt Script for Applications framework (QSA). 00007 ** 00008 ** This file may be distributed and/or modified under the terms of the 00009 ** GNU General Public License version 2 as published by the Free Software 00010 ** Foundation and appearing in the file LICENSE.GPL included in the 00011 ** packaging of this file. 00012 ** 00013 ** Licensees holding a valid Qt Script for Applications license may use 00014 ** this file in accordance with the Qt Script for Applications License 00015 ** Agreement provided with the Software. 00016 ** 00017 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00018 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00019 ** 00020 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 00021 ** information about QSA Commercial License Agreements. 00022 ** See http://www.trolltech.com/gpl/ for GPL licensing information. 00023 ** 00024 ** Contact info@trolltech.com if any conditions of this licensing are 00025 ** not clear to you. 00026 ** 00027 *****************************************************************************/ 00028 00029 #ifndef QSLEXER_H 00030 #define QSLEXER_H 00031 00032 #include <qintdict.h> 00033 #include <qptrlist.h> 00034 #include <qstring.h> 00035 #include <qlocale.h> 00036 00037 class QSLexer 00038 { 00039 public: 00040 enum State { 00041 Start, 00042 Identifier, 00043 InIdentifier, 00044 InSingleLineComment, 00045 InMultiLineComment, 00046 InNum, 00047 InNum0, 00048 InHex, 00049 InOctal, 00050 InDecimal, 00051 InExponentIndicator, 00052 InExponent, 00053 Hex, 00054 Octal, 00055 Number, 00056 String, 00057 Eof, 00058 InString, 00059 InEscapeSequence, 00060 InHexEscape, 00061 InUnicodeEscape, 00062 Other, 00063 Bad, 00064 KeywordNumber 00065 }; 00066 00067 enum ParenthesesState { 00068 IgnoreParentheses, 00069 CountParentheses, 00070 BalancedParentheses 00071 }; 00072 00073 QSLexer(); 00074 ~QSLexer(); 00075 00076 static QSLexer *lexer() { 00077 return lx; 00078 } 00079 00080 void setCode(const QString &c, int id, int lineno = 0); 00081 int lex(); 00082 00083 int lineNo() const { 00084 return yylineno + 1; 00085 } 00086 00087 int sourceId() const { 00088 return sid; 00089 } 00090 00091 bool prevTerminator() const { 00092 return terminator; 00093 } 00094 00095 QString pattern, flags; 00096 00097 bool scanRegExp(); 00098 00099 State lexerState() const { 00100 return state; 00101 } 00102 00103 QString errorMessage() const { 00104 return errmsg; 00105 } 00106 void setErrorMessage(const QString &err) { 00107 errmsg = err; 00108 } 00109 void setErrorMessage(const char *err) { 00110 setErrorMessage(QString::fromLatin1(err)); 00111 } 00112 00113 private: 00114 int yylineno; 00115 bool done; 00116 char *buffer8; 00117 QChar *buffer16; 00118 uint size8, size16; 00119 uint pos8, pos16; 00120 bool terminator; 00121 bool restrKeyword; 00122 // encountered delimiter like "'" and "}" on last run 00123 bool delimited; 00124 int stackToken; 00125 00126 State state; 00127 void setDone(State s) { 00128 state = s; 00129 done = TRUE; 00130 } 00131 00132 uint pos; 00133 00134 bool isWhiteSpace() const { 00135 return (current == ' ' || current == '\t' || 00136 current == 0x0b || current == 0x0c); 00137 } 00138 00139 bool isLineTerminator() const { 00140 return (current == '\n' || current == '\r'); 00141 } 00142 00143 bool isHexDigit(ushort c) const { 00144 return ((c >= '0' && c <= '9') || 00145 (c >= 'a' && c <= 'f') || 00146 (c >= 'A' && c <= 'F')); 00147 } 00148 00149 bool isOctalDigit(ushort c) const { 00150 return (c >= '0' && c <= '7'); 00151 } 00152 00153 ushort singleEscape(ushort c) const { 00154 switch (c) { 00155 case 'b': 00156 return 0x08; 00157 case 't': 00158 return 0x09; 00159 case 'n': 00160 return 0x0A; 00161 case 'v': 00162 return 0x0B; 00163 case 'f': 00164 return 0x0C; 00165 case 'r': 00166 return 0x0D; 00167 case '"': 00168 return 0x22; 00169 case '\'': 00170 return 0x27; 00171 case '\\': 00172 return 0x5C; 00173 default: 00174 return c; 00175 } 00176 } 00177 00178 ushort convertOctal(ushort c1, ushort c2, 00179 ushort c3) const { 00180 return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); 00181 } 00182 00183 public: 00184 static uchar convertHex(ushort c) { 00185 if (c >= '0' && c <= '9') 00186 return static_cast<uchar>(c - '0'); 00187 else if (c >= 'a' && c <= 'f') 00188 return static_cast<uchar>(c - 'a' + 10); 00189 else 00190 return static_cast<uchar>(c - 'A' + 10); 00191 } 00192 00193 static uchar convertHex(ushort c1, ushort c2) { 00194 return ((convertHex(c1) << 4) + convertHex(c2)); 00195 } 00196 00197 static QChar convertUnicode(ushort c1, ushort c2, 00198 ushort c3, ushort c4) { 00199 return QChar((convertHex(c3) << 4) + convertHex(c4), 00200 (convertHex(c1) << 4) + convertHex(c2)); 00201 } 00202 00203 static bool isIdentLetter(ushort c) { 00204 /* TODO: allow other legitimate unicode chars */ 00205 return ((c >= 'a' && c <= 'z') || 00206 (c >= 'A' && c <= 'Z') || 00207 (c == '$' || c == '_')); 00208 } 00209 00210 static bool isDecimalDigit(ushort c) { 00211 return (c >= '0' && c <= '9'); 00212 } 00213 00214 void clearUstr() { 00215 if (ustrHash.count() > 401) 00216 ustrHash.clear(); 00217 ustrList.clear(); 00218 } 00219 00220 private: 00221 00222 static QSLexer *lx; 00223 static int sid; 00224 00225 QIntDict<QString> ustrHash; 00226 QPtrList<QString> ustrList; 00227 00228 uint hashUstr(QChar *s, uint len) { 00229 uint hash = 0; 00230 for (int i = 0; i < len; ++i) { 00231 hash += s[i].unicode(); 00232 hash += (hash << 10); 00233 hash ^= (hash >> 6); 00234 } 00235 hash += (hash << 3); 00236 hash ^= (hash >> 11); 00237 hash += (hash << 15); 00238 return hash; 00239 } 00240 00241 const QString *newUstr(QChar *s, uint len) { 00242 QString *us = 0; 00243 if (len < 50) { 00244 uint hash = hashUstr(s, len); 00245 us = ustrHash.find(hash); 00246 if (!us) { 00247 us = new QString(s, len); 00248 ustrHash.insert(hash, us); 00249 } 00250 } else { 00251 us = new QString(s, len); 00252 ustrList.append(us); 00253 } 00254 return us; 00255 } 00256 00257 void syncProhibitAutomaticSemicolon() { 00258 if (parenthesesState == BalancedParentheses) { 00259 // we have seen something like "if (foo)", which means we should 00260 // never insert an automatic semicolon at this point, since it would 00261 // then be expanded into an empty statement (ECMA-262 7.9.1) 00262 prohibitAutomaticSemicolon = true; 00263 parenthesesState = IgnoreParentheses; 00264 } else { 00265 prohibitAutomaticSemicolon = false; 00266 } 00267 } 00268 00269 const QChar *code; 00270 uint length; 00271 int yycolumn; 00272 int bol; 00273 00274 // current and following unicode characters 00275 ushort current, next1, next2, next3; 00276 00277 QString errmsg; 00278 QLocale localeC; 00279 00280 ParenthesesState parenthesesState; 00281 int parenthesesCount; 00282 bool prohibitAutomaticSemicolon; 00283 }; 00284 00285 #endif