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