PageRenderTime 73ms CodeModel.GetById 41ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/scintilla/lexers/LexTAL.cxx

https://gitlab.com/Smileyt/KomodoEdit
C++ | 399 lines | 359 code | 27 blank | 13 comment | 143 complexity | fdc1f5e860dd1eed9f0e68a2fda19bc5 MD5 | raw file
  1. // Scintilla source code edit control
  2. /** @file LexTAL.cxx
  3. ** Lexer for TAL
  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 TAL
  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. inline bool isTALoperator(char ch)
  29. {
  30. return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch);
  31. }
  32. inline bool isTALwordchar(char ch)
  33. {
  34. return ch == '$' || ch == '^' || iswordchar(ch);
  35. }
  36. inline bool isTALwordstart(char ch)
  37. {
  38. return ch == '$' || ch == '^' || iswordstart(ch);
  39. }
  40. static void getRange(unsigned int start,
  41. unsigned int end,
  42. Accessor &styler,
  43. char *s,
  44. unsigned int len) {
  45. unsigned int i = 0;
  46. while ((i < end - start + 1) && (i < len-1)) {
  47. s[i] = static_cast<char>(tolower(styler[start + i]));
  48. i++;
  49. }
  50. s[i] = '\0';
  51. }
  52. static bool IsStreamCommentStyle(int style) {
  53. return style == SCE_C_COMMENT ||
  54. style == SCE_C_COMMENTDOC ||
  55. style == SCE_C_COMMENTDOCKEYWORD ||
  56. style == SCE_C_COMMENTDOCKEYWORDERROR;
  57. }
  58. static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
  59. if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
  60. styler.ColourTo(end, SCE_C_REGEX);
  61. } else
  62. styler.ColourTo(end, attr);
  63. }
  64. // returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
  65. static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
  66. int ret = 0;
  67. WordList& keywords = *keywordlists[0];
  68. WordList& builtins = *keywordlists[1];
  69. WordList& nonreserved_keywords = *keywordlists[2];
  70. char s[100];
  71. getRange(start, end, styler, s, sizeof(s));
  72. char chAttr = SCE_C_IDENTIFIER;
  73. if (isdigit(s[0]) || (s[0] == '.')) {
  74. chAttr = SCE_C_NUMBER;
  75. }
  76. else {
  77. if (keywords.InList(s)) {
  78. chAttr = SCE_C_WORD;
  79. if (strcmp(s, "asm") == 0) {
  80. ret = 2;
  81. }
  82. else if (strcmp(s, "end") == 0) {
  83. ret = -1;
  84. }
  85. }
  86. else if (s[0] == '$' || builtins.InList(s)) {
  87. chAttr = SCE_C_WORD2;
  88. }
  89. else if (nonreserved_keywords.InList(s)) {
  90. chAttr = SCE_C_UUID;
  91. }
  92. }
  93. ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
  94. return ret;
  95. }
  96. static int classifyFoldPointTAL(const char* s) {
  97. int lev = 0;
  98. if (!(isdigit(s[0]) || (s[0] == '.'))) {
  99. if (strcmp(s, "begin") == 0 ||
  100. strcmp(s, "block") == 0) {
  101. lev=1;
  102. } else if (strcmp(s, "end") == 0) {
  103. lev=-1;
  104. }
  105. }
  106. return lev;
  107. }
  108. static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
  109. Accessor &styler) {
  110. styler.StartAt(startPos);
  111. int state = initStyle;
  112. if (state == SCE_C_CHARACTER) // Does not leak onto next line
  113. state = SCE_C_DEFAULT;
  114. char chPrev = ' ';
  115. char chNext = styler[startPos];
  116. unsigned int lengthDoc = startPos + length;
  117. bool bInClassDefinition;
  118. int currentLine = styler.GetLine(startPos);
  119. if (currentLine > 0) {
  120. styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
  121. bInClassDefinition = (styler.GetLineState(currentLine) == 1);
  122. } else {
  123. styler.SetLineState(currentLine, 0);
  124. bInClassDefinition = false;
  125. }
  126. bool bInAsm = (state == SCE_C_REGEX);
  127. if (bInAsm)
  128. state = SCE_C_DEFAULT;
  129. styler.StartSegment(startPos);
  130. int visibleChars = 0;
  131. for (unsigned int i = startPos; i < lengthDoc; i++) {
  132. char ch = chNext;
  133. chNext = styler.SafeGetCharAt(i + 1);
  134. if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
  135. // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
  136. // Avoid triggering two times on Dos/Win
  137. // End of line
  138. if (state == SCE_C_CHARACTER) {
  139. ColourTo(styler, i, state, bInAsm);
  140. state = SCE_C_DEFAULT;
  141. }
  142. visibleChars = 0;
  143. currentLine++;
  144. styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
  145. }
  146. if (styler.IsLeadByte(ch)) {
  147. chNext = styler.SafeGetCharAt(i + 2);
  148. chPrev = ' ';
  149. i += 1;
  150. continue;
  151. }
  152. if (state == SCE_C_DEFAULT) {
  153. if (isTALwordstart(ch)) {
  154. ColourTo(styler, i-1, state, bInAsm);
  155. state = SCE_C_IDENTIFIER;
  156. } else if (ch == '!' && chNext != '*') {
  157. ColourTo(styler, i-1, state, bInAsm);
  158. state = SCE_C_COMMENT;
  159. } else if (ch == '!' && chNext == '*') {
  160. ColourTo(styler, i-1, state, bInAsm);
  161. state = SCE_C_COMMENTDOC;
  162. } else if (ch == '-' && chNext == '-') {
  163. ColourTo(styler, i-1, state, bInAsm);
  164. state = SCE_C_COMMENTLINE;
  165. } else if (ch == '"') {
  166. ColourTo(styler, i-1, state, bInAsm);
  167. state = SCE_C_STRING;
  168. } else if (ch == '?' && visibleChars == 0) {
  169. ColourTo(styler, i-1, state, bInAsm);
  170. state = SCE_C_PREPROCESSOR;
  171. } else if (isTALoperator(ch)) {
  172. ColourTo(styler, i-1, state, bInAsm);
  173. ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
  174. }
  175. } else if (state == SCE_C_IDENTIFIER) {
  176. if (!isTALwordchar(ch)) {
  177. int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
  178. if(lStateChange == 1) {
  179. styler.SetLineState(currentLine, 1);
  180. bInClassDefinition = true;
  181. } else if(lStateChange == 2) {
  182. bInAsm = true;
  183. } else if(lStateChange == -1) {
  184. styler.SetLineState(currentLine, 0);
  185. bInClassDefinition = false;
  186. bInAsm = false;
  187. }
  188. state = SCE_C_DEFAULT;
  189. chNext = styler.SafeGetCharAt(i + 1);
  190. if (ch == '!' && chNext != '*') {
  191. state = SCE_C_COMMENT;
  192. } else if (ch == '!' && chNext == '*') {
  193. ColourTo(styler, i-1, state, bInAsm);
  194. state = SCE_C_COMMENTDOC;
  195. } else if (ch == '-' && chNext == '-') {
  196. state = SCE_C_COMMENTLINE;
  197. } else if (ch == '"') {
  198. state = SCE_C_STRING;
  199. } else if (isTALoperator(ch)) {
  200. ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
  201. }
  202. }
  203. } else {
  204. if (state == SCE_C_PREPROCESSOR) {
  205. if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
  206. ColourTo(styler, i-1, state, bInAsm);
  207. state = SCE_C_DEFAULT;
  208. }
  209. } else if (state == SCE_C_COMMENT) {
  210. if (ch == '!' || (ch == '\r' || ch == '\n') ) {
  211. ColourTo(styler, i, state, bInAsm);
  212. state = SCE_C_DEFAULT;
  213. }
  214. } else if (state == SCE_C_COMMENTDOC) {
  215. if (ch == '!' || (ch == '\r' || ch == '\n')) {
  216. if (((i > styler.GetStartSegment() + 2) || (
  217. (initStyle == SCE_C_COMMENTDOC) &&
  218. (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
  219. ColourTo(styler, i, state, bInAsm);
  220. state = SCE_C_DEFAULT;
  221. }
  222. }
  223. } else if (state == SCE_C_COMMENTLINE) {
  224. if (ch == '\r' || ch == '\n') {
  225. ColourTo(styler, i-1, state, bInAsm);
  226. state = SCE_C_DEFAULT;
  227. }
  228. } else if (state == SCE_C_STRING) {
  229. if (ch == '"') {
  230. ColourTo(styler, i, state, bInAsm);
  231. state = SCE_C_DEFAULT;
  232. }
  233. }
  234. }
  235. if (!isspacechar(ch))
  236. visibleChars++;
  237. chPrev = ch;
  238. }
  239. ColourTo(styler, lengthDoc - 1, state, bInAsm);
  240. }
  241. static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[],
  242. Accessor &styler) {
  243. bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
  244. bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
  245. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  246. unsigned int endPos = startPos + length;
  247. int visibleChars = 0;
  248. int lineCurrent = styler.GetLine(startPos);
  249. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  250. int levelCurrent = levelPrev;
  251. char chNext = styler[startPos];
  252. int styleNext = styler.StyleAt(startPos);
  253. int style = initStyle;
  254. bool was_end = false;
  255. bool section = false;
  256. int lastStart = 0;
  257. for (unsigned int i = startPos; i < endPos; i++) {
  258. char ch = chNext;
  259. chNext = styler.SafeGetCharAt(i + 1);
  260. int stylePrev = style;
  261. style = styleNext;
  262. styleNext = styler.StyleAt(i + 1);
  263. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  264. if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR))
  265. {
  266. // Store last word start point.
  267. lastStart = i;
  268. }
  269. if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) {
  270. if(isTALwordchar(ch) && !isTALwordchar(chNext)) {
  271. char s[100];
  272. getRange(lastStart, i, styler, s, sizeof(s));
  273. if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
  274. {
  275. section = true;
  276. levelCurrent = 1;
  277. levelPrev = 0;
  278. }
  279. else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID)
  280. {
  281. if (strcmp(s, "block") == 0)
  282. {
  283. // block keyword is ignored immediately after end keyword
  284. if (!was_end)
  285. levelCurrent++;
  286. }
  287. else
  288. levelCurrent += classifyFoldPointTAL(s);
  289. if (strcmp(s, "end") == 0)
  290. {
  291. was_end = true;
  292. }
  293. else
  294. {
  295. was_end = false;
  296. }
  297. }
  298. }
  299. }
  300. if (foldComment && (style == SCE_C_COMMENTLINE)) {
  301. if ((ch == '/') && (chNext == '/')) {
  302. char chNext2 = styler.SafeGetCharAt(i + 2);
  303. if (chNext2 == '{') {
  304. levelCurrent++;
  305. } else if (chNext2 == '}') {
  306. levelCurrent--;
  307. }
  308. }
  309. }
  310. if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
  311. if (ch == '{' && chNext == '$') {
  312. unsigned int j=i+2; // skip {$
  313. while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
  314. j++;
  315. }
  316. if (styler.Match(j, "region") || styler.Match(j, "if")) {
  317. levelCurrent++;
  318. } else if (styler.Match(j, "end")) {
  319. levelCurrent--;
  320. }
  321. }
  322. }
  323. if (foldComment && IsStreamCommentStyle(style)) {
  324. if (!IsStreamCommentStyle(stylePrev)) {
  325. levelCurrent++;
  326. } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
  327. // Comments don't end at end of line and the next character may be unstyled.
  328. levelCurrent--;
  329. }
  330. }
  331. if (atEOL) {
  332. int lev = levelPrev | SC_FOLDLEVELBASE;
  333. if (visibleChars == 0 && foldCompact)
  334. lev |= SC_FOLDLEVELWHITEFLAG;
  335. if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
  336. lev |= SC_FOLDLEVELHEADERFLAG;
  337. if (lev != styler.LevelAt(lineCurrent)) {
  338. styler.SetLevel(lineCurrent, lev);
  339. }
  340. lineCurrent++;
  341. levelPrev = levelCurrent;
  342. visibleChars = 0;
  343. section = false;
  344. }
  345. if (!isspacechar(ch))
  346. visibleChars++;
  347. }
  348. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  349. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  350. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  351. }
  352. static const char * const TALWordListDesc[] = {
  353. "Keywords",
  354. "Builtins",
  355. 0
  356. };
  357. LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc);