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