]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexSpice.cxx
6aa2e8fdca6ff1e311e7d8c0dc7fedd14a51a41f
[wxWidgets.git] / src / stc / scintilla / src / LexSpice.cxx
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
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <stdio.h>
12
13 #include <string>
14
15 #include "Platform.h"
16
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "PropSet.h"
20 #include "KeyWords.h"
21 #include "SciLexer.h"
22
23 #ifdef SCI_NAMESPACE
24 using namespace Scintilla;
25 #endif
26
27 /*
28 * Interface
29 */
30
31 static void ColouriseDocument(
32 unsigned int startPos,
33 int length,
34 int initStyle,
35 WordList *keywordlists[],
36 Accessor &styler);
37
38 static const char * const spiceWordListDesc[] = {
39 "Keywords", // SPICE command
40 "Keywords2", // SPICE functions
41 "Keywords3", // SPICE params
42 0
43 };
44
45 LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);
46
47 /*
48 * Implementation
49 */
50
51 static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
52 static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
53 static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
54 static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
55 static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);
56
57 static inline bool IsDelimiterCharacter(int ch);
58 static inline bool IsNumberStartCharacter(int ch);
59 static inline bool IsNumberCharacter(int ch);
60 static inline bool IsSeparatorOrDelimiterCharacter(int ch);
61 static inline bool IsWordStartCharacter(int ch);
62 static inline bool IsWordCharacter(int ch);
63
64 static void ColouriseComment(StyleContext& sc, bool&) {
65 sc.SetState(SCE_SPICE_COMMENTLINE);
66 while (!sc.atLineEnd) {
67 sc.Forward();
68 }
69 }
70
71 static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
72 apostropheStartsAttribute = sc.Match (')');
73 sc.SetState(SCE_SPICE_DELIMITER);
74 sc.ForwardSetState(SCE_SPICE_DEFAULT);
75 }
76
77 static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
78 apostropheStartsAttribute = true;
79 std::string number;
80 sc.SetState(SCE_SPICE_NUMBER);
81 // Get all characters up to a delimiter or a separator, including points, but excluding
82 // double points (ranges).
83 while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
84 number += static_cast<char>(sc.ch);
85 sc.Forward();
86 }
87 // Special case: exponent with sign
88 if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
89 (sc.ch == '+' || sc.ch == '-')) {
90 number += static_cast<char>(sc.ch);
91 sc.Forward ();
92 while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
93 number += static_cast<char>(sc.ch);
94 sc.Forward();
95 }
96 }
97 sc.SetState(SCE_SPICE_DEFAULT);
98 }
99
100 static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
101 sc.SetState(SCE_SPICE_DEFAULT);
102 sc.ForwardSetState(SCE_SPICE_DEFAULT);
103 }
104
105 static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
106 apostropheStartsAttribute = true;
107 sc.SetState(SCE_SPICE_IDENTIFIER);
108 std::string word;
109 while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
110 word += static_cast<char>(tolower(sc.ch));
111 sc.Forward();
112 }
113 if (keywords.InList(word.c_str())) {
114 sc.ChangeState(SCE_SPICE_KEYWORD);
115 if (word != "all") {
116 apostropheStartsAttribute = false;
117 }
118 }
119 else if (keywords2.InList(word.c_str())) {
120 sc.ChangeState(SCE_SPICE_KEYWORD2);
121 if (word != "all") {
122 apostropheStartsAttribute = false;
123 }
124 }
125 else if (keywords3.InList(word.c_str())) {
126 sc.ChangeState(SCE_SPICE_KEYWORD3);
127 if (word != "all") {
128 apostropheStartsAttribute = false;
129 }
130 }
131 sc.SetState(SCE_SPICE_DEFAULT);
132 }
133
134 //
135 // ColouriseDocument
136 //
137 static void ColouriseDocument(
138 unsigned int startPos,
139 int length,
140 int initStyle,
141 WordList *keywordlists[],
142 Accessor &styler) {
143 WordList &keywords = *keywordlists[0];
144 WordList &keywords2 = *keywordlists[1];
145 WordList &keywords3 = *keywordlists[2];
146 StyleContext sc(startPos, length, initStyle, styler);
147 int lineCurrent = styler.GetLine(startPos);
148 bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
149 while (sc.More()) {
150 if (sc.atLineEnd) {
151 // Go to the next line
152 sc.Forward();
153 lineCurrent++;
154 // Remember the line state for future incremental lexing
155 styler.SetLineState(lineCurrent, apostropheStartsAttribute);
156 // Don't continue any styles on the next line
157 sc.SetState(SCE_SPICE_DEFAULT);
158 }
159 // Comments
160 if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
161 ColouriseComment(sc, apostropheStartsAttribute);
162 // Whitespace
163 } else if (IsASpace(sc.ch)) {
164 ColouriseWhiteSpace(sc, apostropheStartsAttribute);
165 // Delimiters
166 } else if (IsDelimiterCharacter(sc.ch)) {
167 ColouriseDelimiter(sc, apostropheStartsAttribute);
168 // Numbers
169 } else if (IsADigit(sc.ch) || sc.ch == '#') {
170 ColouriseNumber(sc, apostropheStartsAttribute);
171 // Keywords or identifiers
172 } else {
173 ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
174 }
175 }
176 sc.Complete();
177 }
178
179 static inline bool IsDelimiterCharacter(int ch) {
180 switch (ch) {
181 case '&':
182 case '\'':
183 case '(':
184 case ')':
185 case '*':
186 case '+':
187 case ',':
188 case '-':
189 case '.':
190 case '/':
191 case ':':
192 case ';':
193 case '<':
194 case '=':
195 case '>':
196 case '|':
197 return true;
198 default:
199 return false;
200 }
201 }
202
203 static inline bool IsNumberCharacter(int ch) {
204 return IsNumberStartCharacter(ch) ||
205 ch == '_' ||
206 ch == '.' ||
207 ch == '#' ||
208 (ch >= 'a' && ch <= 'f') ||
209 (ch >= 'A' && ch <= 'F');
210 }
211
212 static inline bool IsNumberStartCharacter(int ch) {
213 return IsADigit(ch);
214 }
215
216 static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
217 return IsASpace(ch) || IsDelimiterCharacter(ch);
218 }
219
220 static inline bool IsWordCharacter(int ch) {
221 return IsWordStartCharacter(ch) || IsADigit(ch);
222 }
223
224 static inline bool IsWordStartCharacter(int ch) {
225 return (isascii(ch) && isalpha(ch)) || ch == '_';
226 }