]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexTADS3.cxx
ee16a0ac07d617a808dd81605b334db5ff486d31
1 // Scintilla source code edit control
5 // Copyright 1998-2006 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
9 * TADS3 is a language designed by Michael J. Roberts for the writing of text
10 * based games. TADS comes from Text Adventure Development System. It has good
11 * support for the processing and outputting of formatted text and much of a
12 * TADS program listing consists of strings.
14 * TADS has two types of strings, those enclosed in single quotes (') and those
15 * enclosed in double quotes ("). These strings have different symantics and
16 * can be given different highlighting if desired.
18 * There can be embedded within both types of strings html tags
19 * ( <tag key=value> ), library directives ( <.directive> ), and message
20 * parameters ( {The doctor's/his} ).
22 * Double quoted strings can also contain interpolated expressions
23 * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ). These expressions
24 * may themselves contain single or double quoted strings, although the double
25 * quoted strings may not contain interpolated expressions.
27 * These embedded constructs influence the output and formatting and are an
28 * important part of a program and require highlighting.
31 * http://www.tads.org/
44 #include "StyleContext.h"
46 #include "Scintilla.h"
50 using namespace Scintilla
;
53 static const int T3_SINGLE_QUOTE
= 1;
54 static const int T3_INT_EXPRESSION
= 2;
55 static const int T3_INT_EXPRESSION_IN_TAG
= 4;
56 static const int T3_HTML_SQUOTE
= 8;
58 static inline bool IsEOL(const int ch
, const int chNext
) {
59 return (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
63 * Test the current character to see if it's the START of an EOL sequence;
64 * if so, skip ahead to the last character of the sequence and return true,
65 * and if not just return false. There are a few places where we want to
66 * check to see if a newline sequence occurs at a particular point, but
67 * where a caller expects a subroutine to stop only upon reaching the END
68 * of a newline sequence (in particular, CR-LF on Windows). That's why
69 * IsEOL() above only returns true on CR if the CR isn't followed by an LF
70 * - it doesn't want to admit that there's a newline until reaching the END
71 * of the sequence. We meet both needs by saying that there's a newline
72 * when we see the CR in a CR-LF, but skipping the CR before returning so
73 * that the caller's caller will see that we've stopped at the LF.
75 static inline bool IsEOLSkip(StyleContext
&sc
)
78 if (sc
.ch
== '\r' && sc
.chNext
== '\n')
80 /* got CR-LF - skip the CR and indicate that we're at a newline */
86 * in other cases, we have at most a 1-character newline, so do the
89 return IsEOL(sc
.ch
, sc
.chNext
);
92 static inline bool IsASpaceOrTab(const int ch
) {
93 return ch
== ' ' || ch
== '\t';
96 static inline bool IsATADS3Operator(const int ch
) {
97 return ch
== '=' || ch
== '{' || ch
== '}' || ch
== '(' || ch
== ')'
98 || ch
== '[' || ch
== ']' || ch
== ',' || ch
== ':' || ch
== ';'
99 || ch
== '+' || ch
== '-' || ch
== '*' || ch
== '/' || ch
== '%'
100 || ch
== '?' || ch
== '!' || ch
== '<' || ch
== '>' || ch
== '|'
101 || ch
== '@' || ch
== '&' || ch
== '~';
104 static inline bool IsAWordChar(const int ch
) {
105 return isalnum(ch
) || ch
== '_';
108 static inline bool IsAWordStart(const int ch
) {
109 return isalpha(ch
) || ch
== '_';
112 static inline bool IsAHexDigit(const int ch
) {
113 int lch
= tolower(ch
);
114 return isdigit(lch
) || lch
== 'a' || lch
== 'b' || lch
== 'c'
115 || lch
== 'd' || lch
== 'e' || lch
== 'f';
118 static inline bool IsAnHTMLChar(int ch
) {
119 return isalnum(ch
) || ch
== '-' || ch
== '_' || ch
== '.';
122 static inline bool IsADirectiveChar(int ch
) {
123 return isalnum(ch
) || isspace(ch
) || ch
== '-' || ch
== '/';
126 static inline bool IsANumberStart(StyleContext
&sc
) {
127 return isdigit(sc
.ch
)
128 || (!isdigit(sc
.chPrev
) && sc
.ch
== '.' && isdigit(sc
.chNext
));
131 inline static void ColouriseTADS3Operator(StyleContext
&sc
) {
132 int initState
= sc
.state
;
134 sc
.SetState(c
== '{' || c
== '}' ? SCE_T3_BRACE
: SCE_T3_OPERATOR
);
135 sc
.ForwardSetState(initState
);
138 static void ColouriseTADSHTMLString(StyleContext
&sc
, int &lineState
) {
139 int endState
= sc
.state
;
141 int chString
= (lineState
& T3_SINGLE_QUOTE
) ? '\'' : '"';
142 if (endState
== SCE_T3_HTML_STRING
) {
143 if (lineState
&T3_SINGLE_QUOTE
) {
144 endState
= SCE_T3_S_STRING
;
146 } else if (lineState
&T3_INT_EXPRESSION
) {
147 endState
= SCE_T3_X_STRING
;
150 endState
= SCE_T3_HTML_DEFAULT
;
153 chQuote
= (lineState
& T3_HTML_SQUOTE
) ? '\'' : '"';
155 sc
.SetState(SCE_T3_HTML_STRING
);
159 lineState
&= ~T3_HTML_SQUOTE
;
161 lineState
|= T3_HTML_SQUOTE
;
164 if (IsEOL(sc
.ch
, sc
.chNext
)) {
167 if (sc
.ch
== chQuote
) {
168 sc
.ForwardSetState(endState
);
171 if (sc
.Match('\\', static_cast<char>(chQuote
))) {
173 sc
.SetState(endState
);
176 if (sc
.ch
== chString
) {
177 sc
.SetState(SCE_T3_DEFAULT
);
181 if (sc
.Match('<', '<')) {
182 lineState
|= T3_INT_EXPRESSION
| T3_INT_EXPRESSION_IN_TAG
;
183 sc
.SetState(SCE_T3_X_DEFAULT
);
188 if (sc
.Match('\\', static_cast<char>(chQuote
))
189 || sc
.Match('\\', static_cast<char>(chString
))
190 || sc
.Match('\\', '\\')) {
198 static void ColouriseTADS3HTMLTagStart(StyleContext
&sc
) {
199 sc
.SetState(SCE_T3_HTML_TAG
);
204 while (IsAnHTMLChar(sc
.ch
)) {
209 static void ColouriseTADS3HTMLTag(StyleContext
&sc
, int &lineState
) {
210 int endState
= sc
.state
;
214 case SCE_T3_S_STRING
:
215 ColouriseTADS3HTMLTagStart(sc
);
216 sc
.SetState(SCE_T3_HTML_DEFAULT
);
220 case SCE_T3_D_STRING
:
221 case SCE_T3_X_STRING
:
222 ColouriseTADS3HTMLTagStart(sc
);
223 sc
.SetState(SCE_T3_HTML_DEFAULT
);
225 case SCE_T3_HTML_DEFAULT
:
226 if (lineState
&T3_SINGLE_QUOTE
) {
227 endState
= SCE_T3_S_STRING
;
230 } else if (lineState
&T3_INT_EXPRESSION
) {
231 endState
= SCE_T3_X_STRING
;
233 endState
= SCE_T3_D_STRING
;
239 if (IsEOL(sc
.ch
, sc
.chNext
)) {
242 if (sc
.Match('/', '>')) {
243 sc
.SetState(SCE_T3_HTML_TAG
);
245 sc
.SetState(endState
);
249 sc
.SetState(SCE_T3_HTML_TAG
);
250 sc
.ForwardSetState(endState
);
253 if (sc
.ch
== chQuote
) {
254 sc
.SetState(endState
);
257 if (sc
.Match('\\', static_cast<char>(chQuote
))) {
259 ColouriseTADSHTMLString(sc
, lineState
);
260 if (sc
.state
== SCE_T3_X_DEFAULT
)
262 } else if (sc
.ch
== chString
) {
263 ColouriseTADSHTMLString(sc
, lineState
);
264 } else if (sc
.ch
== '=') {
265 ColouriseTADS3Operator(sc
);
272 static void ColouriseTADS3Keyword(StyleContext
&sc
,
273 WordList
*keywordlists
[], unsigned int endPos
) {
275 WordList
&keywords
= *keywordlists
[0];
276 WordList
&userwords1
= *keywordlists
[1];
277 WordList
&userwords2
= *keywordlists
[2];
278 WordList
&userwords3
= *keywordlists
[3];
279 int initState
= sc
.state
;
280 sc
.SetState(SCE_T3_IDENTIFIER
);
281 while (sc
.More() && (IsAWordChar(sc
.ch
))) {
284 sc
.GetCurrent(s
, sizeof(s
));
285 if ( strcmp(s
, "is") == 0 || strcmp(s
, "not") == 0) {
286 // have to find if "in" is next
288 while (n
+ sc
.currentPos
< endPos
&& IsASpaceOrTab(sc
.GetRelative(n
)))
290 if (sc
.GetRelative(n
) == 'i' && sc
.GetRelative(n
+1) == 'n') {
292 sc
.ChangeState(SCE_T3_KEYWORD
);
294 } else if (keywords
.InList(s
)) {
295 sc
.ChangeState(SCE_T3_KEYWORD
);
296 } else if (userwords3
.InList(s
)) {
297 sc
.ChangeState(SCE_T3_USER3
);
298 } else if (userwords2
.InList(s
)) {
299 sc
.ChangeState(SCE_T3_USER2
);
300 } else if (userwords1
.InList(s
)) {
301 sc
.ChangeState(SCE_T3_USER1
);
303 sc
.SetState(initState
);
306 static void ColouriseTADS3MsgParam(StyleContext
&sc
, int &lineState
) {
307 int endState
= sc
.state
;
310 case SCE_T3_S_STRING
:
311 sc
.SetState(SCE_T3_MSG_PARAM
);
315 case SCE_T3_D_STRING
:
316 case SCE_T3_X_STRING
:
317 sc
.SetState(SCE_T3_MSG_PARAM
);
320 case SCE_T3_MSG_PARAM
:
321 if (lineState
&T3_SINGLE_QUOTE
) {
322 endState
= SCE_T3_S_STRING
;
324 } else if (lineState
&T3_INT_EXPRESSION
) {
325 endState
= SCE_T3_X_STRING
;
327 endState
= SCE_T3_D_STRING
;
331 while (sc
.More() && sc
.ch
!= '}' && sc
.ch
!= chQuote
) {
332 if (IsEOL(sc
.ch
, sc
.chNext
)) {
340 if (sc
.ch
== chQuote
) {
341 sc
.SetState(endState
);
343 sc
.ForwardSetState(endState
);
347 static void ColouriseTADS3LibDirective(StyleContext
&sc
, int &lineState
) {
348 int initState
= sc
.state
;
351 case SCE_T3_S_STRING
:
352 sc
.SetState(SCE_T3_LIB_DIRECTIVE
);
356 case SCE_T3_D_STRING
:
357 sc
.SetState(SCE_T3_LIB_DIRECTIVE
);
360 case SCE_T3_LIB_DIRECTIVE
:
361 if (lineState
&T3_SINGLE_QUOTE
) {
362 initState
= SCE_T3_S_STRING
;
365 initState
= SCE_T3_D_STRING
;
369 while (sc
.More() && IsADirectiveChar(sc
.ch
)) {
370 if (IsEOL(sc
.ch
, sc
.chNext
)) {
375 if (sc
.ch
== '>' || !sc
.More()) {
376 sc
.ForwardSetState(initState
);
377 } else if (sc
.ch
== chQuote
) {
378 sc
.SetState(initState
);
380 sc
.ChangeState(initState
);
385 static void ColouriseTADS3String(StyleContext
&sc
, int &lineState
) {
387 int endState
= sc
.state
;
390 case SCE_T3_X_DEFAULT
:
391 if (chQuote
== '"') {
392 if (sc
.state
== SCE_T3_DEFAULT
) {
393 sc
.SetState(SCE_T3_D_STRING
);
395 sc
.SetState(SCE_T3_X_STRING
);
397 lineState
&= ~T3_SINGLE_QUOTE
;
399 sc
.SetState(SCE_T3_S_STRING
);
400 lineState
|= T3_SINGLE_QUOTE
;
404 case SCE_T3_S_STRING
:
406 endState
= lineState
&T3_INT_EXPRESSION
?
407 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
;
409 case SCE_T3_D_STRING
:
411 endState
= SCE_T3_DEFAULT
;
413 case SCE_T3_X_STRING
:
415 endState
= SCE_T3_X_DEFAULT
;
419 if (IsEOL(sc
.ch
, sc
.chNext
)) {
422 if (sc
.ch
== chQuote
) {
423 sc
.ForwardSetState(endState
);
426 if (sc
.state
== SCE_T3_D_STRING
&& sc
.Match('<', '<')) {
427 lineState
|= T3_INT_EXPRESSION
;
428 sc
.SetState(SCE_T3_X_DEFAULT
);
432 if (sc
.Match('\\', static_cast<char>(chQuote
))
433 || sc
.Match('\\', '\\')) {
435 } else if (sc
.ch
== '{') {
436 ColouriseTADS3MsgParam(sc
, lineState
);
437 } else if (sc
.Match('<', '.')) {
438 ColouriseTADS3LibDirective(sc
, lineState
);
439 } else if (sc
.ch
== '<') {
440 ColouriseTADS3HTMLTag(sc
, lineState
);
441 if (sc
.state
== SCE_T3_X_DEFAULT
)
449 static void ColouriseTADS3Comment(StyleContext
&sc
, int endState
) {
450 sc
.SetState(SCE_T3_BLOCK_COMMENT
);
452 if (IsEOL(sc
.ch
, sc
.chNext
)) {
455 if (sc
.Match('*', '/')) {
457 sc
.SetState(endState
);
464 static void ColouriseToEndOfLine(StyleContext
&sc
, int initState
, int endState
) {
465 sc
.SetState(initState
);
473 if (IsEOL(sc
.ch
, sc
.chNext
)) {
474 sc
.SetState(endState
);
481 static void ColouriseTADS3Number(StyleContext
&sc
) {
482 int endState
= sc
.state
;
483 bool inHexNumber
= false;
485 bool seenDot
= sc
.ch
== '.';
486 sc
.SetState(SCE_T3_NUMBER
);
490 if (sc
.chPrev
== '0' && tolower(sc
.ch
) == 'x') {
496 if (!IsAHexDigit(sc
.ch
)) {
499 } else if (!isdigit(sc
.ch
)) {
500 if (!seenE
&& tolower(sc
.ch
) == 'e') {
503 if (sc
.chNext
== '+' || sc
.chNext
== '-') {
506 } else if (!seenDot
&& sc
.ch
== '.') {
514 sc
.SetState(endState
);
517 static void ColouriseTADS3Doc(unsigned int startPos
, int length
, int initStyle
,
518 WordList
*keywordlists
[], Accessor
&styler
) {
519 int visibleChars
= 0;
520 int bracketLevel
= 0;
522 unsigned int endPos
= startPos
+ length
;
523 int lineCurrent
= styler
.GetLine(startPos
);
524 if (lineCurrent
> 0) {
525 lineState
= styler
.GetLineState(lineCurrent
-1);
527 StyleContext
sc(startPos
, length
, initStyle
, styler
);
531 if (IsEOL(sc
.ch
, sc
.chNext
)) {
532 styler
.SetLineState(lineCurrent
, lineState
);
542 case SCE_T3_PREPROCESSOR
:
543 case SCE_T3_LINE_COMMENT
:
544 ColouriseToEndOfLine(sc
, sc
.state
, lineState
&T3_INT_EXPRESSION
?
545 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
);
547 case SCE_T3_S_STRING
:
548 case SCE_T3_D_STRING
:
549 case SCE_T3_X_STRING
:
550 ColouriseTADS3String(sc
, lineState
);
553 case SCE_T3_MSG_PARAM
:
554 ColouriseTADS3MsgParam(sc
, lineState
);
556 case SCE_T3_LIB_DIRECTIVE
:
557 ColouriseTADS3LibDirective(sc
, lineState
);
559 case SCE_T3_HTML_DEFAULT
:
560 ColouriseTADS3HTMLTag(sc
, lineState
);
562 case SCE_T3_HTML_STRING
:
563 ColouriseTADSHTMLString(sc
, lineState
);
565 case SCE_T3_BLOCK_COMMENT
:
566 ColouriseTADS3Comment(sc
, lineState
&T3_INT_EXPRESSION
?
567 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
);
570 case SCE_T3_X_DEFAULT
:
571 if (IsASpaceOrTab(sc
.ch
)) {
573 } else if (sc
.ch
== '#' && visibleChars
== 0) {
574 ColouriseToEndOfLine(sc
, SCE_T3_PREPROCESSOR
, sc
.state
);
575 } else if (sc
.Match('/', '*')) {
576 ColouriseTADS3Comment(sc
, sc
.state
);
578 } else if (sc
.Match('/', '/')) {
579 ColouriseToEndOfLine(sc
, SCE_T3_LINE_COMMENT
, sc
.state
);
580 } else if (sc
.ch
== '"') {
582 ColouriseTADS3String(sc
, lineState
);
584 } else if (sc
.ch
== '\'') {
585 ColouriseTADS3String(sc
, lineState
);
587 } else if (sc
.state
== SCE_T3_X_DEFAULT
&& bracketLevel
== 0
588 && sc
.Match('>', '>')) {
590 sc
.SetState(SCE_T3_D_STRING
);
591 if (lineState
& T3_INT_EXPRESSION_IN_TAG
)
592 sc
.SetState(SCE_T3_HTML_STRING
);
593 lineState
&= ~(T3_SINGLE_QUOTE
|T3_INT_EXPRESSION
594 |T3_INT_EXPRESSION_IN_TAG
);
595 } else if (IsATADS3Operator(sc
.ch
)) {
596 if (sc
.state
== SCE_T3_X_DEFAULT
) {
599 } else if (sc
.ch
== ')' && bracketLevel
> 0) {
603 ColouriseTADS3Operator(sc
);
605 } else if (IsANumberStart(sc
)) {
606 ColouriseTADS3Number(sc
);
608 } else if (IsAWordStart(sc
.ch
)) {
609 ColouriseTADS3Keyword(sc
, keywordlists
, endPos
);
611 } else if (sc
.Match("...")) {
612 sc
.SetState(SCE_T3_IDENTIFIER
);
614 sc
.SetState(SCE_T3_DEFAULT
);
621 sc
.SetState(SCE_T3_DEFAULT
);
629 TADS3 has two styles of top level block (TLB). Eg
632 silverKey : Key 'small silver key' 'small silver key'
633 "A small key glints in the sunlight. "
641 "A small key glints in the sunlight. "
644 Some constructs mandate one or the other, but usually the author has may choose
647 T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
648 seen and is also used to match the closing ';' of the default style.
650 T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
651 what characters may be seen without incrementing the block level. The general
652 pattern is identifier <punc> identifier, acceptable punctuation characters
653 are ':', ',', '(' and ')'. No attempt is made to ensure that punctuation
654 characters are syntactically correct, eg parentheses match. A ')' always
655 signifies the start of a block. We just need to check if it is followed by a
656 '{', in which case we let the brace handling code handle the folding level.
658 expectingIdentifier == false && expectingIdentifier == false
659 Before the start of a TLB.
661 expectingIdentifier == true && expectingIdentifier == true
662 Currently in an identifier. Will accept identifier or punctuation.
664 expectingIdentifier == true && expectingIdentifier == false
665 Just seen a punctuation character & now waiting for an identifier to start.
667 expectingIdentifier == false && expectingIdentifier == truee
668 We were in an identifier and have seen space. Now waiting to see a punctuation
671 Space, comments & preprocessor directives are always acceptable and are
675 static const int T3_SEENSTART
= 1 << 12;
676 static const int T3_EXPECTINGIDENTIFIER
= 1 << 13;
677 static const int T3_EXPECTINGPUNCTUATION
= 1 << 14;
679 static inline bool IsStringTransition(int s1
, int s2
) {
681 && (s1
== SCE_T3_S_STRING
|| s1
== SCE_T3_X_STRING
682 || (s1
== SCE_T3_D_STRING
&& s2
!= SCE_T3_X_DEFAULT
))
683 && s2
!= SCE_T3_LIB_DIRECTIVE
684 && s2
!= SCE_T3_MSG_PARAM
685 && s2
!= SCE_T3_HTML_TAG
686 && s2
!= SCE_T3_HTML_STRING
;
689 static inline bool IsATADS3Punctuation(const int ch
) {
690 return ch
== ':' || ch
== ',' || ch
== '(' || ch
== ')';
693 static inline bool IsAnIdentifier(const int style
) {
694 return style
== SCE_T3_IDENTIFIER
695 || style
== SCE_T3_USER1
696 || style
== SCE_T3_USER2
697 || style
== SCE_T3_USER3
;
700 static inline bool IsAnOperator(const int style
) {
701 return style
== SCE_T3_OPERATOR
|| SCE_T3_BRACE
;
704 static inline bool IsSpaceEquivalent(const int ch
, const int style
) {
706 || style
== SCE_T3_BLOCK_COMMENT
707 || style
== SCE_T3_LINE_COMMENT
708 || style
== SCE_T3_PREPROCESSOR
;
711 static char peekAhead(unsigned int startPos
, unsigned int endPos
,
713 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
714 int style
= styler
.StyleAt(i
);
716 if (!IsSpaceEquivalent(ch
, style
)) {
717 if (IsAnIdentifier(style
)) {
720 if (IsATADS3Punctuation(ch
)) {
732 static void FoldTADS3Doc(unsigned int startPos
, int length
, int initStyle
,
733 WordList
*[], Accessor
&styler
) {
734 unsigned int endPos
= startPos
+ length
;
735 int lineCurrent
= styler
.GetLine(startPos
);
736 int levelCurrent
= SC_FOLDLEVELBASE
;
738 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
739 int seenStart
= levelCurrent
& T3_SEENSTART
;
740 int expectingIdentifier
= levelCurrent
& T3_EXPECTINGIDENTIFIER
;
741 int expectingPunctuation
= levelCurrent
& T3_EXPECTINGPUNCTUATION
;
742 levelCurrent
&= SC_FOLDLEVELNUMBERMASK
;
743 int levelMinCurrent
= levelCurrent
;
744 int levelNext
= levelCurrent
;
745 char chNext
= styler
[startPos
];
746 int styleNext
= styler
.StyleAt(startPos
);
747 int style
= initStyle
;
749 int stylePrev
= style
;
751 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
757 chNext
= styler
.SafeGetCharAt(i
+ 1);
760 styleNext
= styler
.StyleAt(i
+ 1);
762 bool atEOL
= IsEOL(ch
, chNext
);
764 if (levelNext
== SC_FOLDLEVELBASE
) {
765 if (IsSpaceEquivalent(ch
, style
)) {
766 if (expectingPunctuation
) {
767 expectingIdentifier
= 0;
769 if (style
== SCE_T3_BLOCK_COMMENT
) {
772 } else if (ch
== '{') {
775 } else if (ch
== '\'' || ch
== '"' || ch
== '[') {
780 } else if (ch
== ';') {
782 expectingIdentifier
= 0;
783 expectingPunctuation
= 0;
784 } else if (expectingIdentifier
&& expectingPunctuation
) {
785 if (IsATADS3Punctuation(ch
)) {
786 if (ch
== ')' && peekAhead(i
+1, endPos
, styler
) != '{') {
789 expectingPunctuation
= 0;
791 } else if (!IsAnIdentifier(style
)) {
794 } else if (expectingIdentifier
&& !expectingPunctuation
) {
795 if (!IsAnIdentifier(style
)) {
798 expectingPunctuation
= T3_EXPECTINGPUNCTUATION
;
800 } else if (!expectingIdentifier
&& expectingPunctuation
) {
801 if (!IsATADS3Punctuation(ch
)) {
804 if (ch
== ')' && peekAhead(i
+1, endPos
, styler
) != '{') {
807 expectingIdentifier
= T3_EXPECTINGIDENTIFIER
;
808 expectingPunctuation
= 0;
811 } else if (!expectingIdentifier
&& !expectingPunctuation
) {
812 if (IsAnIdentifier(style
)) {
813 seenStart
= T3_SEENSTART
;
814 expectingIdentifier
= T3_EXPECTINGIDENTIFIER
;
815 expectingPunctuation
= T3_EXPECTINGPUNCTUATION
;
819 if (levelNext
!= SC_FOLDLEVELBASE
&& style
!= SCE_T3_BLOCK_COMMENT
) {
820 expectingIdentifier
= 0;
821 expectingPunctuation
= 0;
824 } else if (levelNext
== SC_FOLDLEVELBASE
+1 && seenStart
825 && ch
== ';' && IsAnOperator(style
)) {
828 } else if (style
== SCE_T3_BLOCK_COMMENT
) {
829 if (stylePrev
!= SCE_T3_BLOCK_COMMENT
) {
831 } else if (styleNext
!= SCE_T3_BLOCK_COMMENT
&& !atEOL
) {
832 // Comments don't end at end of line and the next character may be unstyled.
835 } else if (ch
== '\'' || ch
== '"') {
836 if (IsStringTransition(style
, stylePrev
)) {
837 if (levelMinCurrent
> levelNext
) {
838 levelMinCurrent
= levelNext
;
841 } else if (IsStringTransition(style
, styleNext
)) {
844 } else if (IsAnOperator(style
)) {
845 if (ch
== '{' || ch
== '[') {
846 // Measure the minimum before a '{' to allow
847 // folding on "} else {"
848 if (levelMinCurrent
> levelNext
) {
849 levelMinCurrent
= levelNext
;
852 } else if (ch
== '}' || ch
== ']') {
858 if (seenStart
&& levelNext
== SC_FOLDLEVELBASE
) {
859 switch (peekAhead(i
+1, endPos
, styler
)) {
867 if (expectingPunctuation
) {
872 if (expectingIdentifier
) {
877 if (levelNext
!= SC_FOLDLEVELBASE
) {
878 expectingIdentifier
= 0;
879 expectingPunctuation
= 0;
882 int lev
= levelMinCurrent
| (levelNext
| expectingIdentifier
883 | expectingPunctuation
| seenStart
) << 16;
884 if (levelMinCurrent
< levelNext
)
885 lev
|= SC_FOLDLEVELHEADERFLAG
;
886 if (lev
!= styler
.LevelAt(lineCurrent
)) {
887 styler
.SetLevel(lineCurrent
, lev
);
890 levelCurrent
= levelNext
;
891 levelMinCurrent
= levelCurrent
;
896 static const char * const tads3WordList
[] = {
904 LexerModule
lmTADS3(SCLEX_TADS3
, ColouriseTADS3Doc
, "tads3", FoldTADS3Doc
, tads3WordList
);