PageRenderTime 194ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

/src/Scite/scite201/scintilla/src/LexLisp.cxx

http://anotherclojurebox.googlecode.com/
C++ | 548 lines | 467 code | 39 blank | 42 comment | 359 complexity | cd2d66467dae844320cf92487090d7bd MD5 | raw file
  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 <ctype.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include "Platform.h"
  14. #include "PropSet.h"
  15. #include "Accessor.h"
  16. #include "KeyWords.h"
  17. #include "Scintilla.h"
  18. #include "SciLexer.h"
  19. #include "StyleContext.h"
  20. #ifdef SCI_NAMESPACE
  21. using namespace Scintilla;
  22. #endif
  23. #define SCE_LISP_CHARACTER 29
  24. #define SCE_LISP_MACRO 30
  25. #define SCE_LISP_MACRO_DISPATCH 31
  26. static inline bool isLispoperator(char ch) {
  27. if (isascii(ch) && isalnum(ch))
  28. return false;
  29. if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
  30. return true;
  31. return false;
  32. }
  33. static inline bool isLispwordstart(char ch) {
  34. return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
  35. ch != '\n' && ch != '\r' && ch != '\"';
  36. }
  37. static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
  38. PLATFORM_ASSERT(end >= start);
  39. char s[100];
  40. unsigned int i;
  41. bool digit_flag = true;
  42. for (i = 0; (i < end - start + 1) && (i < 99); i++) {
  43. s[i] = styler[start + i];
  44. s[i + 1] = '\0';
  45. if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
  46. }
  47. char chAttr = SCE_LISP_IDENTIFIER;
  48. if(digit_flag) chAttr = SCE_LISP_NUMBER;
  49. else {
  50. if (keywords.InList(s)) {
  51. chAttr = SCE_LISP_KEYWORD;
  52. } else if (keywords_kw.InList(s)) {
  53. chAttr = SCE_LISP_KEYWORD_KW;
  54. } else if ((s[0] == '*' && s[i-1] == '*') ||
  55. (s[0] == '+' && s[i-1] == '+')) {
  56. chAttr = SCE_LISP_SPECIAL;
  57. }
  58. }
  59. styler.ColourTo(end, chAttr);
  60. return;
  61. }
  62. static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
  63. Accessor &styler) {
  64. WordList &keywords = *keywordlists[0];
  65. WordList &keywords_kw = *keywordlists[1];
  66. styler.StartAt(startPos);
  67. int state = initStyle, radix = -1;
  68. char chNext = styler[startPos];
  69. unsigned int lengthDoc = startPos + length;
  70. styler.StartSegment(startPos);
  71. for (unsigned int i = startPos; i < lengthDoc; i++) {
  72. char ch = chNext;
  73. chNext = styler.SafeGetCharAt(i + 1);
  74. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  75. if (styler.IsLeadByte(ch)) {
  76. chNext = styler.SafeGetCharAt(i + 2);
  77. i += 1;
  78. continue;
  79. }
  80. if (state == SCE_LISP_DEFAULT) {
  81. if (ch == '#') {
  82. styler.ColourTo(i - 1, state);
  83. radix = -1;
  84. state = SCE_LISP_MACRO_DISPATCH;
  85. } else if (ch == ':' && isLispwordstart(chNext)) {
  86. styler.ColourTo(i - 1, state);
  87. state = SCE_LISP_SYMBOL;
  88. } else if (isLispwordstart(ch)) {
  89. styler.ColourTo(i - 1, state);
  90. state = SCE_LISP_IDENTIFIER;
  91. }
  92. else if (ch == ';') {
  93. styler.ColourTo(i - 1, state);
  94. state = SCE_LISP_COMMENT;
  95. }
  96. else if (isLispoperator(ch) || ch=='\'') {
  97. styler.ColourTo(i - 1, state);
  98. styler.ColourTo(i, SCE_LISP_OPERATOR);
  99. if (ch=='\'' && isLispwordstart(chNext)) {
  100. state = SCE_LISP_SYMBOL;
  101. }
  102. }
  103. else if (ch == '\"') {
  104. styler.ColourTo(i - 1, state);
  105. state = SCE_LISP_STRING;
  106. }
  107. } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
  108. if (!isLispwordstart(ch)) {
  109. if (state == SCE_LISP_IDENTIFIER) {
  110. classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
  111. } else {
  112. styler.ColourTo(i - 1, state);
  113. }
  114. state = SCE_LISP_DEFAULT;
  115. } /*else*/
  116. if (isLispoperator(ch) || ch=='\'') {
  117. styler.ColourTo(i - 1, state);
  118. styler.ColourTo(i, SCE_LISP_OPERATOR);
  119. if (ch=='\'' && isLispwordstart(chNext)) {
  120. state = SCE_LISP_SYMBOL;
  121. }
  122. }
  123. } else if (state == SCE_LISP_MACRO_DISPATCH) {
  124. if (!isdigit(ch)) {
  125. if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
  126. state = SCE_LISP_DEFAULT;
  127. } else {
  128. switch (ch) {
  129. case '|': state = SCE_LISP_MULTI_COMMENT; break;
  130. case 'o':
  131. case 'O': radix = 8; state = SCE_LISP_MACRO; break;
  132. case 'x':
  133. case 'X': radix = 16; state = SCE_LISP_MACRO; break;
  134. case 'b':
  135. case 'B': radix = 2; state = SCE_LISP_MACRO; break;
  136. case '\\': state = SCE_LISP_CHARACTER; break;
  137. case ':':
  138. case '-':
  139. case '+': state = SCE_LISP_MACRO; break;
  140. case '\'': if (isLispwordstart(chNext)) {
  141. state = SCE_LISP_SPECIAL;
  142. } else {
  143. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  144. styler.ColourTo(i, SCE_LISP_OPERATOR);
  145. state = SCE_LISP_DEFAULT;
  146. }
  147. break;
  148. default: if (isLispoperator(ch)) {
  149. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  150. styler.ColourTo(i, SCE_LISP_OPERATOR);
  151. }
  152. state = SCE_LISP_DEFAULT;
  153. break;
  154. }
  155. }
  156. }
  157. } else if (state == SCE_LISP_MACRO) {
  158. if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
  159. state = SCE_LISP_SPECIAL;
  160. } else {
  161. state = SCE_LISP_DEFAULT;
  162. }
  163. } else if (state == SCE_LISP_CHARACTER) {
  164. if (isLispoperator(ch)) {
  165. styler.ColourTo(i, SCE_LISP_SPECIAL);
  166. state = SCE_LISP_DEFAULT;
  167. } else if (isLispwordstart(ch)) {
  168. styler.ColourTo(i, SCE_LISP_SPECIAL);
  169. state = SCE_LISP_SPECIAL;
  170. } else {
  171. state = SCE_LISP_DEFAULT;
  172. }
  173. } else if (state == SCE_LISP_SPECIAL) {
  174. if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
  175. styler.ColourTo(i - 1, state);
  176. state = SCE_LISP_DEFAULT;
  177. }
  178. if (isLispoperator(ch) || ch=='\'') {
  179. styler.ColourTo(i - 1, state);
  180. styler.ColourTo(i, SCE_LISP_OPERATOR);
  181. if (ch=='\'' && isLispwordstart(chNext)) {
  182. state = SCE_LISP_SYMBOL;
  183. }
  184. }
  185. } else {
  186. if (state == SCE_LISP_COMMENT) {
  187. if (atEOL) {
  188. styler.ColourTo(i - 1, state);
  189. state = SCE_LISP_DEFAULT;
  190. }
  191. } else if (state == SCE_LISP_MULTI_COMMENT) {
  192. if (ch == '|' && chNext == '#') {
  193. i++;
  194. chNext = styler.SafeGetCharAt(i + 1);
  195. styler.ColourTo(i, state);
  196. state = SCE_LISP_DEFAULT;
  197. }
  198. } else if (state == SCE_LISP_STRING) {
  199. if (ch == '\\') {
  200. if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
  201. i++;
  202. chNext = styler.SafeGetCharAt(i + 1);
  203. }
  204. } else if (ch == '\"') {
  205. styler.ColourTo(i, state);
  206. state = SCE_LISP_DEFAULT;
  207. }
  208. }
  209. }
  210. }
  211. styler.ColourTo(lengthDoc - 1, state);
  212. }
  213. static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
  214. Accessor &styler) {
  215. unsigned int lengthDoc = startPos + length;
  216. int visibleChars = 0;
  217. int lineCurrent = styler.GetLine(startPos);
  218. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  219. int levelCurrent = levelPrev;
  220. char chNext = styler[startPos];
  221. int styleNext = styler.StyleAt(startPos);
  222. for (unsigned int i = startPos; i < lengthDoc; i++) {
  223. char ch = chNext;
  224. chNext = styler.SafeGetCharAt(i + 1);
  225. int style = styleNext;
  226. styleNext = styler.StyleAt(i + 1);
  227. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  228. if (style == SCE_LISP_OPERATOR) {
  229. if (ch == '(' || ch == '[' || ch == '{') {
  230. levelCurrent++;
  231. } else if (ch == ')' || ch == ']' || ch == '}') {
  232. levelCurrent--;
  233. }
  234. }
  235. if (atEOL) {
  236. int lev = levelPrev;
  237. if (visibleChars == 0)
  238. lev |= SC_FOLDLEVELWHITEFLAG;
  239. if ((levelCurrent > levelPrev) && (visibleChars > 0))
  240. lev |= SC_FOLDLEVELHEADERFLAG;
  241. if (lev != styler.LevelAt(lineCurrent)) {
  242. styler.SetLevel(lineCurrent, lev);
  243. }
  244. lineCurrent++;
  245. levelPrev = levelCurrent;
  246. visibleChars = 0;
  247. }
  248. if (!isspacechar(ch))
  249. visibleChars++;
  250. }
  251. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  252. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  253. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  254. }
  255. static const char * const lispWordListDesc[] = {
  256. "Functions and special operators",
  257. "Keywords",
  258. 0
  259. };
  260. #define SCE_CLOJURE_CHARACTER 290
  261. #define SCE_CLOJURE_MACRO 300
  262. #define SCE_CLOJURE_MACRO_DISPATCH 310
  263. #define SCE_CLOJURE_REGEXP 320
  264. static inline bool isClojureoperator(char ch) {
  265. if (isascii(ch) && isalnum(ch))
  266. return false;
  267. if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
  268. return true;
  269. return false;
  270. }
  271. static inline bool isClojurewordstart(char ch) {
  272. return isascii(ch) && ch != ';' && !isspacechar(ch) && !isClojureoperator(ch) &&
  273. ch != '\n' && ch != '\r' && ch != '\"';
  274. }
  275. static void classifyWordClojure(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
  276. PLATFORM_ASSERT(end >= start);
  277. char s[100];
  278. unsigned int i;
  279. bool digit_flag = true;
  280. for (i = 0; (i < end - start + 1) && (i < 99); i++) {
  281. s[i] = styler[start + i];
  282. s[i + 1] = '\0';
  283. if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
  284. }
  285. char chAttr = SCE_CLOJURE_IDENTIFIER;
  286. if(digit_flag) chAttr = SCE_CLOJURE_NUMBER;
  287. else {
  288. if (keywords.InList(s)) {
  289. chAttr = SCE_CLOJURE_KEYWORD;
  290. } else if (keywords_kw.InList(s)) {
  291. chAttr = SCE_CLOJURE_KEYWORD_KW;
  292. } else if ((s[0] == '*' && s[i-1] == '*') ||
  293. (s[0] == '+' && s[i-1] == '+')) {
  294. chAttr = SCE_CLOJURE_SPECIAL;
  295. }
  296. }
  297. styler.ColourTo(end, chAttr);
  298. return;
  299. }
  300. static void ColouriseClojureDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
  301. Accessor &styler) {
  302. WordList &keywords = *keywordlists[0];
  303. WordList &keywords_kw = *keywordlists[1];
  304. styler.StartAt(startPos);
  305. int state = initStyle, radix = -1;
  306. char chNext = styler[startPos];
  307. unsigned int lengthDoc = startPos + length;
  308. styler.StartSegment(startPos);
  309. for (unsigned int i = startPos; i < lengthDoc; i++) {
  310. char ch = chNext;
  311. chNext = styler.SafeGetCharAt(i + 1);
  312. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  313. if (styler.IsLeadByte(ch)) {
  314. chNext = styler.SafeGetCharAt(i + 2);
  315. i += 1;
  316. continue;
  317. }
  318. if (state == SCE_CLOJURE_DEFAULT) {
  319. if (ch == '#') {
  320. styler.ColourTo(i - 1, state);
  321. radix = -1;
  322. state = SCE_CLOJURE_MACRO_DISPATCH;
  323. if (chNext != '\"') {
  324. state = SCE_CLOJURE_DEFAULT;
  325. }
  326. } else if (ch == ':' && isClojurewordstart(chNext)) {
  327. styler.ColourTo(i - 1, state);
  328. state = SCE_CLOJURE_SYMBOL;
  329. } else if (isClojurewordstart(ch)) {
  330. styler.ColourTo(i - 1, state);
  331. state = SCE_CLOJURE_IDENTIFIER;
  332. }
  333. else if (ch == ';') {
  334. styler.ColourTo(i - 1, state);
  335. state = SCE_CLOJURE_COMMENT;
  336. }
  337. else if (isClojureoperator(ch) || ch=='\'') {
  338. styler.ColourTo(i - 1, state);
  339. styler.ColourTo(i, SCE_CLOJURE_OPERATOR);
  340. if (ch=='\'' && isClojurewordstart(chNext)) {
  341. state = SCE_CLOJURE_SYMBOL;
  342. }
  343. }
  344. else if (ch == '\"') {
  345. styler.ColourTo(i - 1, state);
  346. state = SCE_CLOJURE_STRING;
  347. }
  348. } else if (state == SCE_CLOJURE_MACRO_DISPATCH){
  349. if (ch == '\"'){
  350. styler.ColourTo(i - 1, state);
  351. state = SCE_CLOJURE_REGEXP;
  352. }
  353. }else if (state == SCE_CLOJURE_REGEXP){
  354. if (ch == '\\') {
  355. if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
  356. i++;
  357. chNext = styler.SafeGetCharAt(i + 1);
  358. }
  359. } else if (ch == '\"') {
  360. styler.ColourTo(i, state);
  361. state = SCE_CLOJURE_DEFAULT;
  362. }
  363. /*if (!isdigit(ch)) {
  364. if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
  365. state = SCE_LISP_DEFAULT;
  366. } else {
  367. switch (ch) {
  368. case '|': state = SCE_LISP_MULTI_COMMENT; break;
  369. case 'o':
  370. case 'O': radix = 8; state = SCE_LISP_MACRO; break;
  371. case 'x':
  372. case 'X': radix = 16; state = SCE_LISP_MACRO; break;
  373. case 'b':
  374. case 'B': radix = 2; state = SCE_LISP_MACRO; break;
  375. case '\\': state = SCE_LISP_CHARACTER; break;
  376. case ':':
  377. case '-':
  378. case '+': state = SCE_LISP_MACRO; break;
  379. case '\'': if (isLispwordstart(chNext)) {
  380. state = SCE_LISP_SPECIAL;
  381. } else {
  382. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  383. styler.ColourTo(i, SCE_LISP_OPERATOR);
  384. state = SCE_LISP_DEFAULT;
  385. }
  386. break;
  387. default: if (isLispoperator(ch)) {
  388. styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
  389. styler.ColourTo(i, SCE_LISP_OPERATOR);
  390. }
  391. state = SCE_LISP_DEFAULT;
  392. break;
  393. }
  394. }
  395. }*/
  396. } else if (state == SCE_CLOJURE_IDENTIFIER || state == SCE_CLOJURE_SYMBOL) {
  397. if (!isClojurewordstart(ch)) {
  398. if (state == SCE_CLOJURE_IDENTIFIER) {
  399. classifyWordClojure(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
  400. } else {
  401. styler.ColourTo(i - 1, state);
  402. }
  403. state = SCE_CLOJURE_DEFAULT;
  404. } /*else*/
  405. if (isClojureoperator(ch) || ch=='\'') {
  406. styler.ColourTo(i - 1, state);
  407. styler.ColourTo(i, SCE_CLOJURE_OPERATOR);
  408. if (ch=='\'' && isClojurewordstart(chNext)) {
  409. state = SCE_CLOJURE_SYMBOL;
  410. }
  411. }
  412. } else if (state == SCE_CLOJURE_MACRO) {
  413. if (isClojurewordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
  414. state = SCE_CLOJURE_SPECIAL;
  415. } else {
  416. state = SCE_CLOJURE_DEFAULT;
  417. }
  418. } else if (state == SCE_CLOJURE_CHARACTER) {
  419. if (isClojureoperator(ch)) {
  420. styler.ColourTo(i, SCE_CLOJURE_SPECIAL);
  421. state = SCE_CLOJURE_DEFAULT;
  422. } else if (isClojurewordstart(ch)) {
  423. styler.ColourTo(i, SCE_CLOJURE_SPECIAL);
  424. state = SCE_CLOJURE_SPECIAL;
  425. } else {
  426. state = SCE_CLOJURE_DEFAULT;
  427. }
  428. } else if (state == SCE_CLOJURE_SPECIAL) {
  429. if (!isClojurewordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
  430. styler.ColourTo(i - 1, state);
  431. state = SCE_CLOJURE_DEFAULT;
  432. }
  433. if (isClojureoperator(ch) || ch=='\'') {
  434. styler.ColourTo(i - 1, state);
  435. styler.ColourTo(i, SCE_CLOJURE_OPERATOR);
  436. if (ch=='\'' && isClojurewordstart(chNext)) {
  437. state = SCE_CLOJURE_SYMBOL;
  438. }
  439. }
  440. } else {
  441. if (state == SCE_CLOJURE_COMMENT) {
  442. if (atEOL) {
  443. styler.ColourTo(i - 1, state);
  444. state = SCE_CLOJURE_DEFAULT;
  445. }
  446. } else if (state == SCE_CLOJURE_STRING) {
  447. if (ch == '\\') {
  448. if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
  449. i++;
  450. chNext = styler.SafeGetCharAt(i + 1);
  451. }
  452. } else if (ch == '\"') {
  453. styler.ColourTo(i, state);
  454. state = SCE_CLOJURE_DEFAULT;
  455. }
  456. }
  457. }
  458. }
  459. styler.ColourTo(lengthDoc - 1, state);
  460. }
  461. static void FoldClojureDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
  462. Accessor &styler) {
  463. unsigned int lengthDoc = startPos + length;
  464. int visibleChars = 0;
  465. int lineCurrent = styler.GetLine(startPos);
  466. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  467. int levelCurrent = levelPrev;
  468. char chNext = styler[startPos];
  469. int styleNext = styler.StyleAt(startPos);
  470. for (unsigned int i = startPos; i < lengthDoc; i++) {
  471. char ch = chNext;
  472. chNext = styler.SafeGetCharAt(i + 1);
  473. int style = styleNext;
  474. styleNext = styler.StyleAt(i + 1);
  475. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  476. if (style == SCE_CLOJURE_OPERATOR) {
  477. if (ch == '(' || ch == '[' || ch == '{') {
  478. levelCurrent++;
  479. } else if (ch == ')' || ch == ']' || ch == '}') {
  480. levelCurrent--;
  481. }
  482. }
  483. if (atEOL) {
  484. int lev = levelPrev;
  485. if (visibleChars == 0)
  486. lev |= SC_FOLDLEVELWHITEFLAG;
  487. if ((levelCurrent > levelPrev) && (visibleChars > 0))
  488. lev |= SC_FOLDLEVELHEADERFLAG;
  489. if (lev != styler.LevelAt(lineCurrent)) {
  490. styler.SetLevel(lineCurrent, lev);
  491. }
  492. lineCurrent++;
  493. levelPrev = levelCurrent;
  494. visibleChars = 0;
  495. }
  496. if (!isspacechar(ch))
  497. visibleChars++;
  498. }
  499. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  500. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  501. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  502. }
  503. static const char * const clojureWordListDesc[] = {
  504. "Functions and special operators",
  505. "Keywords",
  506. 0
  507. };
  508. LexerModule lmCLOJURE(SCLEX_CLOJURE, ColouriseClojureDoc, "clojure", FoldClojureDoc, clojureWordListDesc);
  509. LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);