1 // Scintilla source code edit control
2 /** @file LexAPDL.cxx
3 ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus.
4 ** By Hadar Raz.
5 **/
6 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <assert.h>
14 #include <ctype.h>
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
27 using namespace Scintilla;
28
IsAWordChar(const int ch)29 static inline bool IsAWordChar(const int ch) {
30 return (ch < 0x80 && (isalnum(ch) || ch == '_'));
31 }
32
IsAnOperator(char ch)33 static inline bool IsAnOperator(char ch) {
34 // '.' left out as it is used to make up numbers
35 if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
36 ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
37 ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
38 ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
39 ch == '$' || ch == ':' || ch == '%')
40 return true;
41 return false;
42 }
43
ColouriseAPDLDoc(Sci_PositionU startPos,Sci_Position length,int initStyle,WordList * keywordlists[],Accessor & styler)44 static void ColouriseAPDLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
45 Accessor &styler) {
46
47 int stringStart = ' ';
48
49 WordList &processors = *keywordlists[0];
50 WordList &commands = *keywordlists[1];
51 WordList &slashcommands = *keywordlists[2];
52 WordList &starcommands = *keywordlists[3];
53 WordList &arguments = *keywordlists[4];
54 WordList &functions = *keywordlists[5];
55
56 // Do not leak onto next line
57 initStyle = SCE_APDL_DEFAULT;
58 StyleContext sc(startPos, length, initStyle, styler);
59
60 for (; sc.More(); sc.Forward()) {
61 // Determine if the current state should terminate.
62 if (sc.state == SCE_APDL_NUMBER) {
63 if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
64 ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
65 sc.SetState(SCE_APDL_DEFAULT);
66 }
67 } else if (sc.state == SCE_APDL_COMMENT) {
68 if (sc.atLineEnd) {
69 sc.SetState(SCE_APDL_DEFAULT);
70 }
71 } else if (sc.state == SCE_APDL_COMMENTBLOCK) {
72 if (sc.atLineEnd) {
73 if (sc.ch == '\r') {
74 sc.Forward();
75 }
76 sc.ForwardSetState(SCE_APDL_DEFAULT);
77 }
78 } else if (sc.state == SCE_APDL_STRING) {
79 if (sc.atLineEnd) {
80 sc.SetState(SCE_APDL_DEFAULT);
81 } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) {
82 sc.ForwardSetState(SCE_APDL_DEFAULT);
83 }
84 } else if (sc.state == SCE_APDL_WORD) {
85 if (!IsAWordChar(sc.ch)) {
86 char s[100];
87 sc.GetCurrentLowered(s, sizeof(s));
88 if (processors.InList(s)) {
89 sc.ChangeState(SCE_APDL_PROCESSOR);
90 } else if (slashcommands.InList(s)) {
91 sc.ChangeState(SCE_APDL_SLASHCOMMAND);
92 } else if (starcommands.InList(s)) {
93 sc.ChangeState(SCE_APDL_STARCOMMAND);
94 } else if (commands.InList(s)) {
95 sc.ChangeState(SCE_APDL_COMMAND);
96 } else if (arguments.InList(s)) {
97 sc.ChangeState(SCE_APDL_ARGUMENT);
98 } else if (functions.InList(s)) {
99 sc.ChangeState(SCE_APDL_FUNCTION);
100 }
101 sc.SetState(SCE_APDL_DEFAULT);
102 }
103 } else if (sc.state == SCE_APDL_OPERATOR) {
104 if (!IsAnOperator(static_cast<char>(sc.ch))) {
105 sc.SetState(SCE_APDL_DEFAULT);
106 }
107 }
108
109 // Determine if a new state should be entered.
110 if (sc.state == SCE_APDL_DEFAULT) {
111 if (sc.ch == '!' && sc.chNext == '!') {
112 sc.SetState(SCE_APDL_COMMENTBLOCK);
113 } else if (sc.ch == '!') {
114 sc.SetState(SCE_APDL_COMMENT);
115 } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
116 sc.SetState(SCE_APDL_NUMBER);
117 } else if (sc.ch == '\'' || sc.ch == '\"') {
118 sc.SetState(SCE_APDL_STRING);
119 stringStart = sc.ch;
120 } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) {
121 sc.SetState(SCE_APDL_WORD);
122 } else if (IsAnOperator(static_cast<char>(sc.ch))) {
123 sc.SetState(SCE_APDL_OPERATOR);
124 }
125 }
126 }
127 sc.Complete();
128 }
129
130 //------------------------------------------------------------------------------
131 // 06-27-07 Sergio Lucato
132 // - Included code folding for Ansys APDL lexer
133 // - Copyied from LexBasic.cxx and modified for APDL
134 //------------------------------------------------------------------------------
135
136 /* Bits:
137 * 1 - whitespace
138 * 2 - operator
139 * 4 - identifier
140 * 8 - decimal digit
141 * 16 - hex digit
142 * 32 - bin digit
143 */
144 static int character_classification[128] =
145 {
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
148 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6,
149 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2,
150 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
151 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4,
152 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
153 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0
154 };
155
IsSpace(int c)156 static bool IsSpace(int c) {
157 return c < 128 && (character_classification[c] & 1);
158 }
159
IsIdentifier(int c)160 static bool IsIdentifier(int c) {
161 return c < 128 && (character_classification[c] & 4);
162 }
163
LowerCase(int c)164 static int LowerCase(int c)
165 {
166 if (c >= 'A' && c <= 'Z')
167 return 'a' + c - 'A';
168 return c;
169 }
170
CheckAPDLFoldPoint(char const * token,int & level)171 static int CheckAPDLFoldPoint(char const *token, int &level) {
172 if (!strcmp(token, "*if") ||
173 !strcmp(token, "*do") ||
174 !strcmp(token, "*dowhile") ) {
175 level |= SC_FOLDLEVELHEADERFLAG;
176 return 1;
177 }
178 if (!strcmp(token, "*endif") ||
179 !strcmp(token, "*enddo") ) {
180 return -1;
181 }
182 return 0;
183 }
184
FoldAPDLDoc(Sci_PositionU startPos,Sci_Position length,int,WordList * [],Accessor & styler)185 static void FoldAPDLDoc(Sci_PositionU startPos, Sci_Position length, int,
186 WordList *[], Accessor &styler) {
187
188 Sci_Position line = styler.GetLine(startPos);
189 int level = styler.LevelAt(line);
190 int go = 0, done = 0;
191 Sci_Position endPos = startPos + length;
192 char word[256];
193 int wordlen = 0;
194 Sci_Position i;
195 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
196 // Scan for tokens at the start of the line (they may include
197 // whitespace, for tokens like "End Function"
198 for (i = startPos; i < endPos; i++) {
199 int c = styler.SafeGetCharAt(i);
200 if (!done && !go) {
201 if (wordlen) { // are we scanning a token already?
202 word[wordlen] = static_cast<char>(LowerCase(c));
203 if (!IsIdentifier(c)) { // done with token
204 word[wordlen] = '\0';
205 go = CheckAPDLFoldPoint(word, level);
206 if (!go) {
207 // Treat any whitespace as single blank, for
208 // things like "End Function".
209 if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
210 word[wordlen] = ' ';
211 if (wordlen < 255)
212 wordlen++;
213 }
214 else // done with this line
215 done = 1;
216 }
217 } else if (wordlen < 255) {
218 wordlen++;
219 }
220 } else { // start scanning at first non-whitespace character
221 if (!IsSpace(c)) {
222 if (IsIdentifier(c)) {
223 word[0] = static_cast<char>(LowerCase(c));
224 wordlen = 1;
225 } else // done with this line
226 done = 1;
227 }
228 }
229 }
230 if (c == '\n') { // line end
231 if (!done && wordlen == 0 && foldCompact) // line was only space
232 level |= SC_FOLDLEVELWHITEFLAG;
233 if (level != styler.LevelAt(line))
234 styler.SetLevel(line, level);
235 level += go;
236 line++;
237 // reset state
238 wordlen = 0;
239 level &= ~SC_FOLDLEVELHEADERFLAG;
240 level &= ~SC_FOLDLEVELWHITEFLAG;
241 go = 0;
242 done = 0;
243 }
244 }
245 }
246
247 static const char * const apdlWordListDesc[] = {
248 "processors",
249 "commands",
250 "slashommands",
251 "starcommands",
252 "arguments",
253 "functions",
254 0
255 };
256
257 LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc);
258