1 // Scintilla source code edit control
5 // Copyright 2006 by Fabien Proriol
6 // The License.txt file describes the conditions under which this software may be distributed.
18 #include "Scintilla.h"
22 #include "LexAccessor.h"
24 #include "StyleContext.h"
25 #include "CharacterSet.h"
26 #include "LexerModule.h"
29 using namespace Scintilla
;
36 static void ColouriseDocument(
37 unsigned int startPos
,
40 WordList
*keywordlists
[],
43 static const char * const spiceWordListDesc
[] = {
44 "Keywords", // SPICE command
45 "Keywords2", // SPICE functions
46 "Keywords3", // SPICE params
50 LexerModule
lmSpice(SCLEX_SPICE
, ColouriseDocument
, "spice", NULL
, spiceWordListDesc
);
56 static void ColouriseComment(StyleContext
& sc
, bool& apostropheStartsAttribute
);
57 static void ColouriseDelimiter(StyleContext
& sc
, bool& apostropheStartsAttribute
);
58 static void ColouriseNumber(StyleContext
& sc
, bool& apostropheStartsAttribute
);
59 static void ColouriseWhiteSpace(StyleContext
& sc
, bool& apostropheStartsAttribute
);
60 static void ColouriseWord(StyleContext
& sc
, WordList
& keywords
, WordList
& keywords2
, WordList
& keywords3
, bool& apostropheStartsAttribute
);
62 static inline bool IsDelimiterCharacter(int ch
);
63 static inline bool IsNumberStartCharacter(int ch
);
64 static inline bool IsNumberCharacter(int ch
);
65 static inline bool IsSeparatorOrDelimiterCharacter(int ch
);
66 static inline bool IsWordStartCharacter(int ch
);
67 static inline bool IsWordCharacter(int ch
);
69 static void ColouriseComment(StyleContext
& sc
, bool&) {
70 sc
.SetState(SCE_SPICE_COMMENTLINE
);
71 while (!sc
.atLineEnd
) {
76 static void ColouriseDelimiter(StyleContext
& sc
, bool& apostropheStartsAttribute
) {
77 apostropheStartsAttribute
= sc
.Match (')');
78 sc
.SetState(SCE_SPICE_DELIMITER
);
79 sc
.ForwardSetState(SCE_SPICE_DEFAULT
);
82 static void ColouriseNumber(StyleContext
& sc
, bool& apostropheStartsAttribute
) {
83 apostropheStartsAttribute
= true;
85 sc
.SetState(SCE_SPICE_NUMBER
);
86 // Get all characters up to a delimiter or a separator, including points, but excluding
87 // double points (ranges).
88 while (!IsSeparatorOrDelimiterCharacter(sc
.ch
) || (sc
.ch
== '.' && sc
.chNext
!= '.')) {
89 number
+= static_cast<char>(sc
.ch
);
92 // Special case: exponent with sign
93 if ((sc
.chPrev
== 'e' || sc
.chPrev
== 'E') &&
94 (sc
.ch
== '+' || sc
.ch
== '-')) {
95 number
+= static_cast<char>(sc
.ch
);
97 while (!IsSeparatorOrDelimiterCharacter(sc
.ch
)) {
98 number
+= static_cast<char>(sc
.ch
);
102 sc
.SetState(SCE_SPICE_DEFAULT
);
105 static void ColouriseWhiteSpace(StyleContext
& sc
, bool& ) {
106 sc
.SetState(SCE_SPICE_DEFAULT
);
107 sc
.ForwardSetState(SCE_SPICE_DEFAULT
);
110 static void ColouriseWord(StyleContext
& sc
, WordList
& keywords
, WordList
& keywords2
, WordList
& keywords3
, bool& apostropheStartsAttribute
) {
111 apostropheStartsAttribute
= true;
112 sc
.SetState(SCE_SPICE_IDENTIFIER
);
114 while (!sc
.atLineEnd
&& !IsSeparatorOrDelimiterCharacter(sc
.ch
)) {
115 word
+= static_cast<char>(tolower(sc
.ch
));
118 if (keywords
.InList(word
.c_str())) {
119 sc
.ChangeState(SCE_SPICE_KEYWORD
);
121 apostropheStartsAttribute
= false;
124 else if (keywords2
.InList(word
.c_str())) {
125 sc
.ChangeState(SCE_SPICE_KEYWORD2
);
127 apostropheStartsAttribute
= false;
130 else if (keywords3
.InList(word
.c_str())) {
131 sc
.ChangeState(SCE_SPICE_KEYWORD3
);
133 apostropheStartsAttribute
= false;
136 sc
.SetState(SCE_SPICE_DEFAULT
);
142 static void ColouriseDocument(
143 unsigned int startPos
,
146 WordList
*keywordlists
[],
148 WordList
&keywords
= *keywordlists
[0];
149 WordList
&keywords2
= *keywordlists
[1];
150 WordList
&keywords3
= *keywordlists
[2];
151 StyleContext
sc(startPos
, length
, initStyle
, styler
);
152 int lineCurrent
= styler
.GetLine(startPos
);
153 bool apostropheStartsAttribute
= (styler
.GetLineState(lineCurrent
) & 1) != 0;
156 // Go to the next line
159 // Remember the line state for future incremental lexing
160 styler
.SetLineState(lineCurrent
, apostropheStartsAttribute
);
161 // Don't continue any styles on the next line
162 sc
.SetState(SCE_SPICE_DEFAULT
);
165 if ((sc
.Match('*') && sc
.atLineStart
) || sc
.Match('*','~')) {
166 ColouriseComment(sc
, apostropheStartsAttribute
);
168 } else if (IsASpace(sc
.ch
)) {
169 ColouriseWhiteSpace(sc
, apostropheStartsAttribute
);
171 } else if (IsDelimiterCharacter(sc
.ch
)) {
172 ColouriseDelimiter(sc
, apostropheStartsAttribute
);
174 } else if (IsADigit(sc
.ch
) || sc
.ch
== '#') {
175 ColouriseNumber(sc
, apostropheStartsAttribute
);
176 // Keywords or identifiers
178 ColouriseWord(sc
, keywords
, keywords2
, keywords3
, apostropheStartsAttribute
);
184 static inline bool IsDelimiterCharacter(int ch
) {
208 static inline bool IsNumberCharacter(int ch
) {
209 return IsNumberStartCharacter(ch
) ||
213 (ch
>= 'a' && ch
<= 'f') ||
214 (ch
>= 'A' && ch
<= 'F');
217 static inline bool IsNumberStartCharacter(int ch
) {
221 static inline bool IsSeparatorOrDelimiterCharacter(int ch
) {
222 return IsASpace(ch
) || IsDelimiterCharacter(ch
);
225 static inline bool IsWordCharacter(int ch
) {
226 return IsWordStartCharacter(ch
) || IsADigit(ch
);
229 static inline bool IsWordStartCharacter(int ch
) {
230 return (isascii(ch
) && isalpha(ch
)) || ch
== '_';