1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
35 #include "highlighterexception.h"
36 #include "progressdata.h"
37 #include "highlightdefinition.h"
40 #include <QtCore/QStringList>
44 using namespace TextEditor;
45 using namespace Internal;
47 const QLatin1Char Rule::kBackSlash('\\');
48 const QLatin1Char Rule::kUnderscore('_');
49 const QLatin1Char Rule::kDot('.');
50 const QLatin1Char Rule::kPlus('+');
51 const QLatin1Char Rule::kMinus('-');
52 const QLatin1Char Rule::kZero('0');
53 const QLatin1Char Rule::kQuote('\"');
54 const QLatin1Char Rule::kSingleQuote('\'');
55 const QLatin1Char Rule::kQuestion('?');
56 const QLatin1Char Rule::kX('x');
57 const QLatin1Char Rule::kA('a');
58 const QLatin1Char Rule::kB('b');
59 const QLatin1Char Rule::kE('e');
60 const QLatin1Char Rule::kF('f');
61 const QLatin1Char Rule::kN('n');
62 const QLatin1Char Rule::kR('r');
63 const QLatin1Char Rule::kT('t');
64 const QLatin1Char Rule::kV('v');
65 const QLatin1Char Rule::kOpeningBrace('{');
66 const QLatin1Char Rule::kClosingBrace('}');
68 Rule::Rule(bool consumesNonSpace) :
69 m_lookAhead(false), m_firstNonSpace(false), m_column(-1), m_consumesNonSpace(consumesNonSpace)
75 void Rule::setContext(const QString &context)
76 { m_context = context; }
78 const QString &Rule::context() const
81 void Rule::setItemData(const QString &itemData)
82 { m_itemData = itemData; }
84 const QString &Rule::itemData() const
85 { return m_itemData; }
87 void Rule::setBeginRegion(const QString &begin)
88 { m_beginRegion = begin; }
90 const QString &Rule::beginRegion() const
91 { return m_beginRegion; }
93 void Rule::setEndRegion(const QString &end)
94 { m_endRegion = end; }
96 const QString &Rule::endRegion() const
97 { return m_endRegion; }
99 void Rule::setLookAhead(const QString &lookAhead)
100 { m_lookAhead = toBool(lookAhead); }
102 bool Rule::isLookAhead() const
103 { return m_lookAhead; }
105 void Rule::setFirstNonSpace(const QString &firstNonSpace)
106 { m_firstNonSpace = toBool(firstNonSpace); }
108 bool Rule::isFirstNonSpace() const
109 { return m_firstNonSpace; }
111 void Rule::setColumn(const QString &column)
114 m_column = column.toInt(&ok);
119 int Rule::column() const
122 void Rule::addChild(const QSharedPointer<Rule> &rule)
123 { m_children.append(rule); }
125 bool Rule::hasChildren() const
126 { return !m_children.isEmpty(); }
128 const QList<QSharedPointer<Rule> > &Rule::children() const
129 { return m_children; }
131 void Rule::setDefinition(const QSharedPointer<HighlightDefinition> &definition)
132 { m_definition = definition; }
134 const QSharedPointer<HighlightDefinition> &Rule::definition() const
135 { return m_definition; }
137 template <class predicate_t>
138 bool Rule::predicateMatchSucceed(const QString &text,
140 ProgressData *progress,
141 const predicate_t &p) const
143 int original = progress->offset();
144 while (progress->offset() < length && p(text.at(progress->offset())))
145 progress->incrementOffset();
147 if (original != progress->offset())
153 bool Rule::charPredicateMatchSucceed(const QString &text,
155 ProgressData *progress,
156 bool (QChar::* predicate)() const) const
158 return predicateMatchSucceed(text, length, progress, std::mem_fun_ref(predicate));
161 bool Rule::charPredicateMatchSucceed(const QString &text,
163 ProgressData *progress,
164 bool (*predicate)(const QChar &)) const
166 return predicateMatchSucceed(text, length, progress, std::ptr_fun(predicate));
169 bool Rule::matchSucceed(const QString &text, const int length, ProgressData *progress)
171 if (m_firstNonSpace && !progress->isOnlySpacesSoFar())
174 if (m_column != -1 && m_column != progress->offset())
177 int original = progress->offset();
178 if (doMatchSucceed(text, length, progress)) {
179 if (progress->isOnlySpacesSoFar() && !m_lookAhead && m_consumesNonSpace)
180 progress->setOnlySpacesSoFar(false);
183 progress->setOffset(original);
191 Rule *Rule::clone() const
192 { return doClone(); }
194 void Rule::progressFinished()
195 { doProgressFinished(); }
197 bool Rule::matchCharacter(const QString &text,
199 ProgressData *progress,
201 bool saveRestoreOffset) const
204 Q_ASSERT(progress->offset() < length);
206 if (text.at(progress->offset()) == c) {
207 if (saveRestoreOffset)
208 progress->saveOffset();
209 progress->incrementOffset();
216 bool Rule::matchEscapeSequence(const QString &text,
218 ProgressData *progress,
219 bool saveRestoreOffset) const
221 if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) {
223 if (progress->offset() < length) {
224 const QChar &c = text.at(progress->offset());
225 if (c == kA || c == kB || c == kE || c == kF || c == kN || c == kR || c == kT ||
226 c == kV || c == kQuestion || c == kSingleQuote || c == kQuote || c == kBackSlash) {
227 progress->incrementOffset();
229 } else if (saveRestoreOffset) {
230 progress->restoreOffset();
232 } else if (saveRestoreOffset) {
233 progress->restoreOffset();
240 bool Rule::matchOctalSequence(const QString &text,
242 ProgressData *progress,
243 bool saveRestoreOffset) const
245 // An octal sequence is identified as in the C++ Standard.
246 // octal-escape-sequence:
248 // \ octal-digit octal-digit
249 // \ octal-digit octal-digit octal-digit
251 if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) {
254 while (progress->offset() < length &&
256 isOctalDigit(text.at(progress->offset()))) {
258 progress->incrementOffset();
263 else if (saveRestoreOffset)
264 progress->restoreOffset();
270 bool Rule::matchHexSequence(const QString &text,
272 ProgressData *progress,
273 bool saveRestoreOffset) const
275 // An hex sequence is identified as in the C++ Standard.
276 // hexadecimal-escape-sequence:
277 // \x hexadecimal-digit
278 // hexadecimal-escape-sequence hexadecimal-digit
280 if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) {
282 if (progress->offset() < length && matchCharacter(text, length, progress, kX, false)) {
284 while (progress->offset() < length && isHexDigit(text.at(progress->offset()))) {
287 progress->incrementOffset();
292 else if (saveRestoreOffset)
293 progress->restoreOffset();
294 } else if (saveRestoreOffset) {
295 progress->restoreOffset();