1 // Copyright (c) 1990-2007, Scientific Toolworks, Inc.
2 // Author: Jason Haslam
3 // The License.txt file describes the conditions under which this software may be distributed.
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <assert.h>
10 #include <ctype.h>
11
12 #include "ILexer.h"
13 #include "Scintilla.h"
14 #include "SciLexer.h"
15
16 #include "WordList.h"
17 #include "LexAccessor.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "CharacterSet.h"
21 #include "LexerModule.h"
22
23 using namespace Scintilla;
24
GetRange(Sci_PositionU start,Sci_PositionU end,Accessor & styler,char * s,Sci_PositionU len)25 static void GetRange(Sci_PositionU start,
26 Sci_PositionU end,
27 Accessor &styler,
28 char *s,
29 Sci_PositionU len) {
30 Sci_PositionU i = 0;
31 while ((i < end - start + 1) && (i < len-1)) {
32 s[i] = static_cast<char>(tolower(styler[start + i]));
33 i++;
34 }
35 s[i] = '\0';
36 }
37
ColourisePlmDoc(Sci_PositionU startPos,Sci_Position length,int initStyle,WordList * keywordlists[],Accessor & styler)38 static void ColourisePlmDoc(Sci_PositionU startPos,
39 Sci_Position length,
40 int initStyle,
41 WordList *keywordlists[],
42 Accessor &styler)
43 {
44 Sci_PositionU endPos = startPos + length;
45 int state = initStyle;
46
47 styler.StartAt(startPos);
48 styler.StartSegment(startPos);
49
50 for (Sci_PositionU i = startPos; i < endPos; i++) {
51 char ch = styler.SafeGetCharAt(i);
52 char chNext = styler.SafeGetCharAt(i + 1);
53
54 if (state == SCE_PLM_DEFAULT) {
55 if (ch == '/' && chNext == '*') {
56 styler.ColourTo(i - 1, state);
57 state = SCE_PLM_COMMENT;
58 } else if (ch == '\'') {
59 styler.ColourTo(i - 1, state);
60 state = SCE_PLM_STRING;
61 } else if (isdigit(ch)) {
62 styler.ColourTo(i - 1, state);
63 state = SCE_PLM_NUMBER;
64 } else if (isalpha(ch)) {
65 styler.ColourTo(i - 1, state);
66 state = SCE_PLM_IDENTIFIER;
67 } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
68 ch == '=' || ch == '<' || ch == '>' || ch == ':') {
69 styler.ColourTo(i - 1, state);
70 state = SCE_PLM_OPERATOR;
71 } else if (ch == '$') {
72 styler.ColourTo(i - 1, state);
73 state = SCE_PLM_CONTROL;
74 }
75 } else if (state == SCE_PLM_COMMENT) {
76 if (ch == '*' && chNext == '/') {
77 i++;
78 styler.ColourTo(i, state);
79 state = SCE_PLM_DEFAULT;
80 }
81 } else if (state == SCE_PLM_STRING) {
82 if (ch == '\'') {
83 if (chNext == '\'') {
84 i++;
85 } else {
86 styler.ColourTo(i, state);
87 state = SCE_PLM_DEFAULT;
88 }
89 }
90 } else if (state == SCE_PLM_NUMBER) {
91 if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
92 i--;
93 styler.ColourTo(i, state);
94 state = SCE_PLM_DEFAULT;
95 }
96 } else if (state == SCE_PLM_IDENTIFIER) {
97 if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
98 // Get the entire identifier.
99 char word[1024];
100 Sci_Position segmentStart = styler.GetStartSegment();
101 GetRange(segmentStart, i - 1, styler, word, sizeof(word));
102
103 i--;
104 if (keywordlists[0]->InList(word))
105 styler.ColourTo(i, SCE_PLM_KEYWORD);
106 else
107 styler.ColourTo(i, state);
108 state = SCE_PLM_DEFAULT;
109 }
110 } else if (state == SCE_PLM_OPERATOR) {
111 if (ch != '=' && ch != '>') {
112 i--;
113 styler.ColourTo(i, state);
114 state = SCE_PLM_DEFAULT;
115 }
116 } else if (state == SCE_PLM_CONTROL) {
117 if (ch == '\r' || ch == '\n') {
118 styler.ColourTo(i - 1, state);
119 state = SCE_PLM_DEFAULT;
120 }
121 }
122 }
123 styler.ColourTo(endPos - 1, state);
124 }
125
FoldPlmDoc(Sci_PositionU startPos,Sci_Position length,int initStyle,WordList * [],Accessor & styler)126 static void FoldPlmDoc(Sci_PositionU startPos,
127 Sci_Position length,
128 int initStyle,
129 WordList *[],
130 Accessor &styler)
131 {
132 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
133 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
134 Sci_PositionU endPos = startPos + length;
135 int visibleChars = 0;
136 Sci_Position lineCurrent = styler.GetLine(startPos);
137 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
138 int levelCurrent = levelPrev;
139 char chNext = styler[startPos];
140 int styleNext = styler.StyleAt(startPos);
141 int style = initStyle;
142 Sci_Position startKeyword = 0;
143
144 for (Sci_PositionU i = startPos; i < endPos; i++) {
145 char ch = chNext;
146 chNext = styler.SafeGetCharAt(i + 1);
147 int stylePrev = style;
148 style = styleNext;
149 styleNext = styler.StyleAt(i + 1);
150 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
151
152 if (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD)
153 startKeyword = i;
154
155 if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) {
156 char word[1024];
157 GetRange(startKeyword, i, styler, word, sizeof(word));
158
159 if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0)
160 levelCurrent++;
161 else if (strcmp(word, "end") == 0)
162 levelCurrent--;
163 }
164
165 if (foldComment) {
166 if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT)
167 levelCurrent++;
168 else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT)
169 levelCurrent--;
170 }
171
172 if (atEOL) {
173 int lev = levelPrev;
174 if (visibleChars == 0 && foldCompact)
175 lev |= SC_FOLDLEVELWHITEFLAG;
176 if ((levelCurrent > levelPrev) && (visibleChars > 0))
177 lev |= SC_FOLDLEVELHEADERFLAG;
178 if (lev != styler.LevelAt(lineCurrent)) {
179 styler.SetLevel(lineCurrent, lev);
180 }
181 lineCurrent++;
182 levelPrev = levelCurrent;
183 visibleChars = 0;
184 }
185
186 if (!isspacechar(ch))
187 visibleChars++;
188 }
189
190 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
191 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
192 }
193
194 static const char *const plmWordListDesc[] = {
195 "Keywords",
196 0
197 };
198
199 LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc);
200