Update Scintilla to version 3.4.1
[geany-mirror.git] / scintilla / lexers / LexMatlab.cxx
bloba8ac03cc7f2c640829c7991f90516310499f1728
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
15 **/
16 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
17 // The License.txt file describes the conditions under which this software may be distributed.
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <assert.h>
24 #include <ctype.h>
26 #include "ILexer.h"
27 #include "Scintilla.h"
28 #include "SciLexer.h"
30 #include "WordList.h"
31 #include "LexAccessor.h"
32 #include "Accessor.h"
33 #include "StyleContext.h"
34 #include "CharacterSet.h"
35 #include "LexerModule.h"
37 #ifdef SCI_NAMESPACE
38 using namespace Scintilla;
39 #endif
41 static bool IsMatlabCommentChar(int c) {
42 return (c == '%') ;
45 static bool IsOctaveCommentChar(int c) {
46 return (c == '%' || c == '#') ;
49 static bool IsMatlabComment(Accessor &styler, int pos, int len) {
50 return len > 0 && IsMatlabCommentChar(styler[pos]) ;
53 static bool IsOctaveComment(Accessor &styler, int pos, int len) {
54 return len > 0 && IsOctaveCommentChar(styler[pos]) ;
57 static void ColouriseMatlabOctaveDoc(
58 unsigned int startPos, int length, int initStyle,
59 WordList *keywordlists[], Accessor &styler,
60 bool (*IsCommentChar)(int),
61 bool ismatlab) {
63 WordList &keywords = *keywordlists[0];
65 styler.StartAt(startPos);
67 // boolean for when the ' is allowed to be transpose vs the start/end
68 // of a string
69 bool transpose = false;
71 // approximate position of first non space character in a line
72 int nonSpaceColumn = -1;
73 // approximate column position of the current character in a line
74 int column = 0;
76 // use the line state of each line to store the block comment depth
77 int curLine = styler.GetLine(startPos);
78 int commentDepth = curLine > 0 ? styler.GetLineState(curLine-1) : 0;
81 StyleContext sc(startPos, length, initStyle, styler);
83 for (; sc.More(); sc.Forward(), column++) {
85 if(sc.atLineStart) {
86 // set the line state to the current commentDepth
87 curLine = styler.GetLine(sc.currentPos);
88 styler.SetLineState(curLine, commentDepth);
90 // reset the column to 0, nonSpace to -1 (not set)
91 column = 0;
92 nonSpaceColumn = -1;
95 // save the column position of first non space character in a line
96 if((nonSpaceColumn == -1) && (! IsASpace(sc.ch)))
98 nonSpaceColumn = column;
101 // check for end of states
102 if (sc.state == SCE_MATLAB_OPERATOR) {
103 if (sc.chPrev == '.') {
104 if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
105 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
106 transpose = false;
107 } else if (sc.ch == '\'') {
108 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
109 transpose = true;
110 } else if(sc.ch == '.' && sc.chNext == '.') {
111 // we werent an operator, but a '...'
112 sc.ChangeState(SCE_MATLAB_COMMENT);
113 transpose = false;
114 } else {
115 sc.SetState(SCE_MATLAB_DEFAULT);
117 } else {
118 sc.SetState(SCE_MATLAB_DEFAULT);
120 } else if (sc.state == SCE_MATLAB_KEYWORD) {
121 if (!isalnum(sc.ch) && sc.ch != '_') {
122 char s[100];
123 sc.GetCurrentLowered(s, sizeof(s));
124 if (keywords.InList(s)) {
125 sc.SetState(SCE_MATLAB_DEFAULT);
126 transpose = false;
127 } else {
128 sc.ChangeState(SCE_MATLAB_IDENTIFIER);
129 sc.SetState(SCE_MATLAB_DEFAULT);
130 transpose = true;
133 } else if (sc.state == SCE_MATLAB_NUMBER) {
134 if (!isdigit(sc.ch) && sc.ch != '.'
135 && !(sc.ch == 'e' || sc.ch == 'E')
136 && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) {
137 sc.SetState(SCE_MATLAB_DEFAULT);
138 transpose = true;
140 } else if (sc.state == SCE_MATLAB_STRING) {
141 if (sc.ch == '\'') {
142 if (sc.chNext == '\'') {
143 sc.Forward();
144 } else {
145 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
148 } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) {
149 if (sc.ch == '\\') {
150 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
151 sc.Forward();
153 } else if (sc.ch == '\"') {
154 sc.ForwardSetState(SCE_MATLAB_DEFAULT);
156 } else if (sc.state == SCE_MATLAB_COMMAND) {
157 if (sc.atLineEnd) {
158 sc.SetState(SCE_MATLAB_DEFAULT);
159 transpose = false;
161 } else if (sc.state == SCE_MATLAB_COMMENT) {
162 // end or start of a nested a block comment?
163 if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) {
164 if(commentDepth > 0) commentDepth --;
166 curLine = styler.GetLine(sc.currentPos);
167 styler.SetLineState(curLine, commentDepth);
168 sc.Forward();
170 if (commentDepth == 0) {
171 sc.ForwardSetState(SCE_D_DEFAULT);
172 transpose = false;
175 else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column)
177 commentDepth ++;
179 curLine = styler.GetLine(sc.currentPos);
180 styler.SetLineState(curLine, commentDepth);
181 sc.Forward();
182 transpose = false;
184 } else if(commentDepth == 0) {
185 // single line comment
186 if (sc.atLineEnd || sc.ch == '\r' || sc.ch == '\n') {
187 sc.SetState(SCE_MATLAB_DEFAULT);
188 transpose = false;
193 // check start of a new state
194 if (sc.state == SCE_MATLAB_DEFAULT) {
195 if (IsCommentChar(sc.ch)) {
196 // ncrement depth if we are a block comment
197 if(sc.chNext == '{' && nonSpaceColumn == column)
198 commentDepth ++;
199 curLine = styler.GetLine(sc.currentPos);
200 styler.SetLineState(curLine, commentDepth);
201 sc.SetState(SCE_MATLAB_COMMENT);
202 } else if (sc.ch == '!' && sc.chNext != '=' ) {
203 if(ismatlab) {
204 sc.SetState(SCE_MATLAB_COMMAND);
205 } else {
206 sc.SetState(SCE_MATLAB_OPERATOR);
208 } else if (sc.ch == '\'') {
209 if (transpose) {
210 sc.SetState(SCE_MATLAB_OPERATOR);
211 } else {
212 sc.SetState(SCE_MATLAB_STRING);
214 } else if (sc.ch == '"') {
215 sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING);
216 } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
217 sc.SetState(SCE_MATLAB_NUMBER);
218 } else if (isalpha(sc.ch)) {
219 sc.SetState(SCE_MATLAB_KEYWORD);
220 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
221 if (sc.ch == ')' || sc.ch == ']') {
222 transpose = true;
223 } else {
224 transpose = false;
226 sc.SetState(SCE_MATLAB_OPERATOR);
227 } else {
228 transpose = false;
232 sc.Complete();
235 static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle,
236 WordList *keywordlists[], Accessor &styler) {
237 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar, true);
240 static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle,
241 WordList *keywordlists[], Accessor &styler) {
242 ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar, false);
245 static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int,
246 WordList *[], Accessor &styler,
247 bool (*IsComment)(Accessor&, int, int)) {
249 int endPos = startPos + length;
251 // Backtrack to previous line in case need to fix its fold status
252 int lineCurrent = styler.GetLine(startPos);
253 if (startPos > 0) {
254 if (lineCurrent > 0) {
255 lineCurrent--;
256 startPos = styler.LineStart(lineCurrent);
259 int spaceFlags = 0;
260 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment);
261 char chNext = styler[startPos];
262 for (int i = startPos; i < endPos; i++) {
263 char ch = chNext;
264 chNext = styler.SafeGetCharAt(i + 1);
266 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
267 int lev = indentCurrent;
268 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment);
269 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
270 // Only non whitespace lines can be headers
271 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
272 lev |= SC_FOLDLEVELHEADERFLAG;
273 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
274 // Line after is blank so check the next - maybe should continue further?
275 int spaceFlags2 = 0;
276 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment);
277 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
278 lev |= SC_FOLDLEVELHEADERFLAG;
282 indentCurrent = indentNext;
283 styler.SetLevel(lineCurrent, lev);
284 lineCurrent++;
289 static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle,
290 WordList *keywordlists[], Accessor &styler) {
291 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment);
294 static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle,
295 WordList *keywordlists[], Accessor &styler) {
296 FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment);
299 static const char * const matlabWordListDesc[] = {
300 "Keywords",
304 static const char * const octaveWordListDesc[] = {
305 "Keywords",
309 LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc);
311 LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc);