]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexPython.cxx
c6c5e6d342861ab518a77acf6b9203c5d34ead20
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexPython.cxx
1 // SciTE - Scintilla based Text Editor
2 // LexPython.cxx - lexer for Python
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11
12 #include "Platform.h"
13
14 #include "PropSet.h"
15 #include "Accessor.h"
16 #include "KeyWords.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 static void classifyWordPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
21 char s[100];
22 bool wordIsNumber = isdigit(styler[start]);
23 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
24 s[i] = styler[start + i];
25 s[i + 1] = '\0';
26 }
27 char chAttr = SCE_P_IDENTIFIER;
28 if (0 == strcmp(prevWord, "class"))
29 chAttr = SCE_P_CLASSNAME;
30 else if (0 == strcmp(prevWord, "def"))
31 chAttr = SCE_P_DEFNAME;
32 else if (wordIsNumber)
33 chAttr = SCE_P_NUMBER;
34 else if (keywords.InList(s))
35 chAttr = SCE_P_WORD;
36 styler.ColourTo(end, chAttr);
37 strcpy(prevWord, s);
38 }
39
40 static bool IsPyComment(StylingContext &styler, int pos, int len) {
41 return len>0 && styler[pos]=='#';
42 }
43
44 static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
45 WordList *keywordlists[], StylingContext &styler) {
46
47 // Python uses a different mask because bad indentation is marked by oring with 32
48 styler.StartAt(startPos, 127);
49
50 WordList &keywords = *keywordlists[0];
51
52 //Platform::DebugPrintf("Python coloured\n");
53 bool fold = styler.GetPropSet().GetInt("fold");
54 int whingeLevel = styler.GetPropSet().GetInt("tab.timmy.whinge.level");
55 char prevWord[200];
56 prevWord[0] = '\0';
57 if (length == 0)
58 return ;
59 int lineCurrent = styler.GetLine(startPos);
60 int spaceFlags = 0;
61 // TODO: Need to check previous line for indentation for both folding and bad indentation
62 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
63
64 int state = initStyle & 31;
65 char chPrev = ' ';
66 char chPrev2 = ' ';
67 char chNext = styler[startPos];
68 char chNext2 = styler[startPos];
69 styler.StartSegment(startPos);
70 int lengthDoc = startPos + length;
71 bool atStartLine = true;
72 for (int i = startPos; i <= lengthDoc; i++) {
73
74 if (atStartLine) {
75 if (whingeLevel == 1) {
76 styler.SetFlags((spaceFlags & wsInconsistent) ? 64 : 0, state);
77 } else if (whingeLevel == 2) {
78 styler.SetFlags((spaceFlags & wsSpaceTab) ? 64 : 0, state);
79 } else if (whingeLevel == 3) {
80 styler.SetFlags((spaceFlags & wsSpace) ? 64 : 0, state);
81 } else if (whingeLevel == 4) {
82 styler.SetFlags((spaceFlags & wsTab) ? 64 : 0, state);
83 }
84 atStartLine = false;
85 }
86
87 char ch = chNext;
88 chNext = styler.SafeGetCharAt(i + 1);
89 chNext2 = styler.SafeGetCharAt(i + 2);
90
91 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
92 if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
93 // Perform colourisation of white space and triple quoted strings at end of each line to allow
94 // tab marking to work inside white space and triple quoted strings
95 styler.ColourTo(i, state);
96 }
97
98 int lev = indentCurrent;
99 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsPyComment);
100 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
101 // Only non whitespace lines can be headers
102 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
103 lev |= SC_FOLDLEVELHEADERFLAG;
104 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
105 // Line after is blank so check the next - maybe should continue further?
106 int spaceFlags2 = 0;
107 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsPyComment);
108 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
109 lev |= SC_FOLDLEVELHEADERFLAG;
110 }
111 }
112 }
113 indentCurrent = indentNext;
114 if (fold) {
115 styler.SetLevel(lineCurrent, lev);
116 }
117 lineCurrent++;
118 atStartLine = true;
119 }
120
121 if (styler.IsLeadByte(ch)) {
122 chNext = styler.SafeGetCharAt(i + 2);
123 chPrev = ' ';
124 chPrev2 = ' ';
125 i += 1;
126 continue;
127 }
128
129 if (state == SCE_P_STRINGEOL) {
130 if (ch != '\r' && ch != '\n') {
131 styler.ColourTo(i - 1, state);
132 state = SCE_P_DEFAULT;
133 }
134 }
135 if (state == SCE_P_DEFAULT) {
136 if (iswordstart(ch)) {
137 styler.ColourTo(i - 1, state);
138 state = SCE_P_WORD;
139 } else if (ch == '#') {
140 styler.ColourTo(i - 1, state);
141 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
142 } else if (ch == '\"') {
143 styler.ColourTo(i - 1, state);
144 if (chNext == '\"' && chNext2 == '\"') {
145 i += 2;
146 state = SCE_P_TRIPLEDOUBLE;
147 ch = ' ';
148 chPrev = ' ';
149 chNext = styler.SafeGetCharAt(i + 1);
150 } else {
151 state = SCE_P_STRING;
152 }
153 } else if (ch == '\'') {
154 styler.ColourTo(i - 1, state);
155 if (chNext == '\'' && chNext2 == '\'') {
156 i += 2;
157 state = SCE_P_TRIPLE;
158 ch = ' ';
159 chPrev = ' ';
160 chNext = styler.SafeGetCharAt(i + 1);
161 } else {
162 state = SCE_P_CHARACTER;
163 }
164 } else if (isoperator(ch)) {
165 styler.ColourTo(i - 1, state);
166 styler.ColourTo(i, SCE_P_OPERATOR);
167 }
168 } else if (state == SCE_P_WORD) {
169 if (!iswordchar(ch)) {
170 classifyWordPy(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
171 state = SCE_P_DEFAULT;
172 if (ch == '#') {
173 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
174 } else if (ch == '\"') {
175 if (chNext == '\"' && chNext2 == '\"') {
176 i += 2;
177 state = SCE_P_TRIPLEDOUBLE;
178 ch = ' ';
179 chPrev = ' ';
180 chNext = styler.SafeGetCharAt(i + 1);
181 } else {
182 state = SCE_P_STRING;
183 }
184 } else if (ch == '\'') {
185 if (chNext == '\'' && chNext2 == '\'') {
186 i += 2;
187 state = SCE_P_TRIPLE;
188 ch = ' ';
189 chPrev = ' ';
190 chNext = styler.SafeGetCharAt(i + 1);
191 } else {
192 state = SCE_P_CHARACTER;
193 }
194 } else if (isoperator(ch)) {
195 styler.ColourTo(i, SCE_P_OPERATOR);
196 }
197 }
198 } else {
199 if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
200 if (ch == '\r' || ch == '\n') {
201 styler.ColourTo(i - 1, state);
202 state = SCE_P_DEFAULT;
203 }
204 } else if (state == SCE_P_STRING) {
205 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
206 styler.ColourTo(i - 1, state);
207 state = SCE_P_STRINGEOL;
208 } else if (ch == '\\') {
209 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
210 i++;
211 ch = chNext;
212 chNext = styler.SafeGetCharAt(i + 1);
213 }
214 } else if (ch == '\"') {
215 styler.ColourTo(i, state);
216 state = SCE_P_DEFAULT;
217 }
218 } else if (state == SCE_P_CHARACTER) {
219 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
220 styler.ColourTo(i - 1, state);
221 state = SCE_P_STRINGEOL;
222 } else if (ch == '\\') {
223 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
224 i++;
225 ch = chNext;
226 chNext = styler.SafeGetCharAt(i + 1);
227 }
228 } else if (ch == '\'') {
229 styler.ColourTo(i, state);
230 state = SCE_P_DEFAULT;
231 }
232 } else if (state == SCE_P_TRIPLE) {
233 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
234 styler.ColourTo(i, state);
235 state = SCE_P_DEFAULT;
236 }
237 } else if (state == SCE_P_TRIPLEDOUBLE) {
238 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
239 styler.ColourTo(i, state);
240 state = SCE_P_DEFAULT;
241 }
242 }
243 }
244 chPrev2 = chPrev;
245 chPrev = ch;
246 }
247 if (state == SCE_P_WORD) {
248 classifyWordPy(styler.GetStartSegment(), lengthDoc, keywords, styler, prevWord);
249 } else {
250 styler.ColourTo(lengthDoc, state);
251 }
252 }
253
254 LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc);