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/
42 #include "Scintilla.h"
46 #include "LexAccessor.h"
48 #include "StyleContext.h"
49 #include "CharacterSet.h"
50 #include "LexerModule.h"
52 using namespace Scintilla
;
54 static const int T3_SINGLE_QUOTE
= 1;
55 static const int T3_INT_EXPRESSION
= 2;
56 static const int T3_INT_EXPRESSION_IN_TAG
= 4;
57 static const int T3_HTML_SQUOTE
= 8;
59 static inline bool IsEOL(const int ch
, const int chNext
) {
60 return (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
64 * Test the current character to see if it's the START of an EOL sequence;
65 * if so, skip ahead to the last character of the sequence and return true,
66 * and if not just return false. There are a few places where we want to
67 * check to see if a newline sequence occurs at a particular point, but
68 * where a caller expects a subroutine to stop only upon reaching the END
69 * of a newline sequence (in particular, CR-LF on Windows). That's why
70 * IsEOL() above only returns true on CR if the CR isn't followed by an LF
71 * - it doesn't want to admit that there's a newline until reaching the END
72 * of the sequence. We meet both needs by saying that there's a newline
73 * when we see the CR in a CR-LF, but skipping the CR before returning so
74 * that the caller's caller will see that we've stopped at the LF.
76 static inline bool IsEOLSkip(StyleContext
&sc
)
79 if (sc
.ch
== '\r' && sc
.chNext
== '\n')
81 /* got CR-LF - skip the CR and indicate that we're at a newline */
87 * in other cases, we have at most a 1-character newline, so do the
90 return IsEOL(sc
.ch
, sc
.chNext
);
93 static inline bool IsATADS3Operator(const int ch
) {
94 return ch
== '=' || ch
== '{' || ch
== '}' || ch
== '(' || ch
== ')'
95 || ch
== '[' || ch
== ']' || ch
== ',' || ch
== ':' || ch
== ';'
96 || ch
== '+' || ch
== '-' || ch
== '*' || ch
== '/' || ch
== '%'
97 || ch
== '?' || ch
== '!' || ch
== '<' || ch
== '>' || ch
== '|'
98 || ch
== '@' || ch
== '&' || ch
== '~';
101 static inline bool IsAWordChar(const int ch
) {
102 return isalnum(ch
) || ch
== '_';
105 static inline bool IsAWordStart(const int ch
) {
106 return isalpha(ch
) || ch
== '_';
109 static inline bool IsAHexDigit(const int ch
) {
110 int lch
= tolower(ch
);
111 return isdigit(lch
) || lch
== 'a' || lch
== 'b' || lch
== 'c'
112 || lch
== 'd' || lch
== 'e' || lch
== 'f';
115 static inline bool IsAnHTMLChar(int ch
) {
116 return isalnum(ch
) || ch
== '-' || ch
== '_' || ch
== '.';
119 static inline bool IsADirectiveChar(int ch
) {
120 return isalnum(ch
) || isspace(ch
) || ch
== '-' || ch
== '/';
123 static inline bool IsANumberStart(StyleContext
&sc
) {
124 return isdigit(sc
.ch
)
125 || (!isdigit(sc
.chPrev
) && sc
.ch
== '.' && isdigit(sc
.chNext
));
128 inline static void ColouriseTADS3Operator(StyleContext
&sc
) {
129 int initState
= sc
.state
;
131 sc
.SetState(c
== '{' || c
== '}' ? SCE_T3_BRACE
: SCE_T3_OPERATOR
);
132 sc
.ForwardSetState(initState
);
135 static void ColouriseTADSHTMLString(StyleContext
&sc
, int &lineState
) {
136 int endState
= sc
.state
;
138 int chString
= (lineState
& T3_SINGLE_QUOTE
) ? '\'' : '"';
139 if (endState
== SCE_T3_HTML_STRING
) {
140 if (lineState
&T3_SINGLE_QUOTE
) {
141 endState
= SCE_T3_S_STRING
;
143 } else if (lineState
&T3_INT_EXPRESSION
) {
144 endState
= SCE_T3_X_STRING
;
147 endState
= SCE_T3_HTML_DEFAULT
;
150 chQuote
= (lineState
& T3_HTML_SQUOTE
) ? '\'' : '"';
152 sc
.SetState(SCE_T3_HTML_STRING
);
156 lineState
&= ~T3_HTML_SQUOTE
;
158 lineState
|= T3_HTML_SQUOTE
;
161 if (IsEOL(sc
.ch
, sc
.chNext
)) {
164 if (sc
.ch
== chQuote
) {
165 sc
.ForwardSetState(endState
);
168 if (sc
.Match('\\', static_cast<char>(chQuote
))) {
170 sc
.SetState(endState
);
173 if (sc
.ch
== chString
) {
174 sc
.SetState(SCE_T3_DEFAULT
);
178 if (sc
.Match('<', '<')) {
179 lineState
|= T3_INT_EXPRESSION
| T3_INT_EXPRESSION_IN_TAG
;
180 sc
.SetState(SCE_T3_X_DEFAULT
);
185 if (sc
.Match('\\', static_cast<char>(chQuote
))
186 || sc
.Match('\\', static_cast<char>(chString
))
187 || sc
.Match('\\', '\\')) {
195 static void ColouriseTADS3HTMLTagStart(StyleContext
&sc
) {
196 sc
.SetState(SCE_T3_HTML_TAG
);
201 while (IsAnHTMLChar(sc
.ch
)) {
206 static void ColouriseTADS3HTMLTag(StyleContext
&sc
, int &lineState
) {
207 int endState
= sc
.state
;
211 case SCE_T3_S_STRING
:
212 ColouriseTADS3HTMLTagStart(sc
);
213 sc
.SetState(SCE_T3_HTML_DEFAULT
);
217 case SCE_T3_D_STRING
:
218 case SCE_T3_X_STRING
:
219 ColouriseTADS3HTMLTagStart(sc
);
220 sc
.SetState(SCE_T3_HTML_DEFAULT
);
222 case SCE_T3_HTML_DEFAULT
:
223 if (lineState
&T3_SINGLE_QUOTE
) {
224 endState
= SCE_T3_S_STRING
;
227 } else if (lineState
&T3_INT_EXPRESSION
) {
228 endState
= SCE_T3_X_STRING
;
230 endState
= SCE_T3_D_STRING
;
236 if (IsEOL(sc
.ch
, sc
.chNext
)) {
239 if (sc
.Match('/', '>')) {
240 sc
.SetState(SCE_T3_HTML_TAG
);
242 sc
.SetState(endState
);
246 sc
.SetState(SCE_T3_HTML_TAG
);
247 sc
.ForwardSetState(endState
);
250 if (sc
.ch
== chQuote
) {
251 sc
.SetState(endState
);
254 if (sc
.Match('\\', static_cast<char>(chQuote
))) {
256 ColouriseTADSHTMLString(sc
, lineState
);
257 if (sc
.state
== SCE_T3_X_DEFAULT
)
259 } else if (sc
.ch
== chString
) {
260 ColouriseTADSHTMLString(sc
, lineState
);
261 } else if (sc
.ch
== '=') {
262 ColouriseTADS3Operator(sc
);
269 static void ColouriseTADS3Keyword(StyleContext
&sc
,
270 WordList
*keywordlists
[], Sci_PositionU endPos
) {
272 WordList
&keywords
= *keywordlists
[0];
273 WordList
&userwords1
= *keywordlists
[1];
274 WordList
&userwords2
= *keywordlists
[2];
275 WordList
&userwords3
= *keywordlists
[3];
276 int initState
= sc
.state
;
277 sc
.SetState(SCE_T3_IDENTIFIER
);
278 while (sc
.More() && (IsAWordChar(sc
.ch
))) {
281 sc
.GetCurrent(s
, sizeof(s
));
282 if ( strcmp(s
, "is") == 0 || strcmp(s
, "not") == 0) {
283 // have to find if "in" is next
285 while (n
+ sc
.currentPos
< endPos
&& IsASpaceOrTab(sc
.GetRelative(n
)))
287 if (sc
.GetRelative(n
) == 'i' && sc
.GetRelative(n
+1) == 'n') {
289 sc
.ChangeState(SCE_T3_KEYWORD
);
291 } else if (keywords
.InList(s
)) {
292 sc
.ChangeState(SCE_T3_KEYWORD
);
293 } else if (userwords3
.InList(s
)) {
294 sc
.ChangeState(SCE_T3_USER3
);
295 } else if (userwords2
.InList(s
)) {
296 sc
.ChangeState(SCE_T3_USER2
);
297 } else if (userwords1
.InList(s
)) {
298 sc
.ChangeState(SCE_T3_USER1
);
300 sc
.SetState(initState
);
303 static void ColouriseTADS3MsgParam(StyleContext
&sc
, int &lineState
) {
304 int endState
= sc
.state
;
307 case SCE_T3_S_STRING
:
308 sc
.SetState(SCE_T3_MSG_PARAM
);
312 case SCE_T3_D_STRING
:
313 case SCE_T3_X_STRING
:
314 sc
.SetState(SCE_T3_MSG_PARAM
);
317 case SCE_T3_MSG_PARAM
:
318 if (lineState
&T3_SINGLE_QUOTE
) {
319 endState
= SCE_T3_S_STRING
;
321 } else if (lineState
&T3_INT_EXPRESSION
) {
322 endState
= SCE_T3_X_STRING
;
324 endState
= SCE_T3_D_STRING
;
328 while (sc
.More() && sc
.ch
!= '}' && sc
.ch
!= chQuote
) {
329 if (IsEOL(sc
.ch
, sc
.chNext
)) {
337 if (sc
.ch
== chQuote
) {
338 sc
.SetState(endState
);
340 sc
.ForwardSetState(endState
);
344 static void ColouriseTADS3LibDirective(StyleContext
&sc
, int &lineState
) {
345 int initState
= sc
.state
;
348 case SCE_T3_S_STRING
:
349 sc
.SetState(SCE_T3_LIB_DIRECTIVE
);
353 case SCE_T3_D_STRING
:
354 sc
.SetState(SCE_T3_LIB_DIRECTIVE
);
357 case SCE_T3_LIB_DIRECTIVE
:
358 if (lineState
&T3_SINGLE_QUOTE
) {
359 initState
= SCE_T3_S_STRING
;
362 initState
= SCE_T3_D_STRING
;
366 while (sc
.More() && IsADirectiveChar(sc
.ch
)) {
367 if (IsEOL(sc
.ch
, sc
.chNext
)) {
372 if (sc
.ch
== '>' || !sc
.More()) {
373 sc
.ForwardSetState(initState
);
374 } else if (sc
.ch
== chQuote
) {
375 sc
.SetState(initState
);
377 sc
.ChangeState(initState
);
382 static void ColouriseTADS3String(StyleContext
&sc
, int &lineState
) {
384 int endState
= sc
.state
;
387 case SCE_T3_X_DEFAULT
:
388 if (chQuote
== '"') {
389 if (sc
.state
== SCE_T3_DEFAULT
) {
390 sc
.SetState(SCE_T3_D_STRING
);
392 sc
.SetState(SCE_T3_X_STRING
);
394 lineState
&= ~T3_SINGLE_QUOTE
;
396 sc
.SetState(SCE_T3_S_STRING
);
397 lineState
|= T3_SINGLE_QUOTE
;
401 case SCE_T3_S_STRING
:
403 endState
= lineState
&T3_INT_EXPRESSION
?
404 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
;
406 case SCE_T3_D_STRING
:
408 endState
= SCE_T3_DEFAULT
;
410 case SCE_T3_X_STRING
:
412 endState
= SCE_T3_X_DEFAULT
;
416 if (IsEOL(sc
.ch
, sc
.chNext
)) {
419 if (sc
.ch
== chQuote
) {
420 sc
.ForwardSetState(endState
);
423 if (sc
.state
== SCE_T3_D_STRING
&& sc
.Match('<', '<')) {
424 lineState
|= T3_INT_EXPRESSION
;
425 sc
.SetState(SCE_T3_X_DEFAULT
);
429 if (sc
.Match('\\', static_cast<char>(chQuote
))
430 || sc
.Match('\\', '\\')) {
432 } else if (sc
.ch
== '{') {
433 ColouriseTADS3MsgParam(sc
, lineState
);
434 } else if (sc
.Match('<', '.')) {
435 ColouriseTADS3LibDirective(sc
, lineState
);
436 } else if (sc
.ch
== '<') {
437 ColouriseTADS3HTMLTag(sc
, lineState
);
438 if (sc
.state
== SCE_T3_X_DEFAULT
)
446 static void ColouriseTADS3Comment(StyleContext
&sc
, int endState
) {
447 sc
.SetState(SCE_T3_BLOCK_COMMENT
);
449 if (IsEOL(sc
.ch
, sc
.chNext
)) {
452 if (sc
.Match('*', '/')) {
454 sc
.SetState(endState
);
461 static void ColouriseToEndOfLine(StyleContext
&sc
, int initState
, int endState
) {
462 sc
.SetState(initState
);
470 if (IsEOL(sc
.ch
, sc
.chNext
)) {
471 sc
.SetState(endState
);
478 static void ColouriseTADS3Number(StyleContext
&sc
) {
479 int endState
= sc
.state
;
480 bool inHexNumber
= false;
482 bool seenDot
= sc
.ch
== '.';
483 sc
.SetState(SCE_T3_NUMBER
);
487 if (sc
.chPrev
== '0' && tolower(sc
.ch
) == 'x') {
493 if (!IsAHexDigit(sc
.ch
)) {
496 } else if (!isdigit(sc
.ch
)) {
497 if (!seenE
&& tolower(sc
.ch
) == 'e') {
500 if (sc
.chNext
== '+' || sc
.chNext
== '-') {
503 } else if (!seenDot
&& sc
.ch
== '.') {
511 sc
.SetState(endState
);
514 static void ColouriseTADS3Doc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
515 WordList
*keywordlists
[], Accessor
&styler
) {
516 int visibleChars
= 0;
517 int bracketLevel
= 0;
519 Sci_PositionU endPos
= startPos
+ length
;
520 Sci_Position lineCurrent
= styler
.GetLine(startPos
);
521 if (lineCurrent
> 0) {
522 lineState
= styler
.GetLineState(lineCurrent
-1);
524 StyleContext
sc(startPos
, length
, initStyle
, styler
);
528 if (IsEOL(sc
.ch
, sc
.chNext
)) {
529 styler
.SetLineState(lineCurrent
, lineState
);
539 case SCE_T3_PREPROCESSOR
:
540 case SCE_T3_LINE_COMMENT
:
541 ColouriseToEndOfLine(sc
, sc
.state
, lineState
&T3_INT_EXPRESSION
?
542 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
);
544 case SCE_T3_S_STRING
:
545 case SCE_T3_D_STRING
:
546 case SCE_T3_X_STRING
:
547 ColouriseTADS3String(sc
, lineState
);
550 case SCE_T3_MSG_PARAM
:
551 ColouriseTADS3MsgParam(sc
, lineState
);
553 case SCE_T3_LIB_DIRECTIVE
:
554 ColouriseTADS3LibDirective(sc
, lineState
);
556 case SCE_T3_HTML_DEFAULT
:
557 ColouriseTADS3HTMLTag(sc
, lineState
);
559 case SCE_T3_HTML_STRING
:
560 ColouriseTADSHTMLString(sc
, lineState
);
562 case SCE_T3_BLOCK_COMMENT
:
563 ColouriseTADS3Comment(sc
, lineState
&T3_INT_EXPRESSION
?
564 SCE_T3_X_DEFAULT
: SCE_T3_DEFAULT
);
567 case SCE_T3_X_DEFAULT
:
568 if (IsASpaceOrTab(sc
.ch
)) {
570 } else if (sc
.ch
== '#' && visibleChars
== 0) {
571 ColouriseToEndOfLine(sc
, SCE_T3_PREPROCESSOR
, sc
.state
);
572 } else if (sc
.Match('/', '*')) {
573 ColouriseTADS3Comment(sc
, sc
.state
);
575 } else if (sc
.Match('/', '/')) {
576 ColouriseToEndOfLine(sc
, SCE_T3_LINE_COMMENT
, sc
.state
);
577 } else if (sc
.ch
== '"') {
579 ColouriseTADS3String(sc
, lineState
);
581 } else if (sc
.ch
== '\'') {
582 ColouriseTADS3String(sc
, lineState
);
584 } else if (sc
.state
== SCE_T3_X_DEFAULT
&& bracketLevel
== 0
585 && sc
.Match('>', '>')) {
587 sc
.SetState(SCE_T3_D_STRING
);
588 if (lineState
& T3_INT_EXPRESSION_IN_TAG
)
589 sc
.SetState(SCE_T3_HTML_STRING
);
590 lineState
&= ~(T3_SINGLE_QUOTE
|T3_INT_EXPRESSION
591 |T3_INT_EXPRESSION_IN_TAG
);
592 } else if (IsATADS3Operator(sc
.ch
)) {
593 if (sc
.state
== SCE_T3_X_DEFAULT
) {
596 } else if (sc
.ch
== ')' && bracketLevel
> 0) {
600 ColouriseTADS3Operator(sc
);
602 } else if (IsANumberStart(sc
)) {
603 ColouriseTADS3Number(sc
);
605 } else if (IsAWordStart(sc
.ch
)) {
606 ColouriseTADS3Keyword(sc
, keywordlists
, endPos
);
608 } else if (sc
.Match("...")) {
609 sc
.SetState(SCE_T3_IDENTIFIER
);
611 sc
.SetState(SCE_T3_DEFAULT
);
618 sc
.SetState(SCE_T3_DEFAULT
);
626 TADS3 has two styles of top level block (TLB). Eg
629 silverKey : Key 'small silver key' 'small silver key'
630 "A small key glints in the sunlight. "
638 "A small key glints in the sunlight. "
641 Some constructs mandate one or the other, but usually the author has may choose
644 T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
645 seen and is also used to match the closing ';' of the default style.
647 T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
648 what characters may be seen without incrementing the block level. The general
649 pattern is identifier <punc> identifier, acceptable punctuation characters
650 are ':', ',', '(' and ')'. No attempt is made to ensure that punctuation
651 characters are syntactically correct, eg parentheses match. A ')' always
652 signifies the start of a block. We just need to check if it is followed by a
653 '{', in which case we let the brace handling code handle the folding level.
655 expectingIdentifier == false && expectingIdentifier == false
656 Before the start of a TLB.
658 expectingIdentifier == true && expectingIdentifier == true
659 Currently in an identifier. Will accept identifier or punctuation.
661 expectingIdentifier == true && expectingIdentifier == false
662 Just seen a punctuation character & now waiting for an identifier to start.
664 expectingIdentifier == false && expectingIdentifier == truee
665 We were in an identifier and have seen space. Now waiting to see a punctuation
668 Space, comments & preprocessor directives are always acceptable and are
672 static const int T3_SEENSTART
= 1 << 12;
673 static const int T3_EXPECTINGIDENTIFIER
= 1 << 13;
674 static const int T3_EXPECTINGPUNCTUATION
= 1 << 14;
676 static inline bool IsStringTransition(int s1
, int s2
) {
678 && (s1
== SCE_T3_S_STRING
|| s1
== SCE_T3_X_STRING
679 || (s1
== SCE_T3_D_STRING
&& s2
!= SCE_T3_X_DEFAULT
))
680 && s2
!= SCE_T3_LIB_DIRECTIVE
681 && s2
!= SCE_T3_MSG_PARAM
682 && s2
!= SCE_T3_HTML_TAG
683 && s2
!= SCE_T3_HTML_STRING
;
686 static inline bool IsATADS3Punctuation(const int ch
) {
687 return ch
== ':' || ch
== ',' || ch
== '(' || ch
== ')';
690 static inline bool IsAnIdentifier(const int style
) {
691 return style
== SCE_T3_IDENTIFIER
692 || style
== SCE_T3_USER1
693 || style
== SCE_T3_USER2
694 || style
== SCE_T3_USER3
;
697 static inline bool IsAnOperator(const int style
) {
698 return style
== SCE_T3_OPERATOR
|| style
== SCE_T3_BRACE
;
701 static inline bool IsSpaceEquivalent(const int ch
, const int style
) {
703 || style
== SCE_T3_BLOCK_COMMENT
704 || style
== SCE_T3_LINE_COMMENT
705 || style
== SCE_T3_PREPROCESSOR
;
708 static char peekAhead(Sci_PositionU startPos
, Sci_PositionU endPos
,
710 for (Sci_PositionU i
= startPos
; i
< endPos
; i
++) {
711 int style
= styler
.StyleAt(i
);
713 if (!IsSpaceEquivalent(ch
, style
)) {
714 if (IsAnIdentifier(style
)) {
717 if (IsATADS3Punctuation(ch
)) {
729 static void FoldTADS3Doc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
730 WordList
*[], Accessor
&styler
) {
731 Sci_PositionU endPos
= startPos
+ length
;
732 Sci_Position lineCurrent
= styler
.GetLine(startPos
);
733 int levelCurrent
= SC_FOLDLEVELBASE
;
735 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
736 int seenStart
= levelCurrent
& T3_SEENSTART
;
737 int expectingIdentifier
= levelCurrent
& T3_EXPECTINGIDENTIFIER
;
738 int expectingPunctuation
= levelCurrent
& T3_EXPECTINGPUNCTUATION
;
739 levelCurrent
&= SC_FOLDLEVELNUMBERMASK
;
740 int levelMinCurrent
= levelCurrent
;
741 int levelNext
= levelCurrent
;
742 char chNext
= styler
[startPos
];
743 int styleNext
= styler
.StyleAt(startPos
);
744 int style
= initStyle
;
746 int stylePrev
= style
;
748 for (Sci_PositionU i
= startPos
; i
< endPos
; i
++) {
754 chNext
= styler
.SafeGetCharAt(i
+ 1);
757 styleNext
= styler
.StyleAt(i
+ 1);
759 bool atEOL
= IsEOL(ch
, chNext
);
761 if (levelNext
== SC_FOLDLEVELBASE
) {
762 if (IsSpaceEquivalent(ch
, style
)) {
763 if (expectingPunctuation
) {
764 expectingIdentifier
= 0;
766 if (style
== SCE_T3_BLOCK_COMMENT
) {
769 } else if (ch
== '{') {
772 } else if (ch
== '\'' || ch
== '"' || ch
== '[') {
777 } else if (ch
== ';') {
779 expectingIdentifier
= 0;
780 expectingPunctuation
= 0;
781 } else if (expectingIdentifier
&& expectingPunctuation
) {
782 if (IsATADS3Punctuation(ch
)) {
783 if (ch
== ')' && peekAhead(i
+1, endPos
, styler
) != '{') {
786 expectingPunctuation
= 0;
788 } else if (!IsAnIdentifier(style
)) {
791 } else if (expectingIdentifier
&& !expectingPunctuation
) {
792 if (!IsAnIdentifier(style
)) {
795 expectingPunctuation
= T3_EXPECTINGPUNCTUATION
;
797 } else if (!expectingIdentifier
&& expectingPunctuation
) {
798 if (!IsATADS3Punctuation(ch
)) {
801 if (ch
== ')' && peekAhead(i
+1, endPos
, styler
) != '{') {
804 expectingIdentifier
= T3_EXPECTINGIDENTIFIER
;
805 expectingPunctuation
= 0;
808 } else if (!expectingIdentifier
&& !expectingPunctuation
) {
809 if (IsAnIdentifier(style
)) {
810 seenStart
= T3_SEENSTART
;
811 expectingIdentifier
= T3_EXPECTINGIDENTIFIER
;
812 expectingPunctuation
= T3_EXPECTINGPUNCTUATION
;
816 if (levelNext
!= SC_FOLDLEVELBASE
&& style
!= SCE_T3_BLOCK_COMMENT
) {
817 expectingIdentifier
= 0;
818 expectingPunctuation
= 0;
821 } else if (levelNext
== SC_FOLDLEVELBASE
+1 && seenStart
822 && ch
== ';' && IsAnOperator(style
)) {
825 } else if (style
== SCE_T3_BLOCK_COMMENT
) {
826 if (stylePrev
!= SCE_T3_BLOCK_COMMENT
) {
828 } else if (styleNext
!= SCE_T3_BLOCK_COMMENT
&& !atEOL
) {
829 // Comments don't end at end of line and the next character may be unstyled.
832 } else if (ch
== '\'' || ch
== '"') {
833 if (IsStringTransition(style
, stylePrev
)) {
834 if (levelMinCurrent
> levelNext
) {
835 levelMinCurrent
= levelNext
;
838 } else if (IsStringTransition(style
, styleNext
)) {
841 } else if (IsAnOperator(style
)) {
842 if (ch
== '{' || ch
== '[') {
843 // Measure the minimum before a '{' to allow
844 // folding on "} else {"
845 if (levelMinCurrent
> levelNext
) {
846 levelMinCurrent
= levelNext
;
849 } else if (ch
== '}' || ch
== ']') {
855 if (seenStart
&& levelNext
== SC_FOLDLEVELBASE
) {
856 switch (peekAhead(i
+1, endPos
, styler
)) {
864 if (expectingPunctuation
) {
869 if (expectingIdentifier
) {
874 if (levelNext
!= SC_FOLDLEVELBASE
) {
875 expectingIdentifier
= 0;
876 expectingPunctuation
= 0;
879 int lev
= levelMinCurrent
| (levelNext
| expectingIdentifier
880 | expectingPunctuation
| seenStart
) << 16;
881 if (levelMinCurrent
< levelNext
)
882 lev
|= SC_FOLDLEVELHEADERFLAG
;
883 if (lev
!= styler
.LevelAt(lineCurrent
)) {
884 styler
.SetLevel(lineCurrent
, lev
);
887 levelCurrent
= levelNext
;
888 levelMinCurrent
= levelCurrent
;
893 static const char * const tads3WordList
[] = {
901 LexerModule
lmTADS3(SCLEX_TADS3
, ColouriseTADS3Doc
, "tads3", FoldTADS3Doc
, tads3WordList
);