LexAVE.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // SciTE - Scintilla based Text Editor
  2. /** @file LexAVE.cxx
  3. ** Lexer for Avenue.
  4. **
  5. ** Written by Alexey Yutkin <yutkin@geol.msu.ru>.
  6. **/
  7. // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
  8. // The License.txt file describes the conditions under which this software may be distributed.
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include <assert.h>
  14. #include <ctype.h>
  15. #include "ILexer.h"
  16. #include "Scintilla.h"
  17. #include "SciLexer.h"
  18. #include "WordList.h"
  19. #include "LexAccessor.h"
  20. #include "Accessor.h"
  21. #include "StyleContext.h"
  22. #include "CharacterSet.h"
  23. #include "LexerModule.h"
  24. #ifdef SCI_NAMESPACE
  25. using namespace Scintilla;
  26. #endif
  27. static inline bool IsAWordChar(const int ch) {
  28. return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
  29. }
  30. static inline bool IsEnumChar(const int ch) {
  31. return (ch < 0x80) && (isalnum(ch)|| ch == '_');
  32. }
  33. static inline bool IsANumberChar(const int ch) {
  34. return (ch < 0x80) && (isalnum(ch) || ch == '.' );
  35. }
  36. inline bool IsAWordStart(const int ch) {
  37. return (ch < 0x80) && (isalnum(ch) || ch == '_');
  38. }
  39. inline bool isAveOperator(char ch) {
  40. if (IsASCII(ch) && isalnum(ch))
  41. return false;
  42. // '.' left out as it is used to make up numbers
  43. if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
  44. ch == '(' || ch == ')' || ch == '=' ||
  45. ch == '{' || ch == '}' ||
  46. ch == '[' || ch == ']' || ch == ';' ||
  47. ch == '<' || ch == '>' || ch == ',' ||
  48. ch == '.' )
  49. return true;
  50. return false;
  51. }
  52. static void ColouriseAveDoc(
  53. Sci_PositionU startPos,
  54. Sci_Position length,
  55. int initStyle,
  56. WordList *keywordlists[],
  57. Accessor &styler) {
  58. WordList &keywords = *keywordlists[0];
  59. WordList &keywords2 = *keywordlists[1];
  60. WordList &keywords3 = *keywordlists[2];
  61. WordList &keywords4 = *keywordlists[3];
  62. WordList &keywords5 = *keywordlists[4];
  63. WordList &keywords6 = *keywordlists[5];
  64. // Do not leak onto next line
  65. if (initStyle == SCE_AVE_STRINGEOL) {
  66. initStyle = SCE_AVE_DEFAULT;
  67. }
  68. StyleContext sc(startPos, length, initStyle, styler);
  69. for (; sc.More(); sc.Forward()) {
  70. if (sc.atLineEnd) {
  71. // Update the line state, so it can be seen by next line
  72. Sci_Position currentLine = styler.GetLine(sc.currentPos);
  73. styler.SetLineState(currentLine, 0);
  74. }
  75. if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) {
  76. // Prevent SCE_AVE_STRINGEOL from leaking back to previous line
  77. sc.SetState(SCE_AVE_STRING);
  78. }
  79. // Determine if the current state should terminate.
  80. if (sc.state == SCE_AVE_OPERATOR) {
  81. sc.SetState(SCE_AVE_DEFAULT);
  82. } else if (sc.state == SCE_AVE_NUMBER) {
  83. if (!IsANumberChar(sc.ch)) {
  84. sc.SetState(SCE_AVE_DEFAULT);
  85. }
  86. } else if (sc.state == SCE_AVE_ENUM) {
  87. if (!IsEnumChar(sc.ch)) {
  88. sc.SetState(SCE_AVE_DEFAULT);
  89. }
  90. } else if (sc.state == SCE_AVE_IDENTIFIER) {
  91. if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
  92. char s[100];
  93. //sc.GetCurrent(s, sizeof(s));
  94. sc.GetCurrentLowered(s, sizeof(s));
  95. if (keywords.InList(s)) {
  96. sc.ChangeState(SCE_AVE_WORD);
  97. } else if (keywords2.InList(s)) {
  98. sc.ChangeState(SCE_AVE_WORD2);
  99. } else if (keywords3.InList(s)) {
  100. sc.ChangeState(SCE_AVE_WORD3);
  101. } else if (keywords4.InList(s)) {
  102. sc.ChangeState(SCE_AVE_WORD4);
  103. } else if (keywords5.InList(s)) {
  104. sc.ChangeState(SCE_AVE_WORD5);
  105. } else if (keywords6.InList(s)) {
  106. sc.ChangeState(SCE_AVE_WORD6);
  107. }
  108. sc.SetState(SCE_AVE_DEFAULT);
  109. }
  110. } else if (sc.state == SCE_AVE_COMMENT) {
  111. if (sc.atLineEnd) {
  112. sc.SetState(SCE_AVE_DEFAULT);
  113. }
  114. } else if (sc.state == SCE_AVE_STRING) {
  115. if (sc.ch == '\"') {
  116. sc.ForwardSetState(SCE_AVE_DEFAULT);
  117. } else if (sc.atLineEnd) {
  118. sc.ChangeState(SCE_AVE_STRINGEOL);
  119. sc.ForwardSetState(SCE_AVE_DEFAULT);
  120. }
  121. }
  122. // Determine if a new state should be entered.
  123. if (sc.state == SCE_AVE_DEFAULT) {
  124. if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
  125. sc.SetState(SCE_AVE_NUMBER);
  126. } else if (IsAWordStart(sc.ch)) {
  127. sc.SetState(SCE_AVE_IDENTIFIER);
  128. } else if (sc.Match('\"')) {
  129. sc.SetState(SCE_AVE_STRING);
  130. } else if (sc.Match('\'')) {
  131. sc.SetState(SCE_AVE_COMMENT);
  132. sc.Forward();
  133. } else if (isAveOperator(static_cast<char>(sc.ch))) {
  134. sc.SetState(SCE_AVE_OPERATOR);
  135. } else if (sc.Match('#')) {
  136. sc.SetState(SCE_AVE_ENUM);
  137. sc.Forward();
  138. }
  139. }
  140. }
  141. sc.Complete();
  142. }
  143. static void FoldAveDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[],
  144. Accessor &styler) {
  145. Sci_PositionU lengthDoc = startPos + length;
  146. int visibleChars = 0;
  147. Sci_Position lineCurrent = styler.GetLine(startPos);
  148. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  149. int levelCurrent = levelPrev;
  150. char chNext = static_cast<char>(tolower(styler[startPos]));
  151. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  152. int styleNext = styler.StyleAt(startPos);
  153. char s[10] = "";
  154. for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
  155. char ch = static_cast<char>(tolower(chNext));
  156. chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
  157. int style = styleNext;
  158. styleNext = styler.StyleAt(i + 1);
  159. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  160. if (style == SCE_AVE_WORD) {
  161. if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') {
  162. for (unsigned int j = 0; j < 6; j++) {
  163. if (!iswordchar(styler[i + j])) {
  164. break;
  165. }
  166. s[j] = static_cast<char>(tolower(styler[i + j]));
  167. s[j + 1] = '\0';
  168. }
  169. if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
  170. levelCurrent++;
  171. }
  172. if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
  173. // Normally "elseif" and "then" will be on the same line and will cancel
  174. // each other out. // As implemented, this does not support fold.at.else.
  175. levelCurrent--;
  176. }
  177. }
  178. } else if (style == SCE_AVE_OPERATOR) {
  179. if (ch == '{' || ch == '(') {
  180. levelCurrent++;
  181. } else if (ch == '}' || ch == ')') {
  182. levelCurrent--;
  183. }
  184. }
  185. if (atEOL) {
  186. int lev = levelPrev;
  187. if (visibleChars == 0 && foldCompact) {
  188. lev |= SC_FOLDLEVELWHITEFLAG;
  189. }
  190. if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
  191. lev |= SC_FOLDLEVELHEADERFLAG;
  192. }
  193. if (lev != styler.LevelAt(lineCurrent)) {
  194. styler.SetLevel(lineCurrent, lev);
  195. }
  196. lineCurrent++;
  197. levelPrev = levelCurrent;
  198. visibleChars = 0;
  199. }
  200. if (!isspacechar(ch)) {
  201. visibleChars++;
  202. }
  203. }
  204. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  205. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  206. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  207. }
  208. LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc);