]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexMatlab.cxx
af5f59aea5dff63524bbb22fcdbf1323ff838983
[wxWidgets.git] / src / stc / scintilla / src / LexMatlab.cxx
1 // Scintilla source code edit control
2 /** @file LexMatlab.cxx
3 ** Lexer for Matlab.
4 ** Written by Jose' Fonseca
5 **
6 ** Changes by Christoph Dalitz 2003/12/04:
7 ** - added support for Octave
8 ** - Strings can now be included both in single or double quotes
9 **/
10 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
11 // The License.txt file describes the conditions under which this software may be distributed.
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <stdarg.h>
18
19 #include "Platform.h"
20
21 #include "PropSet.h"
22 #include "Accessor.h"
23 #include "StyleContext.h"
24 #include "KeyWords.h"
25 #include "Scintilla.h"
26 #include "SciLexer.h"
27
28 #ifdef SCI_NAMESPACE
29 using namespace Scintilla;
30 #endif
31
32 static bool IsMatlabCommentChar(int c) {
33 return (c == '%') ;
34 }
35
36 static bool IsOctaveCommentChar(int c) {
37 return (c == '%' || c == '#') ;
38 }
39
40 static bool IsMatlabComment(Accessor &styler, int pos, int len) {
41 return len > 0 && IsMatlabCommentChar(styler[pos]) ;
42 }
43
44 static bool IsOctaveComment(Accessor &styler, int pos, int len) {
45 return len > 0 && IsOctaveCommentChar(styler[pos]) ;
46 }
47
48 static inline bool IsAWordChar(const int ch) {
49 return (ch < 0x80) && (isalnum(ch) || ch == '_');
50 }
51
52 static inline bool IsAWordStart(const int ch) {
53 return (ch < 0x80) && (isalnum(ch) || ch == '_');
54 }
55
56 static void ColouriseMatlabOctaveDoc(
57 unsigned int startPos, int length, int initStyle,
58 WordList *keywordlists[], Accessor &styler,
59 bool (*IsCommentChar)(int)) {
60
61 WordList &keywords = *keywordlists[0];
62
63 styler.StartAt(startPos);
64
65 bool transpose = false;
66
67 StyleContext sc(startPos, length, initStyle, styler);
68
69 for (; sc.More(); sc.Forward()) {
70
71 if (sc.state == SCE_MATLAB_OPERATOR) {
72 if (sc.chPrev == '.') {
73 if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
74 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
75 transpose = false;
76 } else if (sc.ch == '\'') {
77 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
78 transpose = true;
79 } else {
80 sc.SetState(SCE_MATLAB_DEFAULT);
81 }
82 } else {
83 sc.SetState(SCE_MATLAB_DEFAULT);
84 }
85 } else if (sc.state == SCE_MATLAB_KEYWORD) {
86 if (!isalnum(sc.ch) && sc.ch != '_') {
87 char s[100];
88 sc.GetCurrentLowered(s, sizeof(s));
89 if (keywords.InList(s)) {
90 sc.SetState(SCE_MATLAB_DEFAULT);
91 transpose = false;
92 } else {
93 sc.ChangeState(SCE_MATLAB_IDENTIFIER);
94 sc.SetState(SCE_MATLAB_DEFAULT);
95 transpose = true;
96 }
97 }
98 } else if (sc.state == SCE_MATLAB_NUMBER) {
99 if (!isdigit(sc.ch) && sc.ch != '.'
100 && !(sc.ch == 'e' || sc.ch == 'E')
101 && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) {
102 sc.SetState(SCE_MATLAB_DEFAULT);
103 transpose = true;
104 }
105 } else if (sc.state == SCE_MATLAB_STRING) {
106 if (sc.ch == '\\') {
107 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
108 sc.Forward();
109 }
110 } else if (sc.ch == '\'') {
111 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
112 }
113 } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) {
114 if (sc.ch == '\\') {
115 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
116 sc.Forward();
117 }
118 } else if (sc.ch == '\"') {
119 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
120 }
121 } else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) {
122 if (sc.atLineEnd) {
123 sc.SetState(SCE_MATLAB_DEFAULT);
124 transpose = false;
125 }
126 }
127
128 if (sc.state == SCE_MATLAB_DEFAULT) {
129 if (IsCommentChar(sc.ch)) {
130 sc.SetState(SCE_MATLAB_COMMENT);
131 } else if (sc.ch == '!') {
132 sc.SetState(SCE_MATLAB_COMMAND);
133 } else if (sc.ch == '\'') {
134 if (transpose) {
135 sc.SetState(SCE_MATLAB_OPERATOR);
136 } else {
137 sc.SetState(SCE_MATLAB_STRING);
138 }
139 } else if (sc.ch == '"') {
140 sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING);
141 } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
142 sc.SetState(SCE_MATLAB_NUMBER);
143 } else if (isalpha(sc.ch)) {
144 sc.SetState(SCE_MATLAB_KEYWORD);
145 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
146 if (sc.ch == ')' || sc.ch == ']') {
147 transpose = true;
148 } else {
149 transpose = false;
150 }
151 sc.SetState(SCE_MATLAB_OPERATOR);
152 } else {
153 transpose = false;
154 }
155 }
156 }
157 sc.Complete();
158 }
159
160 static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle,
161 WordList *keywordlists[], Accessor &styler) {
162 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar);
163 }
164
165 static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle,
166 WordList *keywordlists[], Accessor &styler) {
167 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar);
168 }
169
170 static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int,
171 WordList *[], Accessor &styler,
172 bool (*IsComment)(Accessor&, int, int)) {
173
174 int endPos = startPos + length;
175
176 // Backtrack to previous line in case need to fix its fold status
177 int lineCurrent = styler.GetLine(startPos);
178 if (startPos > 0) {
179 if (lineCurrent > 0) {
180 lineCurrent--;
181 startPos = styler.LineStart(lineCurrent);
182 }
183 }
184 int spaceFlags = 0;
185 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment);
186 char chNext = styler[startPos];
187 for (int i = startPos; i < endPos; i++) {
188 char ch = chNext;
189 chNext = styler.SafeGetCharAt(i + 1);
190
191 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
192 int lev = indentCurrent;
193 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment);
194 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
195 // Only non whitespace lines can be headers
196 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
197 lev |= SC_FOLDLEVELHEADERFLAG;
198 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
199 // Line after is blank so check the next - maybe should continue further?
200 int spaceFlags2 = 0;
201 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment);
202 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
203 lev |= SC_FOLDLEVELHEADERFLAG;
204 }
205 }
206 }
207 indentCurrent = indentNext;
208 styler.SetLevel(lineCurrent, lev);
209 lineCurrent++;
210 }
211 }
212 }
213
214 static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle,
215 WordList *keywordlists[], Accessor &styler) {
216 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment);
217 }
218
219 static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle,
220 WordList *keywordlists[], Accessor &styler) {
221 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment);
222 }
223
224 static const char * const matlabWordListDesc[] = {
225 "Keywords",
226 0
227 };
228
229 static const char * const octaveWordListDesc[] = {
230 "Keywords",
231 0
232 };
233
234 LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc);
235
236 LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc);