/ext/scintilla/lexers/LexCrontab.cxx

http://commitmonitor.googlecode.com/ · C++ · 226 lines · 183 code · 14 blank · 29 comment · 75 complexity · fe6b0dc61d27b91db3d4abf6c2265a5f MD5 · raw file

  1. // Scintilla source code edit control
  2. /** @file LexCrontab.cxx
  3. ** Lexer to use with extended crontab files used by a powerful
  4. ** Windows scheduler/event monitor/automation manager nnCron.
  5. ** (http://nemtsev.eserv.ru/)
  6. **/
  7. // Copyright 1998-2001 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 void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList
  28. *keywordLists[], Accessor &styler)
  29. {
  30. int state = SCE_NNCRONTAB_DEFAULT;
  31. char chNext = styler[startPos];
  32. int lengthDoc = startPos + length;
  33. // create a buffer large enough to take the largest chunk...
  34. char *buffer = new char[length+1];
  35. int bufferCount = 0;
  36. // used when highliting environment variables inside quoted string:
  37. bool insideString = false;
  38. // this assumes that we have 3 keyword list in conf.properties
  39. WordList &section = *keywordLists[0];
  40. WordList &keyword = *keywordLists[1];
  41. WordList &modifier = *keywordLists[2];
  42. // go through all provided text segment
  43. // using the hand-written state machine shown below
  44. styler.StartAt(startPos);
  45. styler.StartSegment(startPos);
  46. for (int i = startPos; i < lengthDoc; i++) {
  47. char ch = chNext;
  48. chNext = styler.SafeGetCharAt(i + 1);
  49. if (styler.IsLeadByte(ch)) {
  50. chNext = styler.SafeGetCharAt(i + 2);
  51. i++;
  52. continue;
  53. }
  54. switch(state) {
  55. case SCE_NNCRONTAB_DEFAULT:
  56. if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
  57. // whitespace is simply ignored here...
  58. styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
  59. break;
  60. } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') {
  61. // signals the start of a task...
  62. state = SCE_NNCRONTAB_TASK;
  63. styler.ColourTo(i,SCE_NNCRONTAB_TASK);
  64. }
  65. else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' ||
  66. styler.SafeGetCharAt(i+1) == '\t')) {
  67. // signals the start of an extended comment...
  68. state = SCE_NNCRONTAB_COMMENT;
  69. styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
  70. } else if( ch == '#' ) {
  71. // signals the start of a plain comment...
  72. state = SCE_NNCRONTAB_COMMENT;
  73. styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
  74. } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') {
  75. // signals the end of a task...
  76. state = SCE_NNCRONTAB_TASK;
  77. styler.ColourTo(i,SCE_NNCRONTAB_TASK);
  78. } else if( ch == '"') {
  79. state = SCE_NNCRONTAB_STRING;
  80. styler.ColourTo(i,SCE_NNCRONTAB_STRING);
  81. } else if( ch == '%') {
  82. // signals environment variables
  83. state = SCE_NNCRONTAB_ENVIRONMENT;
  84. styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
  85. } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') {
  86. // signals environment variables
  87. state = SCE_NNCRONTAB_ENVIRONMENT;
  88. styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
  89. } else if( ch == '*' ) {
  90. // signals an asterisk
  91. // no state jump necessary for this simple case...
  92. styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK);
  93. } else if( (IsASCII(ch) && isalpha(ch)) || ch == '<' ) {
  94. // signals the start of an identifier
  95. bufferCount = 0;
  96. buffer[bufferCount++] = ch;
  97. state = SCE_NNCRONTAB_IDENTIFIER;
  98. } else if( IsASCII(ch) && isdigit(ch) ) {
  99. // signals the start of a number
  100. bufferCount = 0;
  101. buffer[bufferCount++] = ch;
  102. state = SCE_NNCRONTAB_NUMBER;
  103. } else {
  104. // style it the default style..
  105. styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
  106. }
  107. break;
  108. case SCE_NNCRONTAB_COMMENT:
  109. // if we find a newline here,
  110. // we simply go to default state
  111. // else continue to work on it...
  112. if( ch == '\n' || ch == '\r' ) {
  113. state = SCE_NNCRONTAB_DEFAULT;
  114. } else {
  115. styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
  116. }
  117. break;
  118. case SCE_NNCRONTAB_TASK:
  119. // if we find a newline here,
  120. // we simply go to default state
  121. // else continue to work on it...
  122. if( ch == '\n' || ch == '\r' ) {
  123. state = SCE_NNCRONTAB_DEFAULT;
  124. } else {
  125. styler.ColourTo(i,SCE_NNCRONTAB_TASK);
  126. }
  127. break;
  128. case SCE_NNCRONTAB_STRING:
  129. if( ch == '%' ) {
  130. state = SCE_NNCRONTAB_ENVIRONMENT;
  131. insideString = true;
  132. styler.ColourTo(i-1,SCE_NNCRONTAB_STRING);
  133. break;
  134. }
  135. // if we find the end of a string char, we simply go to default state
  136. // else we're still dealing with an string...
  137. if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') ||
  138. (ch == '\n') || (ch == '\r') ) {
  139. state = SCE_NNCRONTAB_DEFAULT;
  140. }
  141. styler.ColourTo(i,SCE_NNCRONTAB_STRING);
  142. break;
  143. case SCE_NNCRONTAB_ENVIRONMENT:
  144. // if we find the end of a string char, we simply go to default state
  145. // else we're still dealing with an string...
  146. if( ch == '%' && insideString ) {
  147. state = SCE_NNCRONTAB_STRING;
  148. insideString = false;
  149. break;
  150. }
  151. if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\')
  152. || (ch == '\n') || (ch == '\r') || (ch == '>') ) {
  153. state = SCE_NNCRONTAB_DEFAULT;
  154. styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
  155. break;
  156. }
  157. styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT);
  158. break;
  159. case SCE_NNCRONTAB_IDENTIFIER:
  160. // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
  161. if( (IsASCII(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') ||
  162. (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') ||
  163. (ch == '@') ) {
  164. buffer[bufferCount++] = ch;
  165. } else {
  166. state = SCE_NNCRONTAB_DEFAULT;
  167. buffer[bufferCount] = '\0';
  168. // check if the buffer contains a keyword,
  169. // and highlight it if it is a keyword...
  170. if(section.InList(buffer)) {
  171. styler.ColourTo(i,SCE_NNCRONTAB_SECTION );
  172. } else if(keyword.InList(buffer)) {
  173. styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD );
  174. } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
  175. // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
  176. // }
  177. else if(modifier.InList(buffer)) {
  178. styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER );
  179. } else {
  180. styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT);
  181. }
  182. // push back the faulty character
  183. chNext = styler[i--];
  184. }
  185. break;
  186. case SCE_NNCRONTAB_NUMBER:
  187. // stay in CONF_NUMBER state until we find a non-numeric
  188. if( IsASCII(ch) && isdigit(ch) /* || ch == '.' */ ) {
  189. buffer[bufferCount++] = ch;
  190. } else {
  191. state = SCE_NNCRONTAB_DEFAULT;
  192. buffer[bufferCount] = '\0';
  193. // Colourize here... (normal number)
  194. styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER);
  195. // push back a character
  196. chNext = styler[i--];
  197. }
  198. break;
  199. }
  200. }
  201. delete []buffer;
  202. }
  203. static const char * const cronWordListDesc[] = {
  204. "Section keywords and Forth words",
  205. "nnCrontab keywords",
  206. "Modifiers",
  207. 0
  208. };
  209. LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc);