LexLisp.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Scintilla source code edit control
  2. /** @file LexLisp.cxx
  3. ** Lexer for Lisp.
  4. ** Written by Alexey Yutkin.
  5. **/
  6. // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
  7. // The License.txt file describes the conditions under which this software may be distributed.
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <stdarg.h>
  12. #include <assert.h>
  13. #include <ctype.h>
  14. #include "ILexer.h"
  15. #include "Scintilla.h"
  16. #include "SciLexer.h"
  17. #include "WordList.h"
  18. #include "LexAccessor.h"
  19. #include "Accessor.h"
  20. #include "StyleContext.h"
  21. #include "CharacterSet.h"
  22. #include "LexerModule.h"
  23. #ifdef SCI_NAMESPACE
  24. using namespace Scintilla;
  25. #endif
  26. #define SCE_LISP_CHARACTER 29
  27. #define SCE_LISP_MACRO 30
  28. #define SCE_LISP_MACRO_DISPATCH 31
  29. static inline bool isLispoperator(char ch) {
  30. if (IsASCII(ch) && isalnum(ch))
  31. return false;
  32. if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
  33. return true;
  34. return false;
  35. }
  36. static inline bool isLispwordstart(char ch) {
  37. return IsASCII(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
  38. ch != '\n' && ch != '\r' && ch != '\"';
  39. }
  40. static void classifyWordLisp(Sci_PositionU start, Sci_PositionU end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
  41. assert(end >= start);
  42. char s[100];
  43. Sci_PositionU i;
  44. bool digit_flag = true;
  45. for (i = 0; (i < end - start + 1) && (i < 99); i++) {
  46. s[i] = styler[start + i];
  47. s[i + 1] = '\0';
  48. if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
  49. }
  50. char chAttr = SCE_LISP_IDENTIFIER;
  51. if(digit_flag) chAttr = SCE_LISP_NUMBER;
  52. else {
  53. if (keywords.InList(s)) {
  54. chAttr = SCE_LISP_KEYWORD;
  55. } else if (keywords_kw.InList(s)) {
  56. chAttr = SCE_LISP_KEYWORD_KW;
  57. } else if ((s[0] == '*' && s[i-1] == '*') ||
  58. (s[0] == '+' && s[i-1] == '+')) {
  59. chAttr = SCE_LISP_SPECIAL;
  60. }
  61. }
  62. styler.ColourTo(end, chAttr);
  63. return;
  64. }
  65. static void ColouriseLispDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
  66. Accessor &styler) {
  67. WordList &keywords = *keywordlists[0];
  68. WordList &keywords_kw = *keywordlists[1];
  69. styler.StartAt(startPos);
  70. int state = initStyle, radix = -1;
  71. char chNext = styler[startPos];
  72. Sci_PositionU lengthDoc = startPos + length;
  73. styler.StartSegment(startPos);
  74. for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
  75. char ch = chNext;
  76. chNext = styler.SafeGetCharAt(i + 1);
  77. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  78. if (styler.IsLeadByte(ch)) {
  79. chNext = styler.SafeGetCharAt(i + 2);
  80. i += 1;
  81. continue;
  82. }
  83. if (state == SCE_LISP_DEFAULT) {
  84. if (ch == '#') {
  85. styler.ColourTo(i - 1, state);
  86. radix = -1;
  87. state = SCE_LISP_MACRO_DISPATCH;
  88. } else if (ch == ':' && isLispwordstart(chNext)) {
  89. styler.ColourTo(i - 1, state);
  90. state = SCE_LISP_SYMBOL;
  91. } else if (isLispwordstart(ch)) {
  92. styler.ColourTo(i - 1, state);
  93. state = SCE_LISP_IDENTIFIER;
  94. }
  95. else if (ch == ';') {
  96. styler.ColourTo(i - 1, state);
  97. state = SCE_LISP_COMMENT;
  98. }
  99. else if (isLispoperator(ch) || ch=='\'') {
  100. styler.ColourTo(i - 1, state);
  101. styler.ColourTo(i, SCE_LISP_OPERATOR);
  102. if (ch=='\'' && isLispwordstart(chNext)) {
  103. state = SCE_LISP_SYMBOL;
  104. }
  105. }
  106. else if (ch == '\"') {
  107. styler.ColourTo(i - 1, state);
  108. state = SCE_LISP_STRING;
  109. }
  110. } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
  111. if (!isLispwordstart(ch)) {
  112. if (state == SCE_LISP_IDENTIFIER) {
  113. classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
  114. } else {
  115. styler.ColourTo(i - 1, state);
  116. }
  117. state = SCE_LISP_DEFAULT;
  118. } /*else*/
  119. if (isLispoperator(ch) || ch=='\'') {
  120. styler.ColourTo(i - 1, state);
  121. styler.ColourTo(i, SCE_LISP_OPERATOR);
  122. if (ch=='\'' && isLispwordstart(chNext)) {
  123. state = SCE_LISP_SYMBOL;
  124. }
  125. }
  126. } else if (state == SCE_LISP_MACRO_DISPATCH) {
  127. if (!(IsASCII(ch) && isdigit(ch))) {
  128. if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
  129. state = SCE_LISP_DEFAULT;
  130. } else {
  131. switch (ch) {
  132. case '|': state = SCE_LISP_MULTI_COMMENT; break;
  133. case 'o':
  134. case 'O': radix = 8; state = SCE_LISP_MACRO; break;
  135. case 'x':
  136. case 'X': radix = 16; state = SCE_LISP_MACRO; break;
  137. case 'b':
  138. case 'B': radix = 2; state = SCE_LISP_MACRO; break;
  139. case '\\': state = SCE_LISP_CHARACTER; break;
  140. case ':':
  141. case '-':
  142. case '+': state = SCE_LISP_MACRO; break;
  143. case '\'': if (isLispwordstart(chNext)) {
  144. state = SCE_LISP_SPECIAL;
  145. } else {
  146. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  147. styler.ColourTo(i, SCE_LISP_OPERATOR);
  148. state = SCE_LISP_DEFAULT;
  149. }
  150. break;
  151. default: if (isLispoperator(ch)) {
  152. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  153. styler.ColourTo(i, SCE_LISP_OPERATOR);
  154. }
  155. state = SCE_LISP_DEFAULT;
  156. break;
  157. }
  158. }
  159. }
  160. } else if (state == SCE_LISP_MACRO) {
  161. if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
  162. state = SCE_LISP_SPECIAL;
  163. } else {
  164. state = SCE_LISP_DEFAULT;
  165. }
  166. } else if (state == SCE_LISP_CHARACTER) {
  167. if (isLispoperator(ch)) {
  168. styler.ColourTo(i, SCE_LISP_SPECIAL);
  169. state = SCE_LISP_DEFAULT;
  170. } else if (isLispwordstart(ch)) {
  171. styler.ColourTo(i, SCE_LISP_SPECIAL);
  172. state = SCE_LISP_SPECIAL;
  173. } else {
  174. state = SCE_LISP_DEFAULT;
  175. }
  176. } else if (state == SCE_LISP_SPECIAL) {
  177. if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
  178. styler.ColourTo(i - 1, state);
  179. state = SCE_LISP_DEFAULT;
  180. }
  181. if (isLispoperator(ch) || ch=='\'') {
  182. styler.ColourTo(i - 1, state);
  183. styler.ColourTo(i, SCE_LISP_OPERATOR);
  184. if (ch=='\'' && isLispwordstart(chNext)) {
  185. state = SCE_LISP_SYMBOL;
  186. }
  187. }
  188. } else {
  189. if (state == SCE_LISP_COMMENT) {
  190. if (atEOL) {
  191. styler.ColourTo(i - 1, state);
  192. state = SCE_LISP_DEFAULT;
  193. }
  194. } else if (state == SCE_LISP_MULTI_COMMENT) {
  195. if (ch == '|' && chNext == '#') {
  196. i++;
  197. chNext = styler.SafeGetCharAt(i + 1);
  198. styler.ColourTo(i, state);
  199. state = SCE_LISP_DEFAULT;
  200. }
  201. } else if (state == SCE_LISP_STRING) {
  202. if (ch == '\\') {
  203. if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
  204. i++;
  205. chNext = styler.SafeGetCharAt(i + 1);
  206. }
  207. } else if (ch == '\"') {
  208. styler.ColourTo(i, state);
  209. state = SCE_LISP_DEFAULT;
  210. }
  211. }
  212. }
  213. }
  214. styler.ColourTo(lengthDoc - 1, state);
  215. }
  216. static void FoldLispDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[],
  217. Accessor &styler) {
  218. Sci_PositionU lengthDoc = startPos + length;
  219. int visibleChars = 0;
  220. Sci_Position lineCurrent = styler.GetLine(startPos);
  221. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  222. int levelCurrent = levelPrev;
  223. char chNext = styler[startPos];
  224. int styleNext = styler.StyleAt(startPos);
  225. for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
  226. char ch = chNext;
  227. chNext = styler.SafeGetCharAt(i + 1);
  228. int style = styleNext;
  229. styleNext = styler.StyleAt(i + 1);
  230. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  231. if (style == SCE_LISP_OPERATOR) {
  232. if (ch == '(' || ch == '[' || ch == '{') {
  233. levelCurrent++;
  234. } else if (ch == ')' || ch == ']' || ch == '}') {
  235. levelCurrent--;
  236. }
  237. }
  238. if (atEOL) {
  239. int lev = levelPrev;
  240. if (visibleChars == 0)
  241. lev |= SC_FOLDLEVELWHITEFLAG;
  242. if ((levelCurrent > levelPrev) && (visibleChars > 0))
  243. lev |= SC_FOLDLEVELHEADERFLAG;
  244. if (lev != styler.LevelAt(lineCurrent)) {
  245. styler.SetLevel(lineCurrent, lev);
  246. }
  247. lineCurrent++;
  248. levelPrev = levelCurrent;
  249. visibleChars = 0;
  250. }
  251. if (!isspacechar(ch))
  252. visibleChars++;
  253. }
  254. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  255. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  256. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  257. }
  258. static const char * const lispWordListDesc[] = {
  259. "Functions and special operators",
  260. "Keywords",
  261. 0
  262. };
  263. LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);