LexSmalltalk.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Scintilla source code edit control
  2. /** @file LexSmalltalk.cxx
  3. ** Lexer for Smalltalk language.
  4. ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
  5. **/
  6. // Copyright 1998-2002 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. /*
  27. | lexTable classificationBlock charClasses |
  28. charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
  29. lexTable := ByteArray new: 128.
  30. classificationBlock := [ :charClass :chars |
  31. | flag |
  32. flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
  33. chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].
  34. classificationBlock
  35. value: #DecDigit value: '0123456789';
  36. value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  37. value: #Special value: '()[]{};.^:';
  38. value: #BinSel value: '~@%&*-+=|\/,<>?!';
  39. value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
  40. ((String new: 500) streamContents: [ :stream |
  41. stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
  42. lexTable keysAndValuesDo: [ :index :value |
  43. ((index - 1) rem: 16) == 0 ifTrue: [
  44. stream crLf; tab]
  45. ifFalse: [
  46. stream space].
  47. stream print: value.
  48. index ~= 256 ifTrue: [
  49. stream nextPut: $,]].
  50. stream crLf; nextPutAll: '};'; crLf.
  51. charClasses keysAndValuesDo: [ :index :name |
  52. stream
  53. crLf;
  54. nextPutAll: (
  55. ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
  56. expandMacrosWith: name with: (1 bitShift: (index - 1)))
  57. ]]) edit
  58. */
  59. // autogenerated {{{{
  60. static int ClassificationTable[256] = {
  61. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  62. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  63. 0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
  64. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
  65. 16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
  66. 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
  67. 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  68. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
  69. };
  70. static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
  71. static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
  72. static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
  73. static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
  74. static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
  75. // autogenerated }}}}
  76. static inline bool isAlphaNumeric(int ch) {
  77. return isDecDigit(ch) || isLetter(ch);
  78. }
  79. static inline bool isDigitOfRadix(int ch, int radix)
  80. {
  81. if (isDecDigit(ch))
  82. return (ch - '0') < radix;
  83. else if (!isUpper(ch))
  84. return false;
  85. else
  86. return (ch - 'A' + 10) < radix;
  87. }
  88. static inline void skipComment(StyleContext& sc)
  89. {
  90. while (sc.More() && sc.ch != '\"')
  91. sc.Forward();
  92. }
  93. static inline void skipString(StyleContext& sc)
  94. {
  95. while (sc.More()) {
  96. if (sc.ch == '\'') {
  97. if (sc.chNext != '\'')
  98. return;
  99. sc.Forward();
  100. }
  101. sc.Forward();
  102. }
  103. }
  104. static void handleHash(StyleContext& sc)
  105. {
  106. if (isSpecial(sc.chNext)) {
  107. sc.SetState(SCE_ST_SPECIAL);
  108. return;
  109. }
  110. sc.SetState(SCE_ST_SYMBOL);
  111. sc.Forward();
  112. if (sc.ch == '\'') {
  113. sc.Forward();
  114. skipString(sc);
  115. }
  116. else {
  117. if (isLetter(sc.ch)) {
  118. while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
  119. sc.Forward();
  120. }
  121. else if (isBinSel(sc.ch)) {
  122. while (isBinSel(sc.chNext))
  123. sc.Forward();
  124. }
  125. }
  126. }
  127. static inline void handleSpecial(StyleContext& sc)
  128. {
  129. if (sc.ch == ':' && sc.chNext == '=') {
  130. sc.SetState(SCE_ST_ASSIGN);
  131. sc.Forward();
  132. }
  133. else {
  134. if (sc.ch == '^')
  135. sc.SetState(SCE_ST_RETURN);
  136. else
  137. sc.SetState(SCE_ST_SPECIAL);
  138. }
  139. }
  140. static inline void skipInt(StyleContext& sc, int radix)
  141. {
  142. while (isDigitOfRadix(sc.chNext, radix))
  143. sc.Forward();
  144. }
  145. static void handleNumeric(StyleContext& sc)
  146. {
  147. char num[256];
  148. int nl;
  149. int radix;
  150. sc.SetState(SCE_ST_NUMBER);
  151. num[0] = static_cast<char>(sc.ch);
  152. nl = 1;
  153. while (isDecDigit(sc.chNext)) {
  154. num[nl++] = static_cast<char>(sc.chNext);
  155. sc.Forward();
  156. if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
  157. break;
  158. }
  159. if (sc.chNext == 'r') {
  160. num[nl] = 0;
  161. if (num[0] == '-')
  162. radix = atoi(num + 1);
  163. else
  164. radix = atoi(num);
  165. sc.Forward();
  166. if (sc.chNext == '-')
  167. sc.Forward();
  168. skipInt(sc, radix);
  169. }
  170. else
  171. radix = 10;
  172. if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
  173. return;
  174. sc.Forward();
  175. skipInt(sc, radix);
  176. if (sc.chNext == 's') {
  177. // ScaledDecimal
  178. sc.Forward();
  179. while (isDecDigit(sc.chNext))
  180. sc.Forward();
  181. return;
  182. }
  183. else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
  184. return;
  185. sc.Forward();
  186. if (sc.chNext == '+' || sc.chNext == '-')
  187. sc.Forward();
  188. skipInt(sc, radix);
  189. }
  190. static inline void handleBinSel(StyleContext& sc)
  191. {
  192. sc.SetState(SCE_ST_BINARY);
  193. while (isBinSel(sc.chNext))
  194. sc.Forward();
  195. }
  196. static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
  197. {
  198. char ident[256];
  199. int il;
  200. int state;
  201. bool doubleColonPresent;
  202. sc.SetState(SCE_ST_DEFAULT);
  203. ident[0] = static_cast<char>(sc.ch);
  204. il = 1;
  205. while (isAlphaNumeric(sc.chNext)) {
  206. ident[il++] = static_cast<char>(sc.chNext);
  207. sc.Forward();
  208. if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
  209. break;
  210. }
  211. if (sc.chNext == ':') {
  212. doubleColonPresent = true;
  213. ident[il++] = ':';
  214. sc.Forward();
  215. }
  216. else
  217. doubleColonPresent = false;
  218. ident[il] = 0;
  219. if (specialSelectorList->InList(ident))
  220. state = SCE_ST_SPEC_SEL;
  221. else if (doubleColonPresent)
  222. state = SCE_ST_KWSEND;
  223. else if (isUpper(ident[0]))
  224. state = SCE_ST_GLOBAL;
  225. else {
  226. if (!strcmp(ident, "self"))
  227. state = SCE_ST_SELF;
  228. else if (!strcmp(ident, "super"))
  229. state = SCE_ST_SUPER;
  230. else if (!strcmp(ident, "nil"))
  231. state = SCE_ST_NIL;
  232. else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
  233. state = SCE_ST_BOOL;
  234. else
  235. state = SCE_ST_DEFAULT;
  236. }
  237. sc.ChangeState(state);
  238. }
  239. static void colorizeSmalltalkDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *wordLists[], Accessor &styler)
  240. {
  241. StyleContext sc(startPos, length, initStyle, styler);
  242. if (initStyle == SCE_ST_COMMENT) {
  243. skipComment(sc);
  244. if (sc.More())
  245. sc.Forward();
  246. }
  247. else if (initStyle == SCE_ST_STRING) {
  248. skipString(sc);
  249. if (sc.More())
  250. sc.Forward();
  251. }
  252. for (; sc.More(); sc.Forward()) {
  253. int ch;
  254. ch = sc.ch;
  255. if (ch == '\"') {
  256. sc.SetState(SCE_ST_COMMENT);
  257. sc.Forward();
  258. skipComment(sc);
  259. }
  260. else if (ch == '\'') {
  261. sc.SetState(SCE_ST_STRING);
  262. sc.Forward();
  263. skipString(sc);
  264. }
  265. else if (ch == '#')
  266. handleHash(sc);
  267. else if (ch == '$') {
  268. sc.SetState(SCE_ST_CHARACTER);
  269. sc.Forward();
  270. }
  271. else if (isSpecial(ch))
  272. handleSpecial(sc);
  273. else if (isDecDigit(ch))
  274. handleNumeric(sc);
  275. else if (isLetter(ch))
  276. handleLetter(sc, wordLists[0]);
  277. else if (isBinSel(ch)) {
  278. if (ch == '-' && isDecDigit(sc.chNext))
  279. handleNumeric(sc);
  280. else
  281. handleBinSel(sc);
  282. }
  283. else
  284. sc.SetState(SCE_ST_DEFAULT);
  285. }
  286. sc.Complete();
  287. }
  288. static const char* const smalltalkWordListDesc[] = {
  289. "Special selectors",
  290. 0
  291. };
  292. LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);