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.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
35 static void ColouriseDocument(
36 unsigned int startPos
,
39 WordList
*keywordlists
[],
42 static const char * const spiceWordListDesc
[] = {
43 "Keywords", // SPICE command
44 "Keywords2", // SPICE functions
45 "Keywords3", // SPICE params
49 LexerModule
lmSpice(SCLEX_SPICE
, ColouriseDocument
, "spice", NULL
, spiceWordListDesc
);
55 static void ColouriseComment(StyleContext
& sc
, bool& apostropheStartsAttribute
);
56 static void ColouriseDelimiter(StyleContext
& sc
, bool& apostropheStartsAttribute
);
57 static void ColouriseNumber(StyleContext
& sc
, bool& apostropheStartsAttribute
);
58 static void ColouriseWhiteSpace(StyleContext
& sc
, bool& apostropheStartsAttribute
);
59 static void ColouriseWord(StyleContext
& sc
, WordList
& keywords
, WordList
& keywords2
, WordList
& keywords3
, bool& apostropheStartsAttribute
);
61 static inline bool IsDelimiterCharacter(int ch
);
62 static inline bool IsNumberStartCharacter(int ch
);
63 static inline bool IsNumberCharacter(int ch
);
64 static inline bool IsSeparatorOrDelimiterCharacter(int ch
);
65 static inline bool IsWordStartCharacter(int ch
);
66 static inline bool IsWordCharacter(int ch
);
68 static void ColouriseComment(StyleContext
& sc
, bool&) {
69 sc
.SetState(SCE_SPICE_COMMENTLINE
);
70 while (!sc
.atLineEnd
) {
75 static void ColouriseDelimiter(StyleContext
& sc
, bool& apostropheStartsAttribute
) {
76 apostropheStartsAttribute
= sc
.Match (')');
77 sc
.SetState(SCE_SPICE_DELIMITER
);
78 sc
.ForwardSetState(SCE_SPICE_DEFAULT
);
81 static void ColouriseNumber(StyleContext
& sc
, bool& apostropheStartsAttribute
) {
82 apostropheStartsAttribute
= true;
84 sc
.SetState(SCE_SPICE_NUMBER
);
85 // Get all characters up to a delimiter or a separator, including points, but excluding
86 // double points (ranges).
87 while (!IsSeparatorOrDelimiterCharacter(sc
.ch
) || (sc
.ch
== '.' && sc
.chNext
!= '.')) {
88 number
+= static_cast<char>(sc
.ch
);
91 // Special case: exponent with sign
92 if ((sc
.chPrev
== 'e' || sc
.chPrev
== 'E') &&
93 (sc
.ch
== '+' || sc
.ch
== '-')) {
94 number
+= static_cast<char>(sc
.ch
);
96 while (!IsSeparatorOrDelimiterCharacter(sc
.ch
)) {
97 number
+= static_cast<char>(sc
.ch
);
101 sc
.SetState(SCE_SPICE_DEFAULT
);
104 static void ColouriseWhiteSpace(StyleContext
& sc
, bool& ) {
105 sc
.SetState(SCE_SPICE_DEFAULT
);
106 sc
.ForwardSetState(SCE_SPICE_DEFAULT
);
109 static void ColouriseWord(StyleContext
& sc
, WordList
& keywords
, WordList
& keywords2
, WordList
& keywords3
, bool& apostropheStartsAttribute
) {
110 apostropheStartsAttribute
= true;
111 sc
.SetState(SCE_SPICE_IDENTIFIER
);
113 while (!sc
.atLineEnd
&& !IsSeparatorOrDelimiterCharacter(sc
.ch
)) {
114 word
+= static_cast<char>(tolower(sc
.ch
));
117 if (keywords
.InList(word
.c_str())) {
118 sc
.ChangeState(SCE_SPICE_KEYWORD
);
120 apostropheStartsAttribute
= false;
123 else if (keywords2
.InList(word
.c_str())) {
124 sc
.ChangeState(SCE_SPICE_KEYWORD2
);
126 apostropheStartsAttribute
= false;
129 else if (keywords3
.InList(word
.c_str())) {
130 sc
.ChangeState(SCE_SPICE_KEYWORD3
);
132 apostropheStartsAttribute
= false;
135 sc
.SetState(SCE_SPICE_DEFAULT
);
141 static void ColouriseDocument(
142 unsigned int startPos
,
145 WordList
*keywordlists
[],
147 WordList
&keywords
= *keywordlists
[0];
148 WordList
&keywords2
= *keywordlists
[1];
149 WordList
&keywords3
= *keywordlists
[2];
150 StyleContext
sc(startPos
, length
, initStyle
, styler
);
151 int lineCurrent
= styler
.GetLine(startPos
);
152 bool apostropheStartsAttribute
= (styler
.GetLineState(lineCurrent
) & 1) != 0;
155 // Go to the next line
158 // Remember the line state for future incremental lexing
159 styler
.SetLineState(lineCurrent
, apostropheStartsAttribute
);
160 // Don't continue any styles on the next line
161 sc
.SetState(SCE_SPICE_DEFAULT
);
164 if ((sc
.Match('*') && sc
.atLineStart
) || sc
.Match('*','~')) {
165 ColouriseComment(sc
, apostropheStartsAttribute
);
167 } else if (IsASpace(sc
.ch
)) {
168 ColouriseWhiteSpace(sc
, apostropheStartsAttribute
);
170 } else if (IsDelimiterCharacter(sc
.ch
)) {
171 ColouriseDelimiter(sc
, apostropheStartsAttribute
);
173 } else if (IsADigit(sc
.ch
) || sc
.ch
== '#') {
174 ColouriseNumber(sc
, apostropheStartsAttribute
);
175 // Keywords or identifiers
177 ColouriseWord(sc
, keywords
, keywords2
, keywords3
, apostropheStartsAttribute
);
183 static inline bool IsDelimiterCharacter(int ch
) {
207 static inline bool IsNumberCharacter(int ch
) {
208 return IsNumberStartCharacter(ch
) ||
212 (ch
>= 'a' && ch
<= 'f') ||
213 (ch
>= 'A' && ch
<= 'F');
216 static inline bool IsNumberStartCharacter(int ch
) {
220 static inline bool IsSeparatorOrDelimiterCharacter(int ch
) {
221 return IsASpace(ch
) || IsDelimiterCharacter(ch
);
224 static inline bool IsWordCharacter(int ch
) {
225 return IsWordStartCharacter(ch
) || IsADigit(ch
);
228 static inline bool IsWordStartCharacter(int ch
) {
229 return (isascii(ch
) && isalpha(ch
)) || ch
== '_';