]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexSpice.cxx
5fb5dd77668953444ddfbd6dcdc95dc0cb88b919
[wxWidgets.git] / src / stc / scintilla / lexers / 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 <string.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <assert.h>
13 #include <ctype.h>
14
15 #include <string>
16
17 #include "ILexer.h"
18 #include "Scintilla.h"
19 #include "SciLexer.h"
20
21 #include "WordList.h"
22 #include "LexAccessor.h"
23 #include "Accessor.h"
24 #include "StyleContext.h"
25 #include "CharacterSet.h"
26 #include "LexerModule.h"
27
28 #ifdef SCI_NAMESPACE
29 using namespace Scintilla;
30 #endif
31
32 /*
33 * Interface
34 */
35
36 static void ColouriseDocument(
37 unsigned int startPos,
38 int length,
39 int initStyle,
40 WordList *keywordlists[],
41 Accessor &styler);
42
43 static const char * const spiceWordListDesc[] = {
44 "Keywords", // SPICE command
45 "Keywords2", // SPICE functions
46 "Keywords3", // SPICE params
47 0
48 };
49
50 LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);
51
52 /*
53 * Implementation
54 */
55
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);
61
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);
68
69 static void ColouriseComment(StyleContext& sc, bool&) {
70 sc.SetState(SCE_SPICE_COMMENTLINE);
71 while (!sc.atLineEnd) {
72 sc.Forward();
73 }
74 }
75
76 static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
77 apostropheStartsAttribute = sc.Match (')');
78 sc.SetState(SCE_SPICE_DELIMITER);
79 sc.ForwardSetState(SCE_SPICE_DEFAULT);
80 }
81
82 static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
83 apostropheStartsAttribute = true;
84 std::string number;
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);
90 sc.Forward();
91 }
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);
96 sc.Forward ();
97 while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
98 number += static_cast<char>(sc.ch);
99 sc.Forward();
100 }
101 }
102 sc.SetState(SCE_SPICE_DEFAULT);
103 }
104
105 static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
106 sc.SetState(SCE_SPICE_DEFAULT);
107 sc.ForwardSetState(SCE_SPICE_DEFAULT);
108 }
109
110 static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
111 apostropheStartsAttribute = true;
112 sc.SetState(SCE_SPICE_IDENTIFIER);
113 std::string word;
114 while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
115 word += static_cast<char>(tolower(sc.ch));
116 sc.Forward();
117 }
118 if (keywords.InList(word.c_str())) {
119 sc.ChangeState(SCE_SPICE_KEYWORD);
120 if (word != "all") {
121 apostropheStartsAttribute = false;
122 }
123 }
124 else if (keywords2.InList(word.c_str())) {
125 sc.ChangeState(SCE_SPICE_KEYWORD2);
126 if (word != "all") {
127 apostropheStartsAttribute = false;
128 }
129 }
130 else if (keywords3.InList(word.c_str())) {
131 sc.ChangeState(SCE_SPICE_KEYWORD3);
132 if (word != "all") {
133 apostropheStartsAttribute = false;
134 }
135 }
136 sc.SetState(SCE_SPICE_DEFAULT);
137 }
138
139 //
140 // ColouriseDocument
141 //
142 static void ColouriseDocument(
143 unsigned int startPos,
144 int length,
145 int initStyle,
146 WordList *keywordlists[],
147 Accessor &styler) {
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;
154 while (sc.More()) {
155 if (sc.atLineEnd) {
156 // Go to the next line
157 sc.Forward();
158 lineCurrent++;
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);
163 }
164 // Comments
165 if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
166 ColouriseComment(sc, apostropheStartsAttribute);
167 // Whitespace
168 } else if (IsASpace(sc.ch)) {
169 ColouriseWhiteSpace(sc, apostropheStartsAttribute);
170 // Delimiters
171 } else if (IsDelimiterCharacter(sc.ch)) {
172 ColouriseDelimiter(sc, apostropheStartsAttribute);
173 // Numbers
174 } else if (IsADigit(sc.ch) || sc.ch == '#') {
175 ColouriseNumber(sc, apostropheStartsAttribute);
176 // Keywords or identifiers
177 } else {
178 ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
179 }
180 }
181 sc.Complete();
182 }
183
184 static inline bool IsDelimiterCharacter(int ch) {
185 switch (ch) {
186 case '&':
187 case '\'':
188 case '(':
189 case ')':
190 case '*':
191 case '+':
192 case ',':
193 case '-':
194 case '.':
195 case '/':
196 case ':':
197 case ';':
198 case '<':
199 case '=':
200 case '>':
201 case '|':
202 return true;
203 default:
204 return false;
205 }
206 }
207
208 static inline bool IsNumberCharacter(int ch) {
209 return IsNumberStartCharacter(ch) ||
210 ch == '_' ||
211 ch == '.' ||
212 ch == '#' ||
213 (ch >= 'a' && ch <= 'f') ||
214 (ch >= 'A' && ch <= 'F');
215 }
216
217 static inline bool IsNumberStartCharacter(int ch) {
218 return IsADigit(ch);
219 }
220
221 static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
222 return IsASpace(ch) || IsDelimiterCharacter(ch);
223 }
224
225 static inline bool IsWordCharacter(int ch) {
226 return IsWordStartCharacter(ch) || IsADigit(ch);
227 }
228
229 static inline bool IsWordStartCharacter(int ch) {
230 return (isascii(ch) && isalpha(ch)) || ch == '_';
231 }