]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexAbaqus.cxx
10e8b76b1ec939365946856193c4b92a1d5704bf
1 // Scintilla source code edit control
2 /** @file LexABAQUS.cxx
3 ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz.
5 ** Sort of completely rewritten by Gertjan Kloosterman
7 // The License.txt file describes the conditions under which this software may be distributed.
9 // Code folding copyied and modified from LexBasic.cxx
21 #include "StyleContext.h"
23 #include "Scintilla.h"
27 using namespace Scintilla
;
30 static inline bool IsAWordChar(const int ch
) {
31 return (ch
< 0x80 && (isalnum(ch
) || (ch
== '_')));
34 static inline bool IsAKeywordChar(const int ch
) {
35 return (ch
< 0x80 && (isalnum(ch
) || (ch
== '_') || (ch
== ' ')));
38 static inline bool IsASetChar(const int ch
) {
39 return (ch
< 0x80 && (isalnum(ch
) || (ch
== '_') || (ch
== '.') || (ch
== '-')));
42 static inline bool IsAnOperator(char ch
) {
43 // '.' left out as it is used to make up numbers
44 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
45 ch
== '(' || ch
== ')' || ch
== '=' || ch
== '^' ||
46 ch
== '[' || ch
== ']' || ch
== '<' || ch
== '&' ||
47 ch
== '>' || ch
== ',' || ch
== '|' || ch
== '~' ||
48 ch
== '$' || ch
== ':' || ch
== '%')
53 static void ColouriseABAQUSDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[] /* *keywordlists[] */,
55 enum localState
{ KW_LINE_KW
, KW_LINE_COMMA
, KW_LINE_PAR
, KW_LINE_EQ
, KW_LINE_VAL
, \
56 DAT_LINE_VAL
, DAT_LINE_COMMA
,\
58 ST_ERROR
, LINE_END
} state
;
60 // Do not leak onto next line
62 initStyle
= SCE_ABAQUS_DEFAULT
;
63 StyleContext
sc(startPos
, length
, initStyle
, styler
);
65 // Things are actually quite simple
66 // we have commentlines
67 // keywordlines and datalines
68 // On a data line there will only be colouring of numbers
69 // a keyword line is constructed as
70 // *word,[ paramname[=paramvalue]]*
71 // if the line ends with a , the keyword line continues onto the new line
73 for (; sc
.More(); sc
.Forward()) {
77 // finished the line in keyword state, switch to LINE_END
78 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
80 } else if ( IsAKeywordChar(sc
.ch
) ) {
83 } else if ( sc
.ch
== ',' ) {
84 // Well well we say a comma, arguments *MUST* follow
85 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
86 state
= KW_LINE_COMMA
;
89 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
92 // Done with processing
95 // acomma on a keywordline was seen
96 if ( IsAKeywordChar(sc
.ch
)) {
97 sc
.SetState(SCE_ABAQUS_ARGUMENT
) ;
99 } else if ( sc
.atLineEnd
|| (sc
.ch
== ',') ) {
100 // we remain in keyword mode
101 state
= KW_LINE_COMMA
;
102 } else if ( sc
.ch
== ' ' ) {
103 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
104 state
= KW_LINE_COMMA
;
106 // Anything else constitutes an error
107 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
112 if ( sc
.atLineEnd
) {
113 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
115 } else if ( IsAKeywordChar(sc
.ch
) || (sc
.ch
== '-') ) {
116 // remain in this state
117 state
= KW_LINE_PAR
;
118 } else if ( sc
.ch
== ',' ) {
119 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
120 state
= KW_LINE_COMMA
;
121 } else if ( sc
.ch
== '=' ) {
122 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
125 // Anything else constitutes an error
126 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
131 if ( sc
.ch
== ' ' ) {
132 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
133 // remain in this state
135 } else if ( IsADigit(sc
.ch
) || (sc
.ch
== '-') || (sc
.ch
== '.' && IsADigit(sc
.chNext
)) ) {
136 sc
.SetState(SCE_ABAQUS_NUMBER
) ;
137 state
= KW_LINE_VAL
;
138 } else if ( IsAKeywordChar(sc
.ch
) ) {
139 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
140 state
= KW_LINE_VAL
;
141 } else if ( (sc
.ch
== '\'') || (sc
.ch
== '\"') ) {
142 sc
.SetState(SCE_ABAQUS_STRING
) ;
143 state
= KW_LINE_VAL
;
145 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
150 if ( sc
.atLineEnd
) {
151 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
153 } else if ( IsASetChar(sc
.ch
) && (sc
.state
== SCE_ABAQUS_DEFAULT
) ) {
155 state
= KW_LINE_VAL
;
156 } else if (( (IsADigit(sc
.ch
) || sc
.ch
== '.' || (sc
.ch
== 'e' || sc
.ch
== 'E') ||
157 ((sc
.ch
== '+' || sc
.ch
== '-') && (sc
.chPrev
== 'e' || sc
.chPrev
== 'E')))) &&
158 (sc
.state
== SCE_ABAQUS_NUMBER
)) {
159 // remain in number mode
160 state
= KW_LINE_VAL
;
161 } else if (sc
.state
== SCE_ABAQUS_STRING
) {
162 // accept everything until a closing quote
163 if ( sc
.ch
== '\'' || sc
.ch
== '\"' ) {
164 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
165 state
= KW_LINE_VAL
;
167 } else if ( sc
.ch
== ',' ) {
168 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
169 state
= KW_LINE_COMMA
;
171 // anything else is an error
172 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
177 if ( sc
.atLineEnd
) {
178 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
180 } else if ( IsASetChar(sc
.ch
) && (sc
.state
== SCE_ABAQUS_DEFAULT
) ) {
182 state
= DAT_LINE_VAL
;
183 } else if (( (IsADigit(sc
.ch
) || sc
.ch
== '.' || (sc
.ch
== 'e' || sc
.ch
== 'E') ||
184 ((sc
.ch
== '+' || sc
.ch
== '-') && (sc
.chPrev
== 'e' || sc
.chPrev
== 'E')))) &&
185 (sc
.state
== SCE_ABAQUS_NUMBER
)) {
186 // remain in number mode
187 state
= DAT_LINE_VAL
;
188 } else if (sc
.state
== SCE_ABAQUS_STRING
) {
189 // accept everything until a closing quote
190 if ( sc
.ch
== '\'' || sc
.ch
== '\"' ) {
191 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
192 state
= DAT_LINE_VAL
;
194 } else if ( sc
.ch
== ',' ) {
195 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
196 state
= DAT_LINE_COMMA
;
198 // anything else is an error
199 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
203 case DAT_LINE_COMMA
:
204 // a comma on a data line was seen
205 if ( sc
.atLineEnd
) {
206 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
208 } else if ( sc
.ch
== ' ' ) {
209 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
210 state
= DAT_LINE_COMMA
;
211 } else if (sc
.ch
== ',') {
212 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
213 state
= DAT_LINE_COMMA
;
214 } else if ( IsADigit(sc
.ch
) || (sc
.ch
== '-')|| (sc
.ch
== '.' && IsADigit(sc
.chNext
)) ) {
215 sc
.SetState(SCE_ABAQUS_NUMBER
) ;
216 state
= DAT_LINE_VAL
;
217 } else if ( IsAKeywordChar(sc
.ch
) ) {
218 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
219 state
= DAT_LINE_VAL
;
220 } else if ( (sc
.ch
== '\'') || (sc
.ch
== '\"') ) {
221 sc
.SetState(SCE_ABAQUS_STRING
) ;
222 state
= DAT_LINE_VAL
;
224 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
229 if ( sc
.atLineEnd
) {
230 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
235 if ( sc
.atLineEnd
) {
236 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
241 if ( sc
.atLineEnd
|| sc
.ch
== ' ' ) {
244 } else if ( sc
.ch
== '*' ) {
245 if ( sc
.chNext
== '*' ) {
246 state
= COMMENT_LINE
;
247 sc
.SetState(SCE_ABAQUS_COMMENT
) ;
250 sc
.SetState(SCE_ABAQUS_STARCOMMAND
) ;
253 // it must be a data line, things are as if we are in DAT_LINE_COMMA
254 if ( sc
.ch
== ',' ) {
255 sc
.SetState(SCE_ABAQUS_OPERATOR
) ;
256 state
= DAT_LINE_COMMA
;
257 } else if ( IsADigit(sc
.ch
) || (sc
.ch
== '-')|| (sc
.ch
== '.' && IsADigit(sc
.chNext
)) ) {
258 sc
.SetState(SCE_ABAQUS_NUMBER
) ;
259 state
= DAT_LINE_VAL
;
260 } else if ( IsAKeywordChar(sc
.ch
) ) {
261 sc
.SetState(SCE_ABAQUS_DEFAULT
) ;
262 state
= DAT_LINE_VAL
;
263 } else if ( (sc
.ch
== '\'') || (sc
.ch
== '\"') ) {
264 sc
.SetState(SCE_ABAQUS_STRING
) ;
265 state
= DAT_LINE_VAL
;
267 sc
.SetState(SCE_ABAQUS_PROCESSOR
) ;
277 //------------------------------------------------------------------------------
278 // This copyied and modified from LexBasic.cxx
279 //------------------------------------------------------------------------------
289 static int character_classification
[128] =
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6,
294 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2,
295 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
296 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4,
297 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4,
298 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0
301 static bool IsSpace(int c
) {
302 return c
< 128 && (character_classification
[c
] & 1);
305 static bool IsIdentifier(int c
) {
306 return c
< 128 && (character_classification
[c
] & 4);
309 static int LowerCase(int c
)
311 if (c
>= 'A' && c
<= 'Z')
312 return 'a' + c
- 'A';
316 static int LineEnd(int line
, Accessor
&styler
)
318 const int docLines
= styler
.GetLine(styler
.Length() - 1); // Available last line
320 // if the line is the last line, the eol_pos is styler.Length()
321 // eol will contain a new line, or a virtual new line
322 if ( docLines
== line
)
323 eol_pos
= styler
.Length() ;
325 eol_pos
= styler
.LineStart(line
+ 1) - 1;
329 static int LineStart(int line
, Accessor
&styler
)
331 return styler
.LineStart(line
) ;
336 // bits determines the line type
338 // 2 : only whitespace
339 // 3 : data line with only whitespace
341 // 5 : block open keyword line
342 // 6 : block close keyword line
343 // 7 : keyword line in error
345 static int LineType(int line
, Accessor
&styler
) {
346 int pos
= LineStart(line
, styler
) ;
347 int eol_pos
= LineEnd(line
, styler
) ;
353 while ( i
< eol_pos
) {
354 c
= styler
.SafeGetCharAt(i
);
355 ch
= static_cast<char>(LowerCase(c
));
356 // We can say something as soon as no whitespace
363 if ( i
>= eol_pos
) {
364 // This is a whitespace line, currently
365 // classifies as data line
370 // This is a data line
374 if ( i
== eol_pos
- 1 ) {
375 // Only a single *, error but make keyword line
379 // This means we can have a second character
380 // if that is also a * this means a comment
381 // otherwise it is a keyword.
382 c
= styler
.SafeGetCharAt(i
+1);
383 ch
= static_cast<char>(LowerCase(c
));
388 // At this point we know this is a keyword line
389 // the character at position i is a *
390 // it is not a comment line
398 while ( (i
< eol_pos
) && (wlen
< 255) ) {
399 c
= styler
.SafeGetCharAt(i
);
400 ch
= static_cast<char>(LowerCase(c
));
402 if ( (!IsSpace(c
)) && (!IsIdentifier(c
)) )
405 if ( IsIdentifier(c
) ) {
416 if ( !strcmp(word
, "*step") ||
417 !strcmp(word
, "*part") ||
418 !strcmp(word
, "*instance") ||
419 !strcmp(word
, "*assembly")) {
423 if ( !strcmp(word
, "*endstep") ||
424 !strcmp(word
, "*endpart") ||
425 !strcmp(word
, "*endinstance") ||
426 !strcmp(word
, "*endassembly")) {
433 static void SafeSetLevel(int line
, int level
, Accessor
&styler
)
438 int mask
= ((~SC_FOLDLEVELHEADERFLAG
) | (~SC_FOLDLEVELWHITEFLAG
));
440 if ( (level
& mask
) < 0 )
443 if ( styler
.LevelAt(line
) != level
)
444 styler
.SetLevel(line
, level
) ;
447 static void FoldABAQUSDoc(unsigned int startPos
, int length
, int,
448 WordList
*[], Accessor
&styler
) {
449 int startLine
= styler
.GetLine(startPos
) ;
450 int endLine
= styler
.GetLine(startPos
+length
-1) ;
452 // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
453 // We want to deal with all the cases
454 // To know the correct indentlevel, we need to look back to the
455 // previous command line indentation level
456 // order of formatting keyline datalines commentlines
458 int beginComment
= -1 ;
459 int prvKeyLine
= startLine
;
460 int prvKeyLineTp
= 0 ;
462 // Scan until we find the previous keyword line
463 // this will give us the level reference that we need
464 while ( prvKeyLine
> 0 ) {
466 prvKeyLineTp
= LineType(prvKeyLine
, styler
) ;
467 if ( prvKeyLineTp
& 4 )
471 // Determine the base line level of all lines following
472 // the previous keyword
473 // new keyword lines are placed on this level
474 //if ( prvKeyLineTp & 4 ) {
475 int level
= styler
.LevelAt(prvKeyLine
) & ~SC_FOLDLEVELHEADERFLAG
;
478 // uncomment line below if weird behaviour continues
481 // Now start scanning over the lines.
482 for ( int line
= startLine
; line
<= endLine
; line
++ ) {
483 int lineType
= LineType(line
, styler
) ;
485 // Check for comment line
486 if ( lineType
== 8 ) {
487 if ( beginComment
< 0 ) {
488 beginComment
= line
;
492 // Check for data line
493 if ( (lineType
== 1) || (lineType
== 3) ) {
494 if ( beginData
< 0 ) {
495 if ( beginComment
>= 0 ) {
496 beginData
= beginComment
;
504 // Check for keywordline.
505 // As soon as a keyword line is encountered, we can set the
506 // levels of everything from the previous keyword line to this one
507 if ( lineType
& 4 ) {
508 // this is a keyword, we can now place the previous keyword
509 // all its data lines and the remainder
511 // Write comments and data line
512 if ( beginComment
< 0 ) {
513 beginComment
= line
;
516 if ( beginData
< 0 ) {
517 beginData
= beginComment
;
518 if ( prvKeyLineTp
!= 5 )
519 SafeSetLevel(prvKeyLine
, level
, styler
) ;
521 SafeSetLevel(prvKeyLine
, level
| SC_FOLDLEVELHEADERFLAG
, styler
) ;
523 SafeSetLevel(prvKeyLine
, level
| SC_FOLDLEVELHEADERFLAG
, styler
) ;
526 int datLevel
= level
+ 1 ;
527 if ( !(prvKeyLineTp
& 4) ) {
531 for ( int ll
= beginData
; ll
< beginComment
; ll
++ )
532 SafeSetLevel(ll
, datLevel
, styler
) ;
534 // The keyword we just found is going to be written at another level
535 // if we have a type 5 and type 6
536 if ( prvKeyLineTp
== 5 ) {
540 if ( prvKeyLineTp
== 6 ) {
547 for ( int lll
= beginComment
; lll
< line
; lll
++ )
548 SafeSetLevel(lll
, level
, styler
) ;
554 prvKeyLineTp
= lineType
;
559 if ( beginComment
< 0 ) {
560 beginComment
= endLine
+ 1 ;
562 // We need to find out whether this comment block is followed by
563 // a data line or a keyword line
564 const int docLines
= styler
.GetLine(styler
.Length() - 1);
566 for ( int line
= endLine
+ 1; line
<= docLines
; line
++ ) {
567 int lineType
= LineType(line
, styler
) ;
569 if ( lineType
!= 8 ) {
570 if ( !(lineType
& 4) ) {
571 beginComment
= endLine
+ 1 ;
578 if ( beginData
< 0 ) {
579 beginData
= beginComment
;
580 if ( prvKeyLineTp
!= 5 )
581 SafeSetLevel(prvKeyLine
, level
, styler
) ;
583 SafeSetLevel(prvKeyLine
, level
| SC_FOLDLEVELHEADERFLAG
, styler
) ;
585 SafeSetLevel(prvKeyLine
, level
| SC_FOLDLEVELHEADERFLAG
, styler
) ;
588 int datLevel
= level
+ 1 ;
589 if ( !(prvKeyLineTp
& 4) ) {
593 for ( int ll
= beginData
; ll
< beginComment
; ll
++ )
594 SafeSetLevel(ll
, datLevel
, styler
) ;
596 if ( prvKeyLineTp
== 5 ) {
600 if ( prvKeyLineTp
== 6 ) {
603 for ( int m
= beginComment
; m
<= endLine
; m
++ )
604 SafeSetLevel(m
, level
, styler
) ;
607 static const char * const abaqusWordListDesc
[] = {
617 LexerModule
lmAbaqus(SCLEX_ABAQUS
, ColouriseABAQUSDoc
, "abaqus", FoldABAQUSDoc
, abaqusWordListDesc
);