source: trunk/tools/designer/src/lib/shared/qscripthighlighter.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 21.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Designer of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscripthighlighter_p.h"
43
44#include <QtCore/QSet>
45
46QT_BEGIN_NAMESPACE
47
48static const QSet<QString> &qscriptKeywords() {
49 static QSet<QString> keywords;
50 if (keywords.empty()) {
51 keywords.insert(QLatin1String("Infinity"));
52 keywords.insert(QLatin1String("NaN"));
53 keywords.insert(QLatin1String("abstract"));
54 keywords.insert(QLatin1String("boolean"));
55 keywords.insert(QLatin1String("break"));
56 keywords.insert(QLatin1String("byte"));
57 keywords.insert(QLatin1String("case"));
58 keywords.insert(QLatin1String("catch"));
59 keywords.insert(QLatin1String("char"));
60 keywords.insert(QLatin1String("class"));
61 keywords.insert(QLatin1String("const"));
62 keywords.insert(QLatin1String("constructor"));
63 keywords.insert(QLatin1String("continue"));
64 keywords.insert(QLatin1String("debugger"));
65 keywords.insert(QLatin1String("default"));
66 keywords.insert(QLatin1String("delete"));
67 keywords.insert(QLatin1String("do"));
68 keywords.insert(QLatin1String("double"));
69 keywords.insert(QLatin1String("else"));
70 keywords.insert(QLatin1String("enum"));
71 keywords.insert(QLatin1String("export"));
72 keywords.insert(QLatin1String("extends"));
73 keywords.insert(QLatin1String("false"));
74 keywords.insert(QLatin1String("final"));
75 keywords.insert(QLatin1String("finally"));
76 keywords.insert(QLatin1String("float"));
77 keywords.insert(QLatin1String("for"));
78 keywords.insert(QLatin1String("function"));
79 keywords.insert(QLatin1String("goto"));
80 keywords.insert(QLatin1String("if"));
81 keywords.insert(QLatin1String("implements"));
82 keywords.insert(QLatin1String("import"));
83 keywords.insert(QLatin1String("in"));
84 keywords.insert(QLatin1String("instanceof"));
85 keywords.insert(QLatin1String("int"));
86 keywords.insert(QLatin1String("interface"));
87 keywords.insert(QLatin1String("long"));
88 keywords.insert(QLatin1String("native"));
89 keywords.insert(QLatin1String("new"));
90 keywords.insert(QLatin1String("package"));
91 keywords.insert(QLatin1String("private"));
92 keywords.insert(QLatin1String("protected"));
93 keywords.insert(QLatin1String("public"));
94 keywords.insert(QLatin1String("return"));
95 keywords.insert(QLatin1String("short"));
96 keywords.insert(QLatin1String("static"));
97 keywords.insert(QLatin1String("super"));
98 keywords.insert(QLatin1String("switch"));
99 keywords.insert(QLatin1String("synchronized"));
100 keywords.insert(QLatin1String("this"));
101 keywords.insert(QLatin1String("throw"));
102 keywords.insert(QLatin1String("throws"));
103 keywords.insert(QLatin1String("transient"));
104 keywords.insert(QLatin1String("true"));
105 keywords.insert(QLatin1String("try"));
106 keywords.insert(QLatin1String("typeof"));
107 keywords.insert(QLatin1String("undefined"));
108 keywords.insert(QLatin1String("var"));
109 keywords.insert(QLatin1String("void"));
110 keywords.insert(QLatin1String("volatile"));
111 keywords.insert(QLatin1String("while"));
112 keywords.insert(QLatin1String("with")); // end
113 }
114 return keywords;
115}
116
117static QSet<QChar> alphaChars() {
118 QSet<QChar> rc;
119 const QString alpha = QLatin1String("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
120 foreach (QChar chr, alpha)
121 rc.insert(chr);
122 return rc;
123}
124
125namespace qdesigner_internal {
126
127QScriptHighlighter::QScriptHighlighter(QTextDocument *parent)
128 : QSyntaxHighlighter(parent)
129{
130 m_numberFormat.setForeground(Qt::blue);
131 m_stringFormat.setForeground(Qt::darkGreen);
132 m_typeFormat.setForeground(Qt::darkMagenta);
133 m_keywordFormat.setForeground(Qt::darkYellow);
134 m_labelFormat.setForeground(Qt::darkRed);
135 m_commentFormat.setForeground(Qt::red);
136 //m_commentFormat.setFontFamily("times");
137 m_commentFormat.setFontItalic(true);
138 m_preProcessorFormat.setForeground(Qt::darkBlue);
139}
140
141void QScriptHighlighter::highlightBlock(const QString &text)
142{
143 // states
144 enum {
145 StateStandard,
146 StateCommentStart1,
147 StateCCommentStart2,
148 StateCppCommentStart2,
149 StateCComment,
150 StateCppComment,
151 StateCCommentEnd1,
152 StateCCommentEnd2,
153 StateStringStart,
154 StateString,
155 StateStringEnd,
156 StateString2Start,
157 StateString2,
158 StateString2End,
159 StateNumber,
160 StatePreProcessor,
161 NumStates
162 };
163 // tokens
164 enum {
165 InputAlpha,
166 InputNumber,
167 InputAsterix,
168 InputSlash,
169 InputParen,
170 InputSpace,
171 InputHash,
172 InputQuotation,
173 InputApostrophe,
174 InputSep,
175 NumInputs
176 };
177
178 static const uchar table[NumStates][NumInputs] = {
179 { StateStandard, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateStandard
180 { StateStandard, StateNumber, StateCCommentStart2, StateCppCommentStart2, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateCommentStart1
181 { StateCComment, StateCComment, StateCCommentEnd1, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCCommentStart2
182 { StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment }, // CppCommentStart2
183 { StateCComment, StateCComment, StateCCommentEnd1, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCComment
184 { StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment }, // StateCppComment
185 { StateCComment, StateCComment, StateCCommentEnd1, StateCCommentEnd2, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCCommentEnd1
186 { StateStandard, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateCCommentEnd2
187 { StateString, StateString, StateString, StateString, StateString, StateString, StateString, StateStringEnd, StateString, StateString }, // StateStringStart
188 { StateString, StateString, StateString, StateString, StateString, StateString, StateString, StateStringEnd, StateString, StateString }, // StateString
189 { StateStandard, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateStringEnd
190 { StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2End, StateString2 }, // StateString2Start
191 { StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2End, StateString2 }, // StateString2
192 { StateStandard, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateString2End
193 { StateNumber, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateNumber
194 { StatePreProcessor, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard } // StatePreProcessor
195 };
196
197 QString buffer;
198 buffer.reserve(text.length());
199 QTextCharFormat emptyFormat;
200
201 int state = StateStandard;
202 const int previousState = previousBlockState();
203 if (previousState != -1)
204 state = previousState;
205
206 if (text.isEmpty()) {
207 setCurrentBlockState(previousState);
208 return;
209 }
210
211 int input = -1;
212 int i = 0;
213 bool lastWasBackSlash = false;
214 bool makeLastStandard = false;
215
216 static const QSet<QChar> alphabeth = alphaChars();
217 static const QString mathChars = QString::fromLatin1("xXeE");
218 static const QString numbers = QString::fromLatin1("0123456789");
219 bool questionMark = false;
220 QChar lastChar;
221 QString firstWord;
222 forever {
223 const QChar c = text.at(i);
224
225 if (lastWasBackSlash) {
226 input = InputSep;
227 } else {
228 switch (c.toLatin1()) {
229 case '*':
230 input = InputAsterix;
231 break;
232 case '/':
233 input = InputSlash;
234 break;
235 case '(': case '[': case '{':
236 input = InputParen;
237 if (state == StateStandard
238 || state == StateNumber
239 || state == StatePreProcessor
240 || state == StateCCommentEnd2
241 || state == StateCCommentEnd1
242 || state == StateString2End
243 || state == StateStringEnd
244 )
245 //blockData->parentheses << Parenthesis(Parenthesis::Open, c, i);
246 break;
247 case ')': case ']': case '}':
248 input = InputParen;
249 if (state == StateStandard
250 || state == StateNumber
251 || state == StatePreProcessor
252 || state == StateCCommentEnd2
253 || state == StateCCommentEnd1
254 || state == StateString2End
255 || state == StateStringEnd
256 ) {
257 //blockData->parentheses << Parenthesis(Parenthesis::Closed, c, i);
258 }
259 break;
260 case '#':
261 input = InputHash;
262 break;
263 case '"':
264 input = InputQuotation;
265 break;
266 case '\'':
267 input = InputApostrophe;
268 break;
269 case ' ':
270 input = InputSpace;
271 break;
272 case '1': case '2': case '3': case '4': case '5':
273 case '6': case '7': case '8': case '9': case '0':
274 if (alphabeth.contains(lastChar)
275 && (!mathChars.contains(lastChar) || !numbers.contains(text.at(i - 1)))) {
276 input = InputAlpha;
277 } else {
278 if (input == InputAlpha && numbers.contains(lastChar))
279 input = InputAlpha;
280 else
281 input = InputNumber;
282 }
283 break;
284 case ':': {
285 input = InputAlpha;
286 QChar nextChar = QLatin1Char(' ');
287 if (i < text.length() - 1)
288 nextChar = text.at(i + 1);
289 if (state == StateStandard && !questionMark &&
290 lastChar != QLatin1Char(':') && nextChar != QLatin1Char(':')) {
291 for (int j = 0; j < i; ++j) {
292 if (format(j) == emptyFormat)
293 setFormat(j, 1, m_labelFormat);
294 }
295 }
296 break;
297 }
298 default: {
299 if (!questionMark && c == QLatin1Char('?'))
300 questionMark = true;
301 if (c.isLetter() || c == QLatin1Char('_'))
302 input = InputAlpha;
303 else
304 input = InputSep;
305 } break;
306 }
307 }
308
309 lastWasBackSlash = !lastWasBackSlash && c == QLatin1Char('\\');
310
311 if (input == InputAlpha)
312 buffer += c;
313
314 state = table[state][input];
315
316 switch (state) {
317 case StateStandard: {
318 setFormat(i, 1, emptyFormat);
319 if (makeLastStandard)
320 setFormat(i - 1, 1, emptyFormat);
321 makeLastStandard = false;
322 if (!buffer.isEmpty() && input != InputAlpha ) {
323 highlightKeyword(i, buffer);
324 buffer.clear();
325 }
326 } break;
327 case StateCommentStart1:
328 if (makeLastStandard)
329 setFormat(i - 1, 1, emptyFormat);
330 makeLastStandard = true;
331 buffer.resize(0);
332 break;
333 case StateCCommentStart2:
334 setFormat(i - 1, 2, m_commentFormat);
335 makeLastStandard = false;
336 buffer.resize(0);
337 break;
338 case StateCppCommentStart2:
339 setFormat(i - 1, 2, m_commentFormat);
340 makeLastStandard = false;
341 buffer.resize(0);
342 break;
343 case StateCComment:
344 if (makeLastStandard)
345 setFormat(i - 1, 1, emptyFormat);
346 makeLastStandard = false;
347 setFormat(i, 1, m_commentFormat);
348 buffer.resize(0);
349 break;
350 case StateCppComment:
351 if (makeLastStandard)
352 setFormat(i - 1, 1, emptyFormat);
353 makeLastStandard = false;
354 setFormat(i, 1, m_commentFormat);
355 buffer.resize(0);
356 break;
357 case StateCCommentEnd1:
358 if (makeLastStandard)
359 setFormat(i - 1, 1, emptyFormat);
360 makeLastStandard = false;
361 setFormat(i, 1, m_commentFormat);
362 buffer.resize(0);
363 break;
364 case StateCCommentEnd2:
365 if (makeLastStandard)
366 setFormat(i - 1, 1, emptyFormat);
367 makeLastStandard = false;
368 setFormat(i, 1, m_commentFormat);
369 buffer.resize(0);
370 break;
371 case StateStringStart:
372 if (makeLastStandard)
373 setFormat(i - 1, 1, emptyFormat);
374 makeLastStandard = false;
375 setFormat(i, 1, emptyFormat);
376 buffer.resize(0);
377 break;
378 case StateString:
379 if (makeLastStandard)
380 setFormat(i - 1, 1, emptyFormat);
381 makeLastStandard = false;
382 setFormat(i, 1, m_stringFormat);
383 buffer.resize(0);
384 break;
385 case StateStringEnd:
386 if (makeLastStandard)
387 setFormat(i - 1, 1, emptyFormat);
388 makeLastStandard = false;
389 setFormat(i, 1, emptyFormat);
390 buffer.resize(0);
391 break;
392 case StateString2Start:
393 if (makeLastStandard)
394 setFormat(i - 1, 1, emptyFormat);
395 makeLastStandard = false;
396 setFormat(i, 1, emptyFormat);
397 buffer.resize(0);
398 break;
399 case StateString2:
400 if (makeLastStandard)
401 setFormat(i - 1, 1, emptyFormat);
402 makeLastStandard = false;
403 setFormat(i, 1, m_stringFormat);
404 buffer.resize(0);
405 break;
406 case StateString2End:
407 if (makeLastStandard)
408 setFormat(i - 1, 1, emptyFormat);
409 makeLastStandard = false;
410 setFormat(i, 1, emptyFormat);
411 buffer.resize(0);
412 break;
413 case StateNumber:
414 if (makeLastStandard)
415 setFormat(i - 1, 1, emptyFormat);
416 makeLastStandard = false;
417 setFormat( i, 1, m_numberFormat);
418 buffer.resize(0);
419 break;
420 case StatePreProcessor:
421 if (makeLastStandard)
422 setFormat(i - 1, 1, emptyFormat);
423 makeLastStandard = false;
424 setFormat(i, 1, m_preProcessorFormat);
425 buffer.resize(0);
426 break;
427 }
428
429 lastChar = c;
430 i++;
431 if (i >= text.length())
432 break;
433 }
434
435 highlightKeyword(text.length(), buffer);
436
437 if (state == StateCComment
438 || state == StateCCommentEnd1
439 || state == StateCCommentStart2
440 ) {
441 state = StateCComment;
442 } else if (state == StateString) {
443 state = StateString;
444 } else if (state == StateString2) {
445 state = StateString2;
446 } else {
447 state = StateStandard;
448 }
449
450 setCurrentBlockState(state);
451}
452
453void QScriptHighlighter::highlightKeyword(int currentPos, const QString &buffer)
454{
455 if (buffer.isEmpty())
456 return;
457
458 if (buffer.at(0) == QLatin1Char('Q')) {
459 setFormat(currentPos - buffer.length(), buffer.length(), m_typeFormat);
460 } else {
461 if (qscriptKeywords().contains(buffer)) {
462 setFormat(currentPos - buffer.length(), buffer.length(), m_keywordFormat);
463 }
464 }
465}
466}
467
468QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.