*** empty log message ***
[anjuta-git-plugin.git] / scintilla / LexEScript.cxx
blob49411588aa50b8eb423d2148cd3e854456a67f10
1 // Scintilla source code edit control
2 /** @file LexESCRIPT.cxx
3 ** Lexer for ESCRIPT
4 **/
5 // Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com)
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdarg.h>
13 #include "Platform.h"
15 #include "PropSet.h"
16 #include "Accessor.h"
17 #include "StyleContext.h"
18 #include "KeyWords.h"
19 #include "Scintilla.h"
20 #include "SciLexer.h"
24 static inline bool IsAWordChar(const int ch) {
25 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
28 static inline bool IsAWordStart(const int ch) {
29 return (ch < 0x80) && (isalnum(ch) || ch == '_');
34 static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
35 Accessor &styler) {
37 WordList &keywords = *keywordlists[0];
38 WordList &keywords2 = *keywordlists[1];
39 WordList &keywords3 = *keywordlists[2];
41 // Do not leak onto next line
42 /*if (initStyle == SCE_ESCRIPT_STRINGEOL)
43 initStyle = SCE_ESCRIPT_DEFAULT;*/
45 StyleContext sc(startPos, length, initStyle, styler);
47 bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0;
49 for (; sc.More(); sc.Forward()) {
51 /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) {
52 // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line
53 sc.SetState(SCE_ESCRIPT_STRING);
54 }*/
56 // Handle line continuation generically.
57 if (sc.ch == '\\') {
58 if (sc.chNext == '\n' || sc.chNext == '\r') {
59 sc.Forward();
60 if (sc.ch == '\r' && sc.chNext == '\n') {
61 sc.Forward();
63 continue;
67 // Determine if the current state should terminate.
68 if (sc.state == SCE_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) {
69 sc.SetState(SCE_ESCRIPT_DEFAULT);
70 } else if (sc.state == SCE_ESCRIPT_NUMBER) {
71 if (!IsADigit(sc.ch) || sc.ch != '.') {
72 sc.SetState(SCE_ESCRIPT_DEFAULT);
74 } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) {
75 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
76 char s[100];
77 if (caseSensitive) {
78 sc.GetCurrent(s, sizeof(s));
79 } else {
80 sc.GetCurrentLowered(s, sizeof(s));
83 // sc.GetCurrentLowered(s, sizeof(s));
85 if (keywords.InList(s)) {
86 sc.ChangeState(SCE_ESCRIPT_WORD);
87 } else if (keywords2.InList(s)) {
88 sc.ChangeState(SCE_ESCRIPT_WORD2);
89 } else if (keywords3.InList(s)) {
90 sc.ChangeState(SCE_ESCRIPT_WORD3);
91 // sc.state = SCE_ESCRIPT_IDENTIFIER;
93 sc.SetState(SCE_ESCRIPT_DEFAULT);
95 } else if (sc.state == SCE_ESCRIPT_COMMENT) {
96 if (sc.Match('*', '/')) {
97 sc.Forward();
98 sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
100 } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) {
101 if (sc.Match('*', '/')) {
102 sc.Forward();
103 sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
105 } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) {
106 if (sc.atLineEnd) {
107 sc.SetState(SCE_ESCRIPT_DEFAULT);
109 } else if (sc.state == SCE_ESCRIPT_STRING) {
110 if (sc.ch == '\\') {
111 if (sc.chNext == '\"' || sc.chNext == '\\') {
112 sc.Forward();
114 } else if (sc.ch == '\"') {
115 sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
119 // Determine if a new state should be entered.
120 if (sc.state == SCE_ESCRIPT_DEFAULT) {
121 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
122 sc.SetState(SCE_ESCRIPT_NUMBER);
123 } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) {
124 sc.SetState(SCE_ESCRIPT_IDENTIFIER);
125 } else if (sc.Match('/', '*')) {
126 sc.SetState(SCE_ESCRIPT_COMMENT);
127 sc.Forward(); // Eat the * so it isn't used for the end of the comment
128 } else if (sc.Match('/', '/')) {
129 sc.SetState(SCE_ESCRIPT_COMMENTLINE);
130 } else if (sc.ch == '\"') {
131 sc.SetState(SCE_ESCRIPT_STRING);
132 //} else if (isoperator(static_cast<char>(sc.ch))) {
133 } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') {
134 sc.SetState(SCE_ESCRIPT_OPERATOR);
135 } else if (sc.ch == '{' || sc.ch == '}') {
136 sc.SetState(SCE_ESCRIPT_BRACE);
141 sc.Complete();
145 static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) {
146 int lev = 0;
147 if (strcmp(prevWord, "end") == 0) return lev;
148 if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0)
149 return -1;
151 if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0
152 || strcmp(s, "program") == 0 || strcmp(s, "function") == 0
153 || strcmp(s, "while") == 0 || strcmp(s, "case") == 0
154 || strcmp(s, "if") == 0 ) {
155 lev = 1;
156 } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0
157 || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0
158 || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0
159 || strcmp(s, "endif") == 0 ) {
160 lev = -1;
163 return lev;
167 static bool IsStreamCommentStyle(int style) {
168 return style == SCE_ESCRIPT_COMMENT ||
169 style == SCE_ESCRIPT_COMMENTDOC ||
170 style == SCE_ESCRIPT_COMMENTLINE;
173 static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
174 //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
175 // Do not know how to fold the comment at the moment.
176 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
177 bool foldComment = true;
178 unsigned int endPos = startPos + length;
179 int visibleChars = 0;
180 int lineCurrent = styler.GetLine(startPos);
181 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
182 int levelCurrent = levelPrev;
183 char chNext = styler[startPos];
184 int styleNext = styler.StyleAt(startPos);
185 int style = initStyle;
187 int lastStart = 0;
188 char prevWord[32] = "";
190 for (unsigned int i = startPos; i < endPos; i++) {
191 char ch = chNext;
192 chNext = styler.SafeGetCharAt(i + 1);
193 int stylePrev = style;
194 style = styleNext;
195 styleNext = styler.StyleAt(i + 1);
196 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
199 if (foldComment && IsStreamCommentStyle(style)) {
200 if (!IsStreamCommentStyle(stylePrev)) {
201 levelCurrent++;
202 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
203 // Comments don't end at end of line and the next character may be unstyled.
204 levelCurrent--;
208 if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) {
209 if ((ch == '/') && (chNext == '/')) {
210 char chNext2 = styler.SafeGetCharAt(i + 2);
211 if (chNext2 == '{') {
212 levelCurrent++;
213 } else if (chNext2 == '}') {
214 levelCurrent--;
219 if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3)
221 // Store last word start point.
222 lastStart = i;
225 if (style == SCE_ESCRIPT_WORD3) {
226 if(iswordchar(ch) && !iswordchar(chNext)) {
227 char s[32];
228 unsigned int j;
229 for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) {
230 s[j] = static_cast<char>(tolower(styler[lastStart + j]));
232 s[j] = '\0';
233 levelCurrent += classifyFoldPointESCRIPT(s, prevWord);
234 strcpy(prevWord, s);
237 if (atEOL) {
238 int lev = levelPrev;
239 if (visibleChars == 0 && foldCompact)
240 lev |= SC_FOLDLEVELWHITEFLAG;
241 if ((levelCurrent > levelPrev) && (visibleChars > 0))
242 lev |= SC_FOLDLEVELHEADERFLAG;
243 if (lev != styler.LevelAt(lineCurrent)) {
244 styler.SetLevel(lineCurrent, lev);
246 lineCurrent++;
247 levelPrev = levelCurrent;
248 visibleChars = 0;
249 strcpy(prevWord, "");
252 if (!isspacechar(ch))
253 visibleChars++;
256 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
257 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
258 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
263 static const char * const ESCRIPTWordLists[] = {
264 "Primary keywords and identifiers",
265 "Intrinsic functions",
266 "Extended and user defined functions",
270 LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists);