PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/cssed-0.4.0/scintilla/src/LexMSSQL.cxx

#
C++ | 359 lines | 319 code | 28 blank | 12 comment | 128 complexity | 50899496d227e3b797292f4a2a2f1955 MD5 | raw file
Possible License(s): GPL-2.0
  1. // Scintilla source code edit control
  2. /** @file LexMSSQL.cxx
  3. ** Lexer for MSSQL.
  4. **/
  5. // By Filip Yaghob <fyaghob@gmail.com>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include "Platform.h"
  12. #include "PropSet.h"
  13. #include "Accessor.h"
  14. #include "KeyWords.h"
  15. #include "Scintilla.h"
  16. #include "SciLexer.h"
  17. #define KW_MSSQL_STATEMENTS 0
  18. #define KW_MSSQL_DATA_TYPES 1
  19. #define KW_MSSQL_SYSTEM_TABLES 2
  20. #define KW_MSSQL_GLOBAL_VARIABLES 3
  21. #define KW_MSSQL_FUNCTIONS 4
  22. #define KW_MSSQL_STORED_PROCEDURES 5
  23. #define KW_MSSQL_OPERATORS 6
  24. static bool isMSSQLOperator(char ch) {
  25. if (isascii(ch) && isalnum(ch))
  26. return false;
  27. // '.' left out as it is used to make up numbers
  28. if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
  29. ch == '-' || ch == '+' || ch == '=' || ch == '|' ||
  30. ch == '<' || ch == '>' || ch == '/' ||
  31. ch == '!' || ch == '~' || ch == '(' || ch == ')' ||
  32. ch == ',')
  33. return true;
  34. return false;
  35. }
  36. static char classifyWordSQL(unsigned int start,
  37. unsigned int end,
  38. WordList *keywordlists[],
  39. Accessor &styler,
  40. unsigned int actualState,
  41. unsigned int prevState) {
  42. char s[256];
  43. bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
  44. WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS];
  45. WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES];
  46. WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
  47. WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
  48. WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS];
  49. WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES];
  50. WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS];
  51. for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) {
  52. s[i] = static_cast<char>(tolower(styler[start + i]));
  53. s[i + 1] = '\0';
  54. }
  55. char chAttr = SCE_MSSQL_IDENTIFIER;
  56. if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) {
  57. if (kwGlobalVariables.InList(&s[2]))
  58. chAttr = SCE_MSSQL_GLOBAL_VARIABLE;
  59. } else if (wordIsNumber) {
  60. chAttr = SCE_MSSQL_NUMBER;
  61. } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
  62. // Look first in datatypes
  63. if (kwDataTypes.InList(s))
  64. chAttr = SCE_MSSQL_DATATYPE;
  65. else if (kwOperators.InList(s))
  66. chAttr = SCE_MSSQL_OPERATOR;
  67. else if (kwStatements.InList(s))
  68. chAttr = SCE_MSSQL_STATEMENT;
  69. else if (kwSystemTables.InList(s))
  70. chAttr = SCE_MSSQL_SYSTABLE;
  71. else if (kwFunctions.InList(s))
  72. chAttr = SCE_MSSQL_FUNCTION;
  73. else if (kwStoredProcedures.InList(s))
  74. chAttr = SCE_MSSQL_STORED_PROCEDURE;
  75. } else {
  76. if (kwOperators.InList(s))
  77. chAttr = SCE_MSSQL_OPERATOR;
  78. else if (kwStatements.InList(s))
  79. chAttr = SCE_MSSQL_STATEMENT;
  80. else if (kwSystemTables.InList(s))
  81. chAttr = SCE_MSSQL_SYSTABLE;
  82. else if (kwFunctions.InList(s))
  83. chAttr = SCE_MSSQL_FUNCTION;
  84. else if (kwStoredProcedures.InList(s))
  85. chAttr = SCE_MSSQL_STORED_PROCEDURE;
  86. else if (kwDataTypes.InList(s))
  87. chAttr = SCE_MSSQL_DATATYPE;
  88. }
  89. styler.ColourTo(end, chAttr);
  90. return chAttr;
  91. }
  92. static void ColouriseMSSQLDoc(unsigned int startPos, int length,
  93. int initStyle, WordList *keywordlists[], Accessor &styler) {
  94. styler.StartAt(startPos);
  95. bool fold = styler.GetPropertyInt("fold") != 0;
  96. int lineCurrent = styler.GetLine(startPos);
  97. int spaceFlags = 0;
  98. int state = initStyle;
  99. int prevState = initStyle;
  100. char chPrev = ' ';
  101. char chNext = styler[startPos];
  102. styler.StartSegment(startPos);
  103. unsigned int lengthDoc = startPos + length;
  104. for (unsigned int i = startPos; i < lengthDoc; i++) {
  105. char ch = chNext;
  106. chNext = styler.SafeGetCharAt(i + 1);
  107. if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
  108. int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
  109. int lev = indentCurrent;
  110. if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
  111. // Only non whitespace lines can be headers
  112. int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
  113. if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
  114. lev |= SC_FOLDLEVELHEADERFLAG;
  115. }
  116. }
  117. if (fold) {
  118. styler.SetLevel(lineCurrent, lev);
  119. }
  120. }
  121. if (styler.IsLeadByte(ch)) {
  122. chNext = styler.SafeGetCharAt(i + 2);
  123. chPrev = ' ';
  124. i += 1;
  125. continue;
  126. }
  127. // When the last char isn't part of the state (have to deal with it too)...
  128. if ( (state == SCE_MSSQL_IDENTIFIER) ||
  129. (state == SCE_MSSQL_STORED_PROCEDURE) ||
  130. (state == SCE_MSSQL_DATATYPE) ||
  131. //~ (state == SCE_MSSQL_COLUMN_NAME) ||
  132. (state == SCE_MSSQL_FUNCTION) ||
  133. //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) ||
  134. (state == SCE_MSSQL_VARIABLE)) {
  135. if (!iswordchar(ch)) {
  136. int stateTmp;
  137. if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) {
  138. styler.ColourTo(i - 1, state);
  139. stateTmp = state;
  140. } else
  141. stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
  142. prevState = state;
  143. if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE)
  144. state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
  145. else
  146. state = SCE_MSSQL_DEFAULT;
  147. }
  148. } else if (state == SCE_MSSQL_LINE_COMMENT) {
  149. if (ch == '\r' || ch == '\n') {
  150. styler.ColourTo(i - 1, state);
  151. prevState = state;
  152. state = SCE_MSSQL_DEFAULT;
  153. }
  154. } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) {
  155. if ((ch != '@') && !iswordchar(ch)) {
  156. classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
  157. prevState = state;
  158. state = SCE_MSSQL_DEFAULT;
  159. }
  160. }
  161. // If is the default or one of the above succeeded
  162. if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
  163. if (iswordstart(ch)) {
  164. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  165. prevState = state;
  166. state = SCE_MSSQL_IDENTIFIER;
  167. } else if (ch == '/' && chNext == '*') {
  168. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  169. prevState = state;
  170. state = SCE_MSSQL_COMMENT;
  171. } else if (ch == '-' && chNext == '-') {
  172. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  173. prevState = state;
  174. state = SCE_MSSQL_LINE_COMMENT;
  175. } else if (ch == '\'') {
  176. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  177. prevState = state;
  178. state = SCE_MSSQL_STRING;
  179. } else if (ch == '"') {
  180. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  181. prevState = state;
  182. state = SCE_MSSQL_COLUMN_NAME;
  183. } else if (ch == '[') {
  184. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  185. prevState = state;
  186. state = SCE_MSSQL_COLUMN_NAME_2;
  187. } else if (isMSSQLOperator(ch)) {
  188. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  189. styler.ColourTo(i, SCE_MSSQL_OPERATOR);
  190. //~ style = SCE_MSSQL_DEFAULT;
  191. prevState = state;
  192. state = SCE_MSSQL_DEFAULT;
  193. } else if (ch == '@') {
  194. styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
  195. prevState = state;
  196. if (chNext == '@') {
  197. state = SCE_MSSQL_GLOBAL_VARIABLE;
  198. // i += 2;
  199. } else
  200. state = SCE_MSSQL_VARIABLE;
  201. }
  202. // When the last char is part of the state...
  203. } else if (state == SCE_MSSQL_COMMENT) {
  204. if (ch == '/' && chPrev == '*') {
  205. if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) &&
  206. (styler.GetStartSegment() == startPos)))) {
  207. styler.ColourTo(i, state);
  208. //~ state = SCE_MSSQL_COMMENT;
  209. prevState = state;
  210. state = SCE_MSSQL_DEFAULT;
  211. }
  212. }
  213. } else if (state == SCE_MSSQL_STRING) {
  214. if (ch == '\'') {
  215. if ( chNext == '\'' ) {
  216. i++;
  217. ch = chNext;
  218. chNext = styler.SafeGetCharAt(i + 1);
  219. } else {
  220. styler.ColourTo(i, state);
  221. prevState = state;
  222. state = SCE_MSSQL_DEFAULT;
  223. //i++;
  224. }
  225. //ch = chNext;
  226. //chNext = styler.SafeGetCharAt(i + 1);
  227. }
  228. } else if (state == SCE_MSSQL_COLUMN_NAME) {
  229. if (ch == '"') {
  230. if (chNext == '"') {
  231. i++;
  232. ch = chNext;
  233. chNext = styler.SafeGetCharAt(i + 1);
  234. } else {
  235. styler.ColourTo(i, state);
  236. prevState = state;
  237. state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
  238. //i++;
  239. }
  240. }
  241. } else if (state == SCE_MSSQL_COLUMN_NAME_2) {
  242. if (ch == ']') {
  243. styler.ColourTo(i, state);
  244. prevState = state;
  245. state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
  246. //i++;
  247. }
  248. }
  249. chPrev = ch;
  250. }
  251. styler.ColourTo(lengthDoc - 1, state);
  252. }
  253. static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  254. bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
  255. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  256. unsigned int endPos = startPos + length;
  257. int visibleChars = 0;
  258. int lineCurrent = styler.GetLine(startPos);
  259. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  260. int levelCurrent = levelPrev;
  261. char chNext = styler[startPos];
  262. bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT);
  263. char s[10];
  264. for (unsigned int i = startPos; i < endPos; i++) {
  265. char ch = chNext;
  266. chNext = styler.SafeGetCharAt(i + 1);
  267. int style = styler.StyleAt(i);
  268. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  269. // Comment folding
  270. if (foldComment) {
  271. if (!inComment && (style == SCE_MSSQL_COMMENT))
  272. levelCurrent++;
  273. else if (inComment && (style != SCE_MSSQL_COMMENT))
  274. levelCurrent--;
  275. inComment = (style == SCE_MSSQL_COMMENT);
  276. }
  277. if (style == SCE_MSSQL_STATEMENT) {
  278. // Folding between begin and end
  279. if (ch == 'b' || ch == 'e') {
  280. for (unsigned int j = 0; j < 5; j++) {
  281. if (!iswordchar(styler[i + j])) {
  282. break;
  283. }
  284. s[j] = styler[i + j];
  285. s[j + 1] = '\0';
  286. }
  287. if (strcmp(s, "begin") == 0) {
  288. levelCurrent++;
  289. }
  290. if (strcmp(s, "end") == 0) {
  291. levelCurrent--;
  292. }
  293. }
  294. }
  295. if (atEOL) {
  296. int lev = levelPrev;
  297. if (visibleChars == 0 && foldCompact)
  298. lev |= SC_FOLDLEVELWHITEFLAG;
  299. if ((levelCurrent > levelPrev) && (visibleChars > 0))
  300. lev |= SC_FOLDLEVELHEADERFLAG;
  301. if (lev != styler.LevelAt(lineCurrent)) {
  302. styler.SetLevel(lineCurrent, lev);
  303. }
  304. lineCurrent++;
  305. levelPrev = levelCurrent;
  306. visibleChars = 0;
  307. }
  308. if (!isspacechar(ch))
  309. visibleChars++;
  310. }
  311. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  312. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  313. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  314. }
  315. static const char * const sqlWordListDesc[] = {
  316. "Statements",
  317. "Data Types",
  318. "System tables",
  319. "Global variables",
  320. "Functions",
  321. "System Stored Procedures",
  322. "Operators",
  323. 0,
  324. };
  325. LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);