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