Update Scintilla to version 3.6.3
[geany-mirror.git] / scintilla / lexers / LexMatlab.cxx
blob6b4b2a92adbcebf37ef76f79d1b0dd9046fa0ba4
1 // Scintilla source code edit control
2 /** @file LexMatlab.cxx
3 ** Lexer for Matlab.
4 ** Written by José 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 ** Changes by John Donoghue 2012/04/02
11 ** - added block comment (and nested block comments)
12 ** - added ... displayed as a comment
13 ** - removed unused IsAWord functions
14 ** - added some comments
16 ** Changes by John Donoghue 2014/08/01
17 ** - fix allowed transpose ' after {} operator
18 **/
19 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
20 // The License.txt file describes the conditions under which this software may be distributed.
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <assert.h>
27 #include <ctype.h>
29 #include "ILexer.h"
30 #include "Scintilla.h"
31 #include "SciLexer.h"
33 #include "WordList.h"
34 #include "LexAccessor.h"
35 #include "Accessor.h"
36 #include "StyleContext.h"
37 #include "CharacterSet.h"
38 #include "LexerModule.h"
40 #ifdef SCI_NAMESPACE
41 using namespace Scintilla;
42 #endif
44 static bool IsMatlabCommentChar(int c) {
45 return (c == '%') ;
48 static bool IsOctaveCommentChar(int c) {
49 return (c == '%' || c == '#') ;
52 static bool IsMatlabComment(Accessor &styler, Sci_Position pos, Sci_Position len) {
53 return len > 0 && IsMatlabCommentChar(styler[pos]) ;
56 static bool IsOctaveComment(Accessor &styler, Sci_Position pos, Sci_Position len) {
57 return len > 0 && IsOctaveCommentChar(styler[pos]) ;
60 static void ColouriseMatlabOctaveDoc(
61 Sci_PositionU startPos, Sci_Position length, int initStyle,
62 WordList *keywordlists[], Accessor &styler,
63 bool (*IsCommentChar)(int),
64 bool ismatlab) {
66 WordList &keywords = *keywordlists[0];
68 styler.StartAt(startPos);
70 // boolean for when the ' is allowed to be transpose vs the start/end
71 // of a string
72 bool transpose = false;
74 // approximate position of first non space character in a line
75 int nonSpaceColumn = -1;
76 // approximate column position of the current character in a line
77 int column = 0;
79 // use the line state of each line to store the block comment depth
80 Sci_Position curLine = styler.GetLine(startPos);
81 int commentDepth = curLine > 0 ? styler.GetLineState(curLine-1) : 0;
84 StyleContext sc(startPos, length, initStyle, styler);
86 for (; sc.More(); sc.Forward(), column++) {
88 if(sc.atLineStart) {
89 // set the line state to the current commentDepth
90 curLine = styler.GetLine(sc.currentPos);
91 styler.SetLineState(curLine, commentDepth);
93 // reset the column to 0, nonSpace to -1 (not set)
94 column = 0;
95 nonSpaceColumn = -1;
98 // save the column position of first non space character in a line
99 if((nonSpaceColumn == -1) && (! IsASpace(sc.ch)))
101 nonSpaceColumn = column;
104 // check for end of states
105 if (sc.state == SCE_MATLAB_OPERATOR) {
106 if (sc.chPrev == '.') {
107 if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
108 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
109 transpose = false;
110 } else if (sc.ch == '\'') {
111 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
112 transpose = true;
113 } else if(sc.ch == '.' && sc.chNext == '.') {
114 // we werent an operator, but a '...'
115 sc.ChangeState(SCE_MATLAB_COMMENT);
116 transpose = false;
117 } else {
118 sc.SetState(SCE_MATLAB_DEFAULT);
120 } else {
121 sc.SetState(SCE_MATLAB_DEFAULT);
123 } else if (sc.state == SCE_MATLAB_KEYWORD) {
124 if (!isalnum(sc.ch) && sc.ch != '_') {
125 char s[100];
126 sc.GetCurrentLowered(s, sizeof(s));
127 if (keywords.InList(s)) {
128 sc.SetState(SCE_MATLAB_DEFAULT);
129 transpose = false;
130 } else {
131 sc.ChangeState(SCE_MATLAB_IDENTIFIER);
132 sc.SetState(SCE_MATLAB_DEFAULT);
133 transpose = true;
136 } else if (sc.state == SCE_MATLAB_NUMBER) {
137 if (!isdigit(sc.ch) && sc.ch != '.'
138 && !(sc.ch == 'e' || sc.ch == 'E')
139 && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) {
140 sc.SetState(SCE_MATLAB_DEFAULT);
141 transpose = true;
143 } else if (sc.state == SCE_MATLAB_STRING) {
144 if (sc.ch == '\'') {
145 if (sc.chNext == '\'') {
146 sc.Forward();
147 } else {
148 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
151 } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) {
152 if (sc.ch == '\\') {
153 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
154 sc.Forward();
156 } else if (sc.ch == '\"') {
157 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
159 } else if (sc.state == SCE_MATLAB_COMMAND) {
160 if (sc.atLineEnd) {
161 sc.SetState(SCE_MATLAB_DEFAULT);
162 transpose = false;
164 } else if (sc.state == SCE_MATLAB_COMMENT) {
165 // end or start of a nested a block comment?
166 if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) {
167 if(commentDepth > 0) commentDepth --;
169 curLine = styler.GetLine(sc.currentPos);
170 styler.SetLineState(curLine, commentDepth);
171 sc.Forward();
173 if (commentDepth == 0) {
174 sc.ForwardSetState(SCE_D_DEFAULT);
175 transpose = false;
178 else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column)
180 commentDepth ++;
182 curLine = styler.GetLine(sc.currentPos);
183 styler.SetLineState(curLine, commentDepth);
184 sc.Forward();
185 transpose = false;
187 } else if(commentDepth == 0) {
188 // single line comment
189 if (sc.atLineEnd || sc.ch == '\r' || sc.ch == '\n') {
190 sc.SetState(SCE_MATLAB_DEFAULT);
191 transpose = false;
196 // check start of a new state
197 if (sc.state == SCE_MATLAB_DEFAULT) {
198 if (IsCommentChar(sc.ch)) {
199 // ncrement depth if we are a block comment
200 if(sc.chNext == '{' && nonSpaceColumn == column)
201 commentDepth ++;
202 curLine = styler.GetLine(sc.currentPos);
203 styler.SetLineState(curLine, commentDepth);
204 sc.SetState(SCE_MATLAB_COMMENT);
205 } else if (sc.ch == '!' && sc.chNext != '=' ) {
206 if(ismatlab) {
207 sc.SetState(SCE_MATLAB_COMMAND);
208 } else {
209 sc.SetState(SCE_MATLAB_OPERATOR);
211 } else if (sc.ch == '\'') {
212 if (transpose) {
213 sc.SetState(SCE_MATLAB_OPERATOR);
214 } else {
215 sc.SetState(SCE_MATLAB_STRING);
217 } else if (sc.ch == '"') {
218 sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING);
219 } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
220 sc.SetState(SCE_MATLAB_NUMBER);
221 } else if (isalpha(sc.ch)) {
222 sc.SetState(SCE_MATLAB_KEYWORD);
223 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
224 if (sc.ch == ')' || sc.ch == ']' || sc.ch == '}') {
225 transpose = true;
226 } else {
227 transpose = false;
229 sc.SetState(SCE_MATLAB_OPERATOR);
230 } else {
231 transpose = false;
235 sc.Complete();
238 static void ColouriseMatlabDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
239 WordList *keywordlists[], Accessor &styler) {
240 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar, true);
243 static void ColouriseOctaveDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
244 WordList *keywordlists[], Accessor &styler) {
245 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar, false);
248 static void FoldMatlabOctaveDoc(Sci_PositionU startPos, Sci_Position length, int,
249 WordList *[], Accessor &styler,
250 bool (*IsComment)(Accessor&, Sci_Position, Sci_Position)) {
252 Sci_Position endPos = startPos + length;
254 // Backtrack to previous line in case need to fix its fold status
255 Sci_Position lineCurrent = styler.GetLine(startPos);
256 if (startPos > 0) {
257 if (lineCurrent > 0) {
258 lineCurrent--;
259 startPos = styler.LineStart(lineCurrent);
262 int spaceFlags = 0;
263 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment);
264 char chNext = styler[startPos];
265 for (Sci_Position i = startPos; i < endPos; i++) {
266 char ch = chNext;
267 chNext = styler.SafeGetCharAt(i + 1);
269 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
270 int lev = indentCurrent;
271 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment);
272 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
273 // Only non whitespace lines can be headers
274 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
275 lev |= SC_FOLDLEVELHEADERFLAG;
276 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
277 // Line after is blank so check the next - maybe should continue further?
278 int spaceFlags2 = 0;
279 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment);
280 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
281 lev |= SC_FOLDLEVELHEADERFLAG;
285 indentCurrent = indentNext;
286 styler.SetLevel(lineCurrent, lev);
287 lineCurrent++;
292 static void FoldMatlabDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
293 WordList *keywordlists[], Accessor &styler) {
294 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment);
297 static void FoldOctaveDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
298 WordList *keywordlists[], Accessor &styler) {
299 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment);
302 static const char * const matlabWordListDesc[] = {
303 "Keywords",
307 static const char * const octaveWordListDesc[] = {
308 "Keywords",
312 LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc);
314 LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc);