LexLout.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Scintilla source code edit control
  2. /** @file LexLout.cxx
  3. ** Lexer for the Basser Lout (>= version 3) typesetting language
  4. **/
  5. // Copyright 2003 by Kein-Hong Man <mkh@pl.jaring.my>
  6. // The License.txt file describes the conditions under which this software may be distributed.
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include <assert.h>
  12. #include <ctype.h>
  13. #include "ILexer.h"
  14. #include "Scintilla.h"
  15. #include "SciLexer.h"
  16. #include "WordList.h"
  17. #include "LexAccessor.h"
  18. #include "Accessor.h"
  19. #include "StyleContext.h"
  20. #include "CharacterSet.h"
  21. #include "LexerModule.h"
  22. #ifdef SCI_NAMESPACE
  23. using namespace Scintilla;
  24. #endif
  25. static inline bool IsAWordChar(const int ch) {
  26. return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_');
  27. }
  28. static inline bool IsAnOther(const int ch) {
  29. return (ch < 0x80) && (ch == '{' || ch == '}' ||
  30. ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' ||
  31. ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
  32. ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' ||
  33. ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' ||
  34. ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~');
  35. }
  36. static void ColouriseLoutDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
  37. WordList *keywordlists[], Accessor &styler) {
  38. WordList &keywords = *keywordlists[0];
  39. WordList &keywords2 = *keywordlists[1];
  40. WordList &keywords3 = *keywordlists[2];
  41. int visibleChars = 0;
  42. int firstWordInLine = 0;
  43. int leadingAtSign = 0;
  44. StyleContext sc(startPos, length, initStyle, styler);
  45. for (; sc.More(); sc.Forward()) {
  46. if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) {
  47. // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line
  48. sc.SetState(SCE_LOUT_STRING);
  49. }
  50. // Determine if the current state should terminate.
  51. if (sc.state == SCE_LOUT_COMMENT) {
  52. if (sc.atLineEnd) {
  53. sc.SetState(SCE_LOUT_DEFAULT);
  54. visibleChars = 0;
  55. }
  56. } else if (sc.state == SCE_LOUT_NUMBER) {
  57. if (!IsADigit(sc.ch) && sc.ch != '.') {
  58. sc.SetState(SCE_LOUT_DEFAULT);
  59. }
  60. } else if (sc.state == SCE_LOUT_STRING) {
  61. if (sc.ch == '\\') {
  62. if (sc.chNext == '\"' || sc.chNext == '\\') {
  63. sc.Forward();
  64. }
  65. } else if (sc.ch == '\"') {
  66. sc.ForwardSetState(SCE_LOUT_DEFAULT);
  67. } else if (sc.atLineEnd) {
  68. sc.ChangeState(SCE_LOUT_STRINGEOL);
  69. sc.ForwardSetState(SCE_LOUT_DEFAULT);
  70. visibleChars = 0;
  71. }
  72. } else if (sc.state == SCE_LOUT_IDENTIFIER) {
  73. if (!IsAWordChar(sc.ch)) {
  74. char s[100];
  75. sc.GetCurrent(s, sizeof(s));
  76. if (leadingAtSign) {
  77. if (keywords.InList(s)) {
  78. sc.ChangeState(SCE_LOUT_WORD);
  79. } else {
  80. sc.ChangeState(SCE_LOUT_WORD4);
  81. }
  82. } else if (firstWordInLine && keywords3.InList(s)) {
  83. sc.ChangeState(SCE_LOUT_WORD3);
  84. }
  85. sc.SetState(SCE_LOUT_DEFAULT);
  86. }
  87. } else if (sc.state == SCE_LOUT_OPERATOR) {
  88. if (!IsAnOther(sc.ch)) {
  89. char s[100];
  90. sc.GetCurrent(s, sizeof(s));
  91. if (keywords2.InList(s)) {
  92. sc.ChangeState(SCE_LOUT_WORD2);
  93. }
  94. sc.SetState(SCE_LOUT_DEFAULT);
  95. }
  96. }
  97. // Determine if a new state should be entered.
  98. if (sc.state == SCE_LOUT_DEFAULT) {
  99. if (sc.ch == '#') {
  100. sc.SetState(SCE_LOUT_COMMENT);
  101. } else if (sc.ch == '\"') {
  102. sc.SetState(SCE_LOUT_STRING);
  103. } else if (IsADigit(sc.ch) ||
  104. (sc.ch == '.' && IsADigit(sc.chNext))) {
  105. sc.SetState(SCE_LOUT_NUMBER);
  106. } else if (IsAWordChar(sc.ch)) {
  107. firstWordInLine = (visibleChars == 0);
  108. leadingAtSign = (sc.ch == '@');
  109. sc.SetState(SCE_LOUT_IDENTIFIER);
  110. } else if (IsAnOther(sc.ch)) {
  111. sc.SetState(SCE_LOUT_OPERATOR);
  112. }
  113. }
  114. if (sc.atLineEnd) {
  115. // Reset states to begining of colourise so no surprises
  116. // if different sets of lines lexed.
  117. visibleChars = 0;
  118. }
  119. if (!IsASpace(sc.ch)) {
  120. visibleChars++;
  121. }
  122. }
  123. sc.Complete();
  124. }
  125. static void FoldLoutDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[],
  126. Accessor &styler) {
  127. Sci_PositionU endPos = startPos + length;
  128. int visibleChars = 0;
  129. Sci_Position lineCurrent = styler.GetLine(startPos);
  130. int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
  131. int levelCurrent = levelPrev;
  132. char chNext = styler[startPos];
  133. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  134. int styleNext = styler.StyleAt(startPos);
  135. char s[10] = "";
  136. for (Sci_PositionU i = startPos; i < endPos; i++) {
  137. char ch = chNext;
  138. chNext = styler.SafeGetCharAt(i + 1);
  139. int style = styleNext;
  140. styleNext = styler.StyleAt(i + 1);
  141. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  142. if (style == SCE_LOUT_WORD) {
  143. if (ch == '@') {
  144. for (Sci_PositionU j = 0; j < 8; j++) {
  145. if (!IsAWordChar(styler[i + j])) {
  146. break;
  147. }
  148. s[j] = styler[i + j];
  149. s[j + 1] = '\0';
  150. }
  151. if (strcmp(s, "@Begin") == 0) {
  152. levelCurrent++;
  153. } else if (strcmp(s, "@End") == 0) {
  154. levelCurrent--;
  155. }
  156. }
  157. } else if (style == SCE_LOUT_OPERATOR) {
  158. if (ch == '{') {
  159. levelCurrent++;
  160. } else if (ch == '}') {
  161. levelCurrent--;
  162. }
  163. }
  164. if (atEOL) {
  165. int lev = levelPrev;
  166. if (visibleChars == 0 && foldCompact) {
  167. lev |= SC_FOLDLEVELWHITEFLAG;
  168. }
  169. if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
  170. lev |= SC_FOLDLEVELHEADERFLAG;
  171. }
  172. if (lev != styler.LevelAt(lineCurrent)) {
  173. styler.SetLevel(lineCurrent, lev);
  174. }
  175. lineCurrent++;
  176. levelPrev = levelCurrent;
  177. visibleChars = 0;
  178. }
  179. if (!isspacechar(ch))
  180. visibleChars++;
  181. }
  182. // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  183. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  184. styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  185. }
  186. static const char * const loutWordLists[] = {
  187. "Predefined identifiers",
  188. "Predefined delimiters",
  189. "Predefined keywords",
  190. 0,
  191. };
  192. LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists);