1 ///////////////////////////////////////////////////////////////////////////
4 // Updated: 19-Jul-1998
6 // Copyright: Ferdinand Prantl, portions by Stcherbatchenko Andrei
7 // E-mail: prantl@ff.cuni.cz
9 // SQL syntax highlighing definition
11 // You are free to use or modify this code to the following restrictions:
12 // - Acknowledge me somewhere in your about box, simple "Parts of code by.."
13 // will be enough. If you can't (or don't want to), contact me personally.
14 // - LEAVE THIS HEADER INTACT
15 ////////////////////////////////////////////////////////////////////////////
18 #include "crystallineparser.h"
19 #include "../SyntaxColors.h"
20 #include "../utils/string_util.h"
26 // C++ keywords (MSVC5.0 + POET5.0)
27 static LPCTSTR s_apszSqlKeywordList[] =
48 static LPCTSTR s_apszUser1KeywordList[] =
63 IsSqlKeyword (LPCTSTR pszChars, int nLength)
65 return ISXKEYWORDI (s_apszSqlKeywordList, pszChars, nLength);
69 IsUser1Keyword (LPCTSTR pszChars, int nLength)
71 return ISXKEYWORDI (s_apszUser1KeywordList, pszChars, nLength);
75 CrystalLineParser::ParseLineSql (DWORD dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
78 return dwCookie & COOKIE_EXT_COMMENT;
80 bool bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
81 bool bRedefineBlock = true;
82 bool bWasCommentStart = false;
83 bool bDecIndex = false;
87 for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
91 // CharNext did not advance, so we're at the end of the string
92 // and we already handled this character, so stop
101 if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
103 DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
105 else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
107 DEFINE_BLOCK (nPos, COLORINDEX_STRING);
111 if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (*::CharPrev(pszChars, pszChars + nPos)) && !xisalpha (*::CharNext(pszChars + nPos))))
113 DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
117 DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
118 bRedefineBlock = true;
123 bRedefineBlock = false;
128 // Can be bigger than length if there is binary data
129 // See bug #1474782 Crash when comparing SQL with with binary data
130 if (I >= nLength || pszChars[I] == 0)
133 if (dwCookie & COOKIE_COMMENT)
135 DEFINE_BLOCK (I, COLORINDEX_COMMENT);
136 dwCookie |= COOKIE_COMMENT;
140 // String constant "...."
141 if (dwCookie & COOKIE_STRING)
143 if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
145 dwCookie &= ~COOKIE_STRING;
146 bRedefineBlock = true;
151 // Char constant '..'
152 if (dwCookie & COOKIE_CHAR)
154 if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
156 dwCookie &= ~COOKIE_CHAR;
157 bRedefineBlock = true;
162 // Extended comment /*....*/
163 if (dwCookie & COOKIE_EXT_COMMENT)
165 // if (I > 0 && pszChars[I] == '/' && pszChars[nPrevI] == '*')
166 if ((I > 1 && pszChars[I] == '/' && pszChars[nPrevI] == '*' /*&& *::CharPrev(pszChars, pszChars + nPrevI) != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[nPrevI] == '*'))
168 dwCookie &= ~COOKIE_EXT_COMMENT;
169 bRedefineBlock = true;
171 bWasCommentStart = false;
175 if (I > 0 && pszChars[I] == '/' && pszChars[nPrevI] == '/')
177 DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
178 dwCookie |= COOKIE_COMMENT;
183 if (pszChars[I] == '"')
185 DEFINE_BLOCK (I, COLORINDEX_STRING);
186 dwCookie |= COOKIE_STRING;
189 if (pszChars[I] == '\'')
191 // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
192 if (!I || !xisalnum (pszChars[nPrevI]))
194 DEFINE_BLOCK (I, COLORINDEX_STRING);
195 dwCookie |= COOKIE_CHAR;
199 if (I > 0 && pszChars[I] == '*' && pszChars[nPrevI] == '/')
201 DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
202 dwCookie |= COOKIE_EXT_COMMENT;
203 bWasCommentStart = true;
207 bWasCommentStart = false;
211 if (!xisspace (pszChars[I]))
216 continue; // We don't need to extract keywords,
217 // for faster parsing skip the rest of loop
219 if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[nPrevI]) && !xisalpha (pszChars[I + 1])))
221 if (nIdentBegin == -1)
226 if (nIdentBegin >= 0)
228 if (IsSqlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
230 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
232 else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
234 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
236 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
238 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
242 bool bFunction = false;
244 for (int j = I; j < nLength; j++)
246 if (!xisspace (pszChars[j]))
248 if (pszChars[j] == '(')
257 DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
260 bRedefineBlock = true;
267 if (nIdentBegin >= 0)
269 if (IsSqlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
271 DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
273 else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
275 DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
277 else if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
279 DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
283 bool bFunction = false;
285 for (int j = I; j < nLength; j++)
287 if (!xisspace (pszChars[j]))
289 if (pszChars[j] == '(')
298 DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
303 if (pszChars[nLength - 1] != '\\' || IsMBSTrail(pszChars, nLength - 1))
304 dwCookie &= COOKIE_EXT_COMMENT;