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