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