1
// -*- coding: utf-8 -*-
2
// Scintilla source code edit control
5
* @author Dariusz "DKnoto" KnociÅski
7
* @brief Lexer for Modula-2/3 documents.
9
// The License.txt file describes the conditions under which this software may
20
#include "Scintilla.h"
23
#include "PropSetSimple.h"
25
#include "LexAccessor.h"
27
#include "StyleContext.h"
28
#include "CharacterSet.h"
29
#include "LexerModule.h"
32
using namespace Scintilla;
35
#ifdef DEBUG_LEX_MODULA
36
#define DEBUG_STATE( p, c )\
37
fprintf( stderr, "Unknown state: currentPos = %d, char = '%c'\n", p, c );
39
#define DEBUG_STATE( p, c )
42
static inline bool IsDigitOfBase( unsigned ch, unsigned base ) {
43
if( ch < '0' || ch > 'f' ) return false;
45
if( ch >= ( '0' + base ) ) return false;
48
unsigned nb = base - 10;
49
if( ( ch < 'A' ) || ( ch >= ( 'A' + nb ) ) ) {
50
if( ( ch < 'a' ) || ( ch >= ( 'a' + nb ) ) ) {
59
static inline unsigned IsOperator( StyleContext & sc, WordList & op ) {
66
for( i = 0; i < op.len; i++ ) {
67
if( ( strlen( op.words[i] ) == 2 ) &&
68
( s[0] == op.words[i][0] && s[1] == op.words[i][1] ) ) {
73
for( i = 0; i < op.len; i++ ) {
74
if( ( strlen( op.words[i] ) == 1 ) &&
75
( s[0] == op.words[i][0] ) ) {
82
static inline bool IsEOL( Accessor &styler, unsigned curPos ) {
83
unsigned ch = styler.SafeGetCharAt( curPos );
84
if( ( ch == '\r' && styler.SafeGetCharAt( curPos + 1 ) == '\n' ) ||
91
static inline bool checkStatement(
94
const char *stt, bool spaceAfter = true ) {
95
int len = strlen( stt );
97
for( i = 0; i < len; i++ ) {
98
if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
103
if( ! isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
107
curPos += ( len - 1 );
111
static inline bool checkEndSemicolon(
113
int &curPos, int endPos )
115
const char *stt = "END";
116
int len = strlen( stt );
118
for( i = 0; i < len; i++ ) {
119
if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
123
while( isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
125
if( ( curPos + i ) >= endPos ) return false;
127
if( styler.SafeGetCharAt( curPos + i ) != ';' ) {
134
static inline bool checkKeyIdentOper(
137
int &curPos, int endPos,
138
const char *stt, const char etk ) {
140
if( ! checkStatement( styler, newPos, stt ) )
143
if( newPos >= endPos )
145
if( ! isspace( styler.SafeGetCharAt( newPos ) ) )
148
if( newPos >= endPos )
150
while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
152
if( newPos >= endPos )
155
if( ! isalpha( styler.SafeGetCharAt( newPos ) ) )
158
if( newPos >= endPos )
161
ch = styler.SafeGetCharAt( newPos );
162
while( isalpha( ch ) || isdigit( ch ) || ch == '_' ) {
164
if( newPos >= endPos ) return false;
165
ch = styler.SafeGetCharAt( newPos );
167
while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
169
if( newPos >= endPos ) return false;
171
if( styler.SafeGetCharAt( newPos ) != etk )
177
static void FoldModulaDoc( unsigned int startPos,
182
int curLine = styler.GetLine(startPos);
183
int curLevel = SC_FOLDLEVELBASE;
184
int endPos = startPos + length;
186
curLevel = styler.LevelAt( curLine - 1 ) >> 16;
187
int curPos = startPos;
188
int style = styler.StyleAt( curPos );
190
int nextLevel = curLevel;
192
while( curPos < endPos ) {
193
if( ! isspace( styler.SafeGetCharAt( curPos ) ) ) visChars++;
196
case SCE_MODULA_COMMENT:
197
if( checkStatement( styler, curPos, "(*" ) )
200
if( checkStatement( styler, curPos, "*)" ) )
204
case SCE_MODULA_DOXYCOMM:
205
if( checkStatement( styler, curPos, "(**", false ) )
208
if( checkStatement( styler, curPos, "*)" ) )
212
case SCE_MODULA_KEYWORD:
213
if( checkStatement( styler, curPos, "IF" ) )
216
if( checkStatement( styler, curPos, "BEGIN" ) )
219
if( checkStatement( styler, curPos, "TRY" ) )
222
if( checkStatement( styler, curPos, "LOOP" ) )
225
if( checkStatement( styler, curPos, "FOR" ) )
228
if( checkStatement( styler, curPos, "WHILE" ) )
231
if( checkStatement( styler, curPos, "REPEAT" ) )
234
if( checkStatement( styler, curPos, "UNTIL" ) )
237
if( checkStatement( styler, curPos, "WITH" ) )
240
if( checkStatement( styler, curPos, "CASE" ) )
243
if( checkStatement( styler, curPos, "TYPECASE" ) )
246
if( checkStatement( styler, curPos, "LOCK" ) )
249
if( checkKeyIdentOper( styler, curPos, endPos, "PROCEDURE", '(' ) )
252
if( checkKeyIdentOper( styler, curPos, endPos, "END", ';' ) ) {
254
int clv_old = curLevel;
259
clv_new = styler.LevelAt( cln - 1 ) >> 16;
260
if( clv_new < clv_old ) {
262
pos = styler.LineStart( cln );
263
while( ( ch = styler.SafeGetCharAt( pos ) ) != '\n' ) {
265
if( styler.StyleAt(pos) == SCE_MODULA_KEYWORD ) {
266
if( checkKeyIdentOper( styler, pos, endPos,
267
"PROCEDURE", '(' ) ) {
280
if( checkKeyIdentOper( styler, curPos, endPos, "END", '.' ) )
283
if( checkEndSemicolon( styler, curPos, endPos ) )
286
while( styler.StyleAt( curPos + 1 ) == SCE_MODULA_KEYWORD )
295
if( IsEOL( styler, curPos ) || ( curPos == endPos - 1 ) ) {
296
int efectiveLevel = curLevel | nextLevel << 16;
298
efectiveLevel |= SC_FOLDLEVELWHITEFLAG;
299
if( curLevel < nextLevel )
300
efectiveLevel |= SC_FOLDLEVELHEADERFLAG;
301
if( efectiveLevel != styler.LevelAt(curLine) ) {
302
styler.SetLevel(curLine, efectiveLevel );
305
curLevel = nextLevel;
306
if( IsEOL( styler, curPos ) && ( curPos == endPos - 1 ) ) {
307
styler.SetLevel( curLine, ( curLevel | curLevel << 16)
308
| SC_FOLDLEVELWHITEFLAG);
313
style = styler.StyleAt( curPos );
317
static inline bool skipWhiteSpaces( StyleContext & sc ) {
318
while( isspace( sc.ch ) ) {
319
sc.SetState( SCE_MODULA_DEFAULT );
328
static void ColouriseModulaDoc( unsigned int startPos,
333
WordList& keyWords = *wl[0];
334
WordList& reservedWords = *wl[1];
335
WordList& operators = *wl[2];
336
WordList& pragmaWords = *wl[3];
337
WordList& escapeCodes = *wl[4];
338
WordList& doxyKeys = *wl[5];
340
const int BUFLEN = 128;
347
StyleContext sc( startPos, length, initStyle, styler );
351
case SCE_MODULA_DEFAULT:
352
if( ! skipWhiteSpaces( sc ) ) break;
354
if( sc.ch == '(' && sc.chNext == '*' ) {
355
if( sc.GetRelative(2) == '*' ) {
356
sc.SetState( SCE_MODULA_DOXYCOMM );
359
sc.SetState( SCE_MODULA_COMMENT );
364
if( isalpha( sc.ch ) ) {
365
if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
366
for( i = 0; i < BUFLEN - 1; i++ ) {
367
buf[i] = sc.GetRelative(i);
368
if( !isalpha( buf[i] ) && !(buf[i] == '_') )
374
if( keyWords.InList( buf ) ) {
375
sc.SetState( SCE_MODULA_KEYWORD );
377
sc.SetState( SCE_MODULA_DEFAULT );
381
if( reservedWords.InList( buf ) ) {
382
sc.SetState( SCE_MODULA_RESERVED );
384
sc.SetState( SCE_MODULA_DEFAULT );
387
/** check procedure identifier */
390
for( i = 0; i < BUFLEN - 1; i++ ) {
391
buf[i] = sc.GetRelative(i);
392
if( !isalpha( buf[i] ) &&
393
!isdigit( buf[i] ) &&
400
sc.SetState( SCE_MODULA_DEFAULT );
406
if( isdigit( sc.ch ) ) {
407
sc.SetState( SCE_MODULA_NUMBER );
411
if( sc.ch == '\"' ) {
412
sc.SetState( SCE_MODULA_STRING );
415
if( sc.ch == '\'' ) {
416
charPos = sc.currentPos;
417
sc.SetState( SCE_MODULA_CHAR );
420
if( sc.ch == '<' && sc.chNext == '*' ) {
421
sc.SetState( SCE_MODULA_PRAGMA );
424
unsigned len = IsOperator( sc, operators );
426
sc.SetState( SCE_MODULA_OPERATOR );
428
sc.SetState( SCE_MODULA_DEFAULT );
431
DEBUG_STATE( sc.currentPos, sc.ch );
436
case SCE_MODULA_COMMENT:
437
if( sc.ch == '*' && sc.chNext == ')' ) {
439
sc.SetState( SCE_MODULA_DEFAULT );
444
case SCE_MODULA_DOXYCOMM:
447
if( sc.chNext == ')' ) {
449
sc.SetState( SCE_MODULA_DEFAULT );
455
if( islower( sc.chNext ) ) {
456
for( i = 0; i < BUFLEN - 1; i++ ) {
457
buf[i] = sc.GetRelative(i+1);
458
if( isspace( buf[i] ) ) break;
463
if( doxyKeys.InList( buf ) ) {
464
sc.SetState( SCE_MODULA_DOXYKEY );
465
sc.Forward( kl + 1 );
466
sc.SetState( SCE_MODULA_DOXYCOMM );
476
case SCE_MODULA_NUMBER:
479
for( i = 1; i < BUFLEN - 1; i++ ) {
480
buf[i] = sc.GetRelative(i);
481
if( ! isdigit( buf[i] ) )
487
switch( sc.GetRelative(kl) ) {
490
int base = atoi( buf );
491
if( base < 2 || base > 16 ) {
492
sc.SetState( SCE_MODULA_BADSTR );
497
for( i = 0; i < BUFLEN - 1; i++ ) {
498
buf[i] = sc.GetRelative(kl+i);
499
if( ! IsDigitOfBase( buf[i], 16 ) ) {
504
for( i = 0; i < imax; i++ ) {
505
if( ! IsDigitOfBase( buf[i], base ) ) {
506
sc.SetState( SCE_MODULA_BADSTR );
512
sc.SetState( SCE_MODULA_BASENUM );
513
for( i = 0; i < kl; i++ ) {
516
sc.SetState( SCE_MODULA_DEFAULT );
522
if( sc.GetRelative(kl+1) == '.' ) {
524
for( i = 0; i < kl; i++ ) {
528
sc.SetState( SCE_MODULA_DEFAULT );
535
buf[0] = sc.GetRelative(kl);
536
if( isdigit( buf[0] ) ) {
538
if( !isdigit(sc.GetRelative(kl+i)) )
542
buf[0] = sc.GetRelative(kl);
553
buf[0] = sc.GetRelative(kl);
554
if( buf[0] == '-' || buf[0] == '+' ) {
557
buf[0] = sc.GetRelative(kl);
558
if( isdigit( buf[0] ) ) {
560
if( !isdigit(sc.GetRelative(kl+i)) ) {
561
buf[0] = sc.GetRelative(kl+i);
568
sc.SetState( SCE_MODULA_BADSTR );
577
sc.SetState( SCE_MODULA_BADSTR );
581
if( ! isspace( buf[0] ) &&
594
sc.SetState( SCE_MODULA_BADSTR );
600
sc.SetState( SCE_MODULA_FLOAT );
601
for( i = 0; i < kl; i++ ) {
604
sc.SetState( SCE_MODULA_DEFAULT );
609
for( i = 0; i < kl; i++ ) {
614
sc.SetState( SCE_MODULA_DEFAULT );
619
case SCE_MODULA_STRING:
620
if( sc.ch == '\"' ) {
622
sc.SetState( SCE_MODULA_DEFAULT );
625
if( sc.ch == '\\' ) {
627
if( IsDigitOfBase( sc.chNext, 8 ) ) {
628
for( i = 1; i < BUFLEN - 1; i++ ) {
629
if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
633
sc.SetState( SCE_MODULA_STRSPEC );
635
sc.SetState( SCE_MODULA_BADSTR );
641
if( escapeCodes.InList( buf ) ) {
642
sc.SetState( SCE_MODULA_STRSPEC );
644
sc.SetState( SCE_MODULA_BADSTR );
648
sc.SetState( SCE_MODULA_STRING );
654
case SCE_MODULA_CHAR:
655
if( sc.ch == '\'' ) {
657
sc.SetState( SCE_MODULA_DEFAULT );
661
if( ( sc.currentPos - charPos ) == 1 ) {
662
if( sc.ch == '\\' ) {
664
if( IsDigitOfBase( sc.chNext, 8 ) ) {
665
for( i = 1; i < BUFLEN - 1; i++ ) {
666
if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
670
sc.SetState( SCE_MODULA_CHARSPEC );
672
sc.SetState( SCE_MODULA_BADSTR );
678
if( escapeCodes.InList( buf ) ) {
679
sc.SetState( SCE_MODULA_CHARSPEC );
681
sc.SetState( SCE_MODULA_BADSTR );
685
sc.SetState( SCE_MODULA_CHAR );
689
sc.SetState( SCE_MODULA_BADSTR );
691
sc.SetState( SCE_MODULA_CHAR );
696
case SCE_MODULA_PRAGMA:
697
if( sc.ch == '*' && sc.chNext == '>' ) {
700
sc.SetState( SCE_MODULA_DEFAULT );
704
if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
707
for( i = 2; i < BUFLEN - 1; i++ ) {
708
buf[i] = sc.GetRelative(i);
709
if( !isupper( buf[i] ) )
714
if( pragmaWords.InList( buf ) ) {
715
sc.SetState( SCE_MODULA_PRGKEY );
717
sc.SetState( SCE_MODULA_PRAGMA );
731
static const char *const modulaWordListDesc[] =
742
LexerModule lmModula( SCLEX_MODULA, ColouriseModulaDoc, "modula", FoldModulaDoc,