PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/stc/scintilla/lexers/LexCOBOL.cxx

https://bitbucket.org/cafu/cafu
C++ | 379 lines | 334 code | 28 blank | 17 comment | 150 complexity | 771a54461147db5b2e9bf09f5f280d66 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0, BSD-3-Clause, LGPL-3.0, LGPL-2.1, AGPL-3.0
  1. // Scintilla source code edit control
  2. /** @file LexCOBOL.cxx
  3. ** Lexer for COBOL
  4. ** Based on LexPascal.cxx
  5. ** Written by Laurent le Tynevez
  6. ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
  7. ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
  8. ** Updated by Rod Falck, Aug 2006 Converted to COBOL
  9. **/
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #include <assert.h>
  15. #include <ctype.h>
  16. #include "ILexer.h"
  17. #include "Scintilla.h"
  18. #include "SciLexer.h"
  19. #include "WordList.h"
  20. #include "LexAccessor.h"
  21. #include "Accessor.h"
  22. #include "StyleContext.h"
  23. #include "CharacterSet.h"
  24. #include "LexerModule.h"
  25. #ifdef SCI_NAMESPACE
  26. using namespace Scintilla;
  27. #endif
  28. #define IN_DIVISION 0x01
  29. #define IN_DECLARATIVES 0x02
  30. #define IN_SECTION 0x04
  31. #define IN_PARAGRAPH 0x08
  32. #define IN_FLAGS 0xF
  33. #define NOT_HEADER 0x10
  34. inline bool isCOBOLoperator(char ch)
  35. {
  36. return isoperator(ch);
  37. }
  38. inline bool isCOBOLwordchar(char ch)
  39. {
  40. return isascii(ch) && (isalnum(ch) || ch == '-');
  41. }
  42. inline bool isCOBOLwordstart(char ch)
  43. {
  44. return isascii(ch) && isalnum(ch);
  45. }
  46. static int CountBits(int nBits)
  47. {
  48. int count = 0;
  49. for (int i = 0; i < 32; ++i)
  50. {
  51. count += nBits & 1;
  52. nBits >>= 1;
  53. }
  54. return count;
  55. }
  56. static void getRange(unsigned int start,
  57. unsigned int end,
  58. Accessor &styler,
  59. char *s,
  60. unsigned int len) {
  61. unsigned int i = 0;
  62. while ((i < end - start + 1) && (i < len-1)) {
  63. s[i] = static_cast<char>(tolower(styler[start + i]));
  64. i++;
  65. }
  66. s[i] = '\0';
  67. }
  68. static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) {
  69. styler.ColourTo(end, attr);
  70. }
  71. static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) {
  72. int ret = 0;
  73. WordList& a_keywords = *keywordlists[0];
  74. WordList& b_keywords = *keywordlists[1];
  75. WordList& c_keywords = *keywordlists[2];
  76. char s[100];
  77. getRange(start, end, styler, s, sizeof(s));
  78. char chAttr = SCE_C_IDENTIFIER;
  79. if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) {
  80. chAttr = SCE_C_NUMBER;
  81. char *p = s + 1;
  82. while (*p) {
  83. if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) {
  84. chAttr = SCE_C_IDENTIFIER;
  85. break;
  86. }
  87. ++p;
  88. }
  89. }
  90. else {
  91. if (a_keywords.InList(s)) {
  92. chAttr = SCE_C_WORD;
  93. }
  94. else if (b_keywords.InList(s)) {
  95. chAttr = SCE_C_WORD2;
  96. }
  97. else if (c_keywords.InList(s)) {
  98. chAttr = SCE_C_UUID;
  99. }
  100. }
  101. if (*bAarea) {
  102. if (strcmp(s, "division") == 0) {
  103. ret = IN_DIVISION;
  104. // we've determined the containment, anything else is just ignored for those purposes
  105. *bAarea = false;
  106. } else if (strcmp(s, "declaratives") == 0) {
  107. ret = IN_DIVISION | IN_DECLARATIVES;
  108. if (nContainment & IN_DECLARATIVES)
  109. ret |= NOT_HEADER | IN_SECTION;
  110. // we've determined the containment, anything else is just ignored for those purposes
  111. *bAarea = false;
  112. } else if (strcmp(s, "section") == 0) {
  113. ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION;
  114. // we've determined the containment, anything else is just ignored for those purposes
  115. *bAarea = false;
  116. } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) {
  117. ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER;
  118. } else {
  119. ret = nContainment | IN_PARAGRAPH;
  120. }
  121. }
  122. ColourTo(styler, end, chAttr);
  123. return ret;
  124. }
  125. static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
  126. Accessor &styler) {
  127. styler.StartAt(startPos);
  128. int state = initStyle;
  129. if (state == SCE_C_CHARACTER) // Does not leak onto next line
  130. state = SCE_C_DEFAULT;
  131. char chPrev = ' ';
  132. char chNext = styler[startPos];
  133. unsigned int lengthDoc = startPos + length;
  134. int nContainment;
  135. int currentLine = styler.GetLine(startPos);
  136. if (currentLine > 0) {
  137. styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
  138. nContainment = styler.GetLineState(currentLine);
  139. nContainment &= ~NOT_HEADER;
  140. } else {
  141. styler.SetLineState(currentLine, 0);
  142. nContainment = 0;
  143. }
  144. styler.StartSegment(startPos);
  145. bool bNewLine = true;
  146. bool bAarea = !isspacechar(chNext);
  147. int column = 0;
  148. for (unsigned int i = startPos; i < lengthDoc; i++) {
  149. char ch = chNext;
  150. chNext = styler.SafeGetCharAt(i + 1);
  151. ++column;
  152. if (bNewLine) {
  153. column = 0;
  154. }
  155. if (column <= 1 && !bAarea) {
  156. bAarea = !isspacechar(ch);
  157. }
  158. bool bSetNewLine = false;
  159. if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
  160. // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
  161. // Avoid triggering two times on Dos/Win
  162. // End of line
  163. if (state == SCE_C_CHARACTER) {
  164. ColourTo(styler, i, state);
  165. state = SCE_C_DEFAULT;
  166. }
  167. styler.SetLineState(currentLine, nContainment);
  168. currentLine++;
  169. bSetNewLine = true;
  170. if (nContainment & NOT_HEADER)
  171. nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION);
  172. }
  173. if (styler.IsLeadByte(ch)) {
  174. chNext = styler.SafeGetCharAt(i + 2);
  175. chPrev = ' ';
  176. i += 1;
  177. continue;
  178. }
  179. if (state == SCE_C_DEFAULT) {
  180. if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) {
  181. ColourTo(styler, i-1, state);
  182. state = SCE_C_IDENTIFIER;
  183. } else if (column == 6 && ch == '*') {
  184. // Cobol comment line: asterisk in column 7.
  185. ColourTo(styler, i-1, state);
  186. state = SCE_C_COMMENTLINE;
  187. } else if (ch == '*' && chNext == '>') {
  188. // Cobol inline comment: asterisk, followed by greater than.
  189. ColourTo(styler, i-1, state);
  190. state = SCE_C_COMMENTLINE;
  191. } else if (column == 0 && ch == '*' && chNext != '*') {
  192. ColourTo(styler, i-1, state);
  193. state = SCE_C_COMMENTLINE;
  194. } else if (column == 0 && ch == '/' && chNext != '*') {
  195. ColourTo(styler, i-1, state);
  196. state = SCE_C_COMMENTLINE;
  197. } else if (column == 0 && ch == '*' && chNext == '*') {
  198. ColourTo(styler, i-1, state);
  199. state = SCE_C_COMMENTDOC;
  200. } else if (column == 0 && ch == '/' && chNext == '*') {
  201. ColourTo(styler, i-1, state);
  202. state = SCE_C_COMMENTDOC;
  203. } else if (ch == '"') {
  204. ColourTo(styler, i-1, state);
  205. state = SCE_C_STRING;
  206. } else if (ch == '\'') {
  207. ColourTo(styler, i-1, state);
  208. state = SCE_C_CHARACTER;
  209. } else if (ch == '?' && column == 0) {
  210. ColourTo(styler, i-1, state);
  211. state = SCE_C_PREPROCESSOR;
  212. } else if (isCOBOLoperator(ch)) {
  213. ColourTo(styler, i-1, state);
  214. ColourTo(styler, i, SCE_C_OPERATOR);
  215. }
  216. } else if (state == SCE_C_IDENTIFIER) {
  217. if (!isCOBOLwordchar(ch)) {
  218. int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea);
  219. if(lStateChange != 0) {
  220. styler.SetLineState(currentLine, lStateChange);
  221. nContainment = lStateChange;
  222. }
  223. state = SCE_C_DEFAULT;
  224. chNext = styler.SafeGetCharAt(i + 1);
  225. if (ch == '"') {
  226. state = SCE_C_STRING;
  227. } else if (ch == '\'') {
  228. state = SCE_C_CHARACTER;
  229. } else if (isCOBOLoperator(ch)) {
  230. ColourTo(styler, i, SCE_C_OPERATOR);
  231. }
  232. }
  233. } else {
  234. if (state == SCE_C_PREPROCESSOR) {
  235. if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
  236. ColourTo(styler, i-1, state);
  237. state = SCE_C_DEFAULT;
  238. }
  239. } else if (state == SCE_C_COMMENT) {
  240. if (ch == '\r' || ch == '\n') {
  241. ColourTo(styler, i, state);
  242. state = SCE_C_DEFAULT;
  243. }
  244. } else if (state == SCE_C_COMMENTDOC) {
  245. if (ch == '\r' || ch == '\n') {
  246. if (((i > styler.GetStartSegment() + 2) || (
  247. (initStyle == SCE_C_COMMENTDOC) &&
  248. (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
  249. ColourTo(styler, i, state);
  250. state = SCE_C_DEFAULT;
  251. }
  252. }
  253. } else if (state == SCE_C_COMMENTLINE) {
  254. if (ch == '\r' || ch == '\n') {
  255. ColourTo(styler, i-1, state);
  256. state = SCE_C_DEFAULT;
  257. }
  258. } else if (state == SCE_C_STRING) {
  259. if (ch == '"') {
  260. ColourTo(styler, i, state);
  261. state = SCE_C_DEFAULT;
  262. }
  263. } else if (state == SCE_C_CHARACTER) {
  264. if (ch == '\'') {
  265. ColourTo(styler, i, state);
  266. state = SCE_C_DEFAULT;
  267. }
  268. }
  269. }
  270. chPrev = ch;
  271. bNewLine = bSetNewLine;
  272. if (bNewLine)
  273. {
  274. bAarea = false;
  275. }
  276. }
  277. ColourTo(styler, lengthDoc - 1, state);
  278. }
  279. static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[],
  280. Accessor &styler) {
  281. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  282. unsigned int endPos = startPos + length;
  283. int visibleChars = 0;
  284. int lineCurrent = styler.GetLine(startPos);
  285. int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF;
  286. char chNext = styler[startPos];
  287. bool bNewLine = true;
  288. bool bAarea = !isspacechar(chNext);
  289. int column = 0;
  290. bool bComment = false;
  291. for (unsigned int i = startPos; i < endPos; i++) {
  292. char ch = chNext;
  293. chNext = styler.SafeGetCharAt(i + 1);
  294. ++column;
  295. if (bNewLine) {
  296. column = 0;
  297. bComment = (ch == '*' || ch == '/' || ch == '?');
  298. }
  299. if (column <= 1 && !bAarea) {
  300. bAarea = !isspacechar(ch);
  301. }
  302. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  303. if (atEOL) {
  304. int nContainment = styler.GetLineState(lineCurrent);
  305. int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE;
  306. if (bAarea && !bComment)
  307. --lev;
  308. if (visibleChars == 0 && foldCompact)
  309. lev |= SC_FOLDLEVELWHITEFLAG;
  310. if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment)
  311. lev |= SC_FOLDLEVELHEADERFLAG;
  312. if (lev != styler.LevelAt(lineCurrent)) {
  313. styler.SetLevel(lineCurrent, lev);
  314. }
  315. if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) {
  316. // this level is at the same level or less than the previous line
  317. // therefore these is nothing for the previous header to collapse, so remove the header
  318. styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
  319. }
  320. levelPrev = lev;
  321. visibleChars = 0;
  322. bAarea = false;
  323. bNewLine = true;
  324. lineCurrent++;
  325. } else {
  326. bNewLine = false;
  327. }
  328. if (!isspacechar(ch))
  329. visibleChars++;
  330. }
  331. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  332. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  333. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  334. }
  335. static const char * const COBOLWordListDesc[] = {
  336. "A Keywords",
  337. "B Keywords",
  338. "Extended Keywords",
  339. 0
  340. };
  341. LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc);