LexSpice.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Scintilla source code edit control
  2. /** @file LexSpice.cxx
  3. ** Lexer for Spice
  4. **/
  5. // Copyright 2006 by Fabien Proriol
  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 <string>
  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. * Interface
  28. */
  29. static void ColouriseDocument(
  30. Sci_PositionU startPos,
  31. Sci_Position length,
  32. int initStyle,
  33. WordList *keywordlists[],
  34. Accessor &styler);
  35. static const char * const spiceWordListDesc[] = {
  36. "Keywords", // SPICE command
  37. "Keywords2", // SPICE functions
  38. "Keywords3", // SPICE params
  39. 0
  40. };
  41. LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);
  42. /*
  43. * Implementation
  44. */
  45. static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
  46. static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
  47. static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
  48. static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
  49. static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);
  50. static inline bool IsDelimiterCharacter(int ch);
  51. static inline bool IsSeparatorOrDelimiterCharacter(int ch);
  52. static void ColouriseComment(StyleContext& sc, bool&) {
  53. sc.SetState(SCE_SPICE_COMMENTLINE);
  54. while (!sc.atLineEnd) {
  55. sc.Forward();
  56. }
  57. }
  58. static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
  59. apostropheStartsAttribute = sc.Match (')');
  60. sc.SetState(SCE_SPICE_DELIMITER);
  61. sc.ForwardSetState(SCE_SPICE_DEFAULT);
  62. }
  63. static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
  64. apostropheStartsAttribute = true;
  65. std::string number;
  66. sc.SetState(SCE_SPICE_NUMBER);
  67. // Get all characters up to a delimiter or a separator, including points, but excluding
  68. // double points (ranges).
  69. while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
  70. number += static_cast<char>(sc.ch);
  71. sc.Forward();
  72. }
  73. // Special case: exponent with sign
  74. if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
  75. (sc.ch == '+' || sc.ch == '-')) {
  76. number += static_cast<char>(sc.ch);
  77. sc.Forward ();
  78. while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
  79. number += static_cast<char>(sc.ch);
  80. sc.Forward();
  81. }
  82. }
  83. sc.SetState(SCE_SPICE_DEFAULT);
  84. }
  85. static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
  86. sc.SetState(SCE_SPICE_DEFAULT);
  87. sc.ForwardSetState(SCE_SPICE_DEFAULT);
  88. }
  89. static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
  90. apostropheStartsAttribute = true;
  91. sc.SetState(SCE_SPICE_IDENTIFIER);
  92. std::string word;
  93. while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
  94. word += static_cast<char>(tolower(sc.ch));
  95. sc.Forward();
  96. }
  97. if (keywords.InList(word.c_str())) {
  98. sc.ChangeState(SCE_SPICE_KEYWORD);
  99. if (word != "all") {
  100. apostropheStartsAttribute = false;
  101. }
  102. }
  103. else if (keywords2.InList(word.c_str())) {
  104. sc.ChangeState(SCE_SPICE_KEYWORD2);
  105. if (word != "all") {
  106. apostropheStartsAttribute = false;
  107. }
  108. }
  109. else if (keywords3.InList(word.c_str())) {
  110. sc.ChangeState(SCE_SPICE_KEYWORD3);
  111. if (word != "all") {
  112. apostropheStartsAttribute = false;
  113. }
  114. }
  115. sc.SetState(SCE_SPICE_DEFAULT);
  116. }
  117. //
  118. // ColouriseDocument
  119. //
  120. static void ColouriseDocument(
  121. Sci_PositionU startPos,
  122. Sci_Position length,
  123. int initStyle,
  124. WordList *keywordlists[],
  125. Accessor &styler) {
  126. WordList &keywords = *keywordlists[0];
  127. WordList &keywords2 = *keywordlists[1];
  128. WordList &keywords3 = *keywordlists[2];
  129. StyleContext sc(startPos, length, initStyle, styler);
  130. Sci_Position lineCurrent = styler.GetLine(startPos);
  131. bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
  132. while (sc.More()) {
  133. if (sc.atLineEnd) {
  134. // Go to the next line
  135. sc.Forward();
  136. lineCurrent++;
  137. // Remember the line state for future incremental lexing
  138. styler.SetLineState(lineCurrent, apostropheStartsAttribute);
  139. // Don't continue any styles on the next line
  140. sc.SetState(SCE_SPICE_DEFAULT);
  141. }
  142. // Comments
  143. if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
  144. ColouriseComment(sc, apostropheStartsAttribute);
  145. // Whitespace
  146. } else if (IsASpace(sc.ch)) {
  147. ColouriseWhiteSpace(sc, apostropheStartsAttribute);
  148. // Delimiters
  149. } else if (IsDelimiterCharacter(sc.ch)) {
  150. ColouriseDelimiter(sc, apostropheStartsAttribute);
  151. // Numbers
  152. } else if (IsADigit(sc.ch) || sc.ch == '#') {
  153. ColouriseNumber(sc, apostropheStartsAttribute);
  154. // Keywords or identifiers
  155. } else {
  156. ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
  157. }
  158. }
  159. sc.Complete();
  160. }
  161. static inline bool IsDelimiterCharacter(int ch) {
  162. switch (ch) {
  163. case '&':
  164. case '\'':
  165. case '(':
  166. case ')':
  167. case '*':
  168. case '+':
  169. case ',':
  170. case '-':
  171. case '.':
  172. case '/':
  173. case ':':
  174. case ';':
  175. case '<':
  176. case '=':
  177. case '>':
  178. case '|':
  179. return true;
  180. default:
  181. return false;
  182. }
  183. }
  184. static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
  185. return IsASpace(ch) || IsDelimiterCharacter(ch);
  186. }