xref: /aoo42x/main/basic/source/comp/token.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 #include <ctype.h>
32 #include "sbcomp.hxx"
33 
34 struct TokenTable { SbiToken t; const char *s; };
35 
36 static short nToken;					// Anzahl der Tokens
37 
38 static TokenTable* pTokTable;
39 
40 static TokenTable aTokTable_Basic [] = {		// Token-Tabelle:
41 
42 	{ CAT,		"&" },
43 	{ MUL,		"*" },
44 	{ PLUS,		"+" },
45 	{ MINUS,	"-" },
46 	{ DIV,		"/" },
47 	{ EOS,		":" },
48 	{ ASSIGN,	":=" },
49 	{ LT,		"<" },
50 	{ LE,		"<=" },
51 	{ NE,		"<>" },
52 	{ EQ,		"=" },
53 	{ GT,		">" },
54 	{ GE,		">=" },
55 	{ ACCESS,	"Access" },
56 	{ ALIAS,	"Alias" },
57 	{ AND,		"And" },
58 	{ ANY,		"Any" },
59 	{ APPEND,	"Append" },
60 	{ AS,		"As" },
61 	{ BASE,		"Base" },
62 	{ BINARY,	"Binary" },
63 	{ TBOOLEAN,	"Boolean" },
64 	{ BYREF,	"ByRef", },
65 	{ TBYTE,	"Byte", },
66 	{ BYVAL,	"ByVal", },
67 	{ CALL,		"Call" },
68 	{ CASE,		"Case" },
69 	{ _CDECL_,	"Cdecl" },
70 	{ CLASSMODULE, "ClassModule" },
71 	{ CLOSE,	"Close" },
72 	{ COMPARE,	"Compare" },
73 	{ COMPATIBLE,"Compatible" },
74 	{ _CONST_,	"Const" },
75 	{ TCURRENCY,"Currency" },
76 	{ TDATE,	"Date" },
77 	{ DECLARE,	"Declare" },
78 	{ DEFBOOL,	"DefBool" },
79 	{ DEFCUR,	"DefCur" },
80 	{ DEFDATE,	"DefDate" },
81 	{ DEFDBL,	"DefDbl" },
82 	{ DEFERR,	"DefErr" },
83 	{ DEFINT,	"DefInt" },
84 	{ DEFLNG,	"DefLng" },
85 	{ DEFOBJ,	"DefObj" },
86 	{ DEFSNG,	"DefSng" },
87 	{ DEFSTR,	"DefStr" },
88 	{ DEFVAR,	"DefVar" },
89 	{ DIM,		"Dim" },
90 	{ DO,		"Do" },
91 	{ TDOUBLE,	"Double" },
92 	{ EACH,		"Each" },
93 	{ ELSE,		"Else" },
94 	{ ELSEIF,	"ElseIf" },
95 	{ END,		"End" },
96 	{ ENDENUM,	"End Enum" },
97 	{ ENDFUNC,	"End Function" },
98 	{ ENDIF,	"End If" },
99 	{ ENDPROPERTY, "End Property" },
100 	{ ENDSELECT,"End Select" },
101 	{ ENDSUB,	"End Sub" },
102 	{ ENDTYPE,	"End Type" },
103 	{ ENDIF,	"EndIf" },
104 	{ ENUM,		"Enum" },
105 	{ EQV,		"Eqv" },
106 	{ ERASE,	"Erase" },
107 	{ _ERROR_,	"Error" },
108 	{ EXIT,		"Exit" },
109 	{ EXPLICIT,	"Explicit" },
110 	{ FOR,		"For" },
111 	{ FUNCTION,	"Function" },
112 	{ GET,		"Get" },
113 	{ GLOBAL,	"Global" },
114 	{ GOSUB,	"GoSub" },
115 	{ GOTO,		"GoTo" },
116 	{ IF,		"If" },
117 	{ IMP,		"Imp" },
118 	{ IMPLEMENTS, "Implements" },
119 	{ _IN_,		"In" },
120 	{ INPUT,	"Input" },				// auch INPUT #
121 	{ TINTEGER,	"Integer" },
122 	{ IS,		"Is" },
123 	{ LET,		"Let" },
124 	{ LIB,		"Lib" },
125 	{ LIKE,		"Like" },
126 	{ LINE,		"Line" },
127 	{ LINEINPUT,"Line Input" },
128 	{ LOCAL,	"Local" },
129 	{ LOCK,		"Lock" },
130 	{ TLONG,	"Long" },
131 	{ LOOP,		"Loop" },
132 	{ LPRINT,	"LPrint" },
133 	{ LSET,     "LSet" }, // JSM
134 	{ MOD,		"Mod" },
135 	{ NAME,		"Name" },
136 	{ NEW,		"New" },
137 	{ NEXT,		"Next" },
138 	{ NOT,		"Not" },
139 	{ TOBJECT,	"Object" },
140 	{ ON,		"On" },
141 	{ OPEN,		"Open" },
142 	{ OPTION,	"Option" },
143 	{ _OPTIONAL_,	"Optional" },
144 	{ OR,		"Or" },
145 	{ OUTPUT,	"Output" },
146 	{ PARAMARRAY,	"ParamArray" },
147 	{ PRESERVE, "Preserve" },
148 	{ PRINT,	"Print" },
149 	{ PRIVATE,	"Private" },
150 	{ PROPERTY,	"Property" },
151 	{ PUBLIC,	"Public" },
152 	{ RANDOM,	"Random" },
153 	{ READ,		"Read" },
154 	{ REDIM,	"ReDim" },
155 	{ REM, 		"Rem" },
156 	{ RESUME,	"Resume" },
157 	{ RETURN,	"Return" },
158 	{ RSET,     "RSet" }, // JSM
159 	{ SELECT,	"Select" },
160 	{ SET,		"Set" },
161 #ifdef SHARED
162 #undef SHARED
163 #define tmpSHARED
164 #endif
165 	{ SHARED,	"Shared" },
166 #ifdef tmpSHARED
167 #define SHARED
168 #undef tmpSHARED
169 #endif
170 	{ TSINGLE,	"Single" },
171 	{ STATIC,	"Static" },
172 	{ STEP,		"Step" },
173 	{ STOP,		"Stop" },
174 	{ TSTRING,	"String" },
175 	{ SUB,		"Sub" },
176 	{ STOP,		"System" },
177 	{ TEXT,		"Text" },
178 	{ THEN,		"Then" },
179 	{ TO,		"To", },
180 	{ TYPE,		"Type" },
181 	{ TYPEOF,	"TypeOf" },
182 	{ UNTIL,	"Until" },
183 	{ TVARIANT,	"Variant" },
184 	{ VBASUPPORT,	"VbaSupport" },
185 	{ WEND,		"Wend" },
186 	{ WHILE,	"While" },
187 	{ WITH,		"With" },
188 	{ WITHEVENTS,	"WithEvents" },
189 	{ WRITE,	"Write" },				// auch WRITE #
190 	{ XOR,		"Xor" },
191 	{ NIL,		"" }
192 };
193 
194 /*
195 TokenTable aTokTable_Java [] = {		// Token-Tabelle:
196 
197 	{ JS_LOG_NOT,	"!" },
198 	{ JS_NE,		"!=" },
199 	{ JS_MOD,		"%" },
200 	{ JS_ASS_MOD,	"%=" },
201 	{ JS_BIT_AND,	"&" },
202 	{ JS_LOG_AND,	"&&" },
203 	{ JS_ASS_AND,	"&=" },
204 	{ JS_LPAREN,	"(" },
205 	{ JS_RPAREN,	")" },
206 	{ JS_MUL,		"*" },
207 	{ JS_ASS_MUL,	"*=" },
208 	{ JS_PLUS,		"+" },
209 	{ JS_INC,		"++" },
210 	{ JS_ASS_PLUS,	"+=" },
211 	{ JS_COMMA,		"," },
212 	{ JS_MINUS,		"-" },
213 	{ JS_DEC,		"--" },
214 	{ JS_ASS_MINUS,	"-=" },
215 	{ JS_DIV,		"/" },
216 	{ JS_ASS_DIV,	"/=" },
217 	{ JS_COND_SEL,	":" },
218 	{ JS_LT,		"<" },
219 	{ JS_LSHIFT,	"<<" },
220 	{ JS_ASS_LSHIFT,"<<=" },
221 	{ JS_LE,		"<=" },
222 	{ JS_NE,		"<>" },
223 	{ JS_ASSIGNMENT,"=" },
224 	{ JS_EQ,		"==" },
225 	{ JS_GT,		">" },
226 	{ JS_RSHIFT,	">>" },
227 	{ JS_ASS_RSHIFT,">>=" },
228 	{ JS_RSHIFT_Z,	">>>" },
229 	{ JS_ASS_RSHIFT_Z,">>>=" },
230 	{ JS_GE,		">=" },
231 	{ JS_COND_QUEST,"?" },
232 	{ ACCESS,	"Access" },
233 	{ ALIAS,	"Alias" },
234 	{ AND,		"And" },
235 	{ ANY,		"Any" },
236 	{ APPEND,	"Append" },
237 	{ AS,		"As" },
238 	{ BASE,		"Base" },
239 	{ BINARY,	"Binary" },
240 	{ TBOOLEAN,	"Boolean" },
241 	{ BYVAL,	"ByVal", },
242 	{ CALL,		"Call" },
243 	{ CASE,		"Case" },
244 	{ _CDECL_,	"Cdecl" },
245 	{ CLOSE,	"Close" },
246 	{ COMPARE,	"Compare" },
247 	{ _CONST_,	"Const" },
248 	{ TCURRENCY,"Currency" },
249 	{ TDATE,	"Date" },
250 	{ DECLARE,	"Declare" },
251 	{ DEFBOOL,	"DefBool" },
252 	{ DEFCUR,	"DefCur" },
253 	{ DEFDATE,	"DefDate" },
254 	{ DEFDBL,	"DefDbl" },
255 	{ DEFERR,	"DefErr" },
256 	{ DEFINT,	"DefInt" },
257 	{ DEFLNG,	"DefLng" },
258 	{ DEFOBJ,	"DefObj" },
259 	{ DEFSNG,	"DefSng" },
260 	{ DEFSTR,	"DefStr" },
261 	{ DEFVAR,	"DefVar" },
262 	{ DIM,		"Dim" },
263 	{ DO,		"Do" },
264 	{ TDOUBLE,	"Double" },
265 	{ EACH,		"Each" },
266 	{ ELSE,		"Else" },
267 	{ ELSEIF,	"ElseIf" },
268 	{ END,		"End" },
269 	{ ENDFUNC,	"End Function" },
270 	{ ENDIF,	"End If" },
271 	{ ENDSELECT,"End Select" },
272 	{ ENDSUB,	"End Sub" },
273 	{ ENDTYPE,	"End Type" },
274 	{ ENDIF,	"EndIf" },
275 	{ EQV,		"Eqv" },
276 	{ ERASE,	"Erase" },
277 	{ _ERROR_,	"Error" },
278 	{ EXIT,		"Exit" },
279 	{ EXPLICIT,	"Explicit" },
280 	{ FOR,		"For" },
281 	{ FUNCTION,	"Function" },
282 	{ GLOBAL,	"Global" },
283 	{ GOSUB,	"GoSub" },
284 	{ GOTO,		"GoTo" },
285 	{ IF,		"If" },
286 	{ IMP,		"Imp" },
287 	{ _IN_,		"In" },
288 	{ INPUT,	"Input" },				// auch INPUT #
289 	{ TINTEGER,	"Integer" },
290 	{ IS,		"Is" },
291 	{ LET,		"Let" },
292 	{ LIB,		"Lib" },
293 	{ LINE,		"Line" },
294 	{ LINEINPUT,"Line Input" },
295 	{ LOCAL,	"Local" },
296 	{ LOCK,		"Lock" },
297 	{ TLONG,	"Long" },
298 	{ LOOP,		"Loop" },
299 	{ LPRINT,	"LPrint" },
300 	{ LSET,     "LSet" }, // JSM
301 	{ MOD,		"Mod" },
302 	{ NAME,		"Name" },
303 	{ NEW,		"New" },
304 	{ NEXT,		"Next" },
305 	{ NOT,		"Not" },
306 	{ TOBJECT,	"Object" },
307 	{ ON,		"On" },
308 	{ OPEN,		"Open" },
309 	{ OPTION,	"Option" },
310 	{ _OPTIONAL_,	"Optional" },
311 	{ OR,		"Or" },
312 	{ OUTPUT,	"Output" },
313 	{ PRESERVE, "Preserve" },
314 	{ PRINT,	"Print" },
315 	{ PRIVATE,	"Private" },
316 	{ PUBLIC,	"Public" },
317 	{ RANDOM,	"Random" },
318 	{ READ,		"Read" },
319 	{ REDIM,	"ReDim" },
320 	{ REM, 		"Rem" },
321 	{ RESUME,	"Resume" },
322 	{ RETURN,	"Return" },
323 	{ RSET,     "RSet" }, // JSM
324 	{ SELECT,	"Select" },
325 	{ SET,		"Set" },
326 	{ SHARED,	"Shared" },
327 	{ TSINGLE,	"Single" },
328 	{ STATIC,	"Static" },
329 	{ STEP,		"Step" },
330 	{ STOP,		"Stop" },
331 	{ TSTRING,	"String" },
332 	{ SUB,		"Sub" },
333 	{ STOP,		"System" },
334 	{ TEXT,		"Text" },
335 	{ THEN,		"Then" },
336 	{ TO,		"To", },
337 	{ TYPE,		"Type" },
338 	{ UNTIL,	"Until" },
339 	{ TVARIANT,	"Variant" },
340 	{ WEND,		"Wend" },
341 	{ WHILE,	"While" },
342 	{ WITH,		"With" },
343 	{ WRITE,	"Write" },				// auch WRITE #
344 	{ XOR,		"Xor" },
345 	{ JS_LINDEX,	"[" },
346 	{ JS_RINDEX,	"]" },
347 	{ JS_BIT_XOR,	"^" },
348 	{ JS_ASS_XOR,	"^=" },
349 	{ JS_BIT_OR,	"|" },
350 	{ JS_ASS_OR,	"|=" },
351 	{ JS_LOG_OR,	"||" },
352 	{ JS_BIT_NOT,	"~" },
353 	{ NIL }
354 };
355 */
356 
357 // #i109076
358 TokenLabelInfo::TokenLabelInfo( void )
359 {
360 	m_pTokenCanBeLabelTab = new bool[VBASUPPORT+1];
361 	for( int i = 0 ; i <= VBASUPPORT ; ++i )
362 		m_pTokenCanBeLabelTab[i] = false;
363 
364 	// Token accepted as label by VBA
365 	SbiToken eLabelToken[] = { ACCESS, ALIAS, APPEND, BASE, BINARY, CLASSMODULE,
366 		COMPARE, COMPATIBLE, DEFERR, _ERROR_, EXPLICIT, LIB, LINE, LPRINT, NAME,
367 		TOBJECT, OUTPUT, PROPERTY, RANDOM, READ, STEP, STOP, TEXT, VBASUPPORT, NIL };
368 	SbiToken* pTok = eLabelToken;
369 	SbiToken eTok;
370 	for( pTok = eLabelToken ; (eTok = *pTok) != NIL ; ++pTok )
371 		m_pTokenCanBeLabelTab[eTok] = true;
372 }
373 
374 TokenLabelInfo::~TokenLabelInfo()
375 {
376 	delete[] m_pTokenCanBeLabelTab;
377 }
378 
379 
380 // Der Konstruktor ermittelt die Laenge der Token-Tabelle.
381 
382 SbiTokenizer::SbiTokenizer( const ::rtl::OUString& rSrc, StarBASIC* pb )
383 		   : SbiScanner( rSrc, pb )
384 {
385 	pTokTable = aTokTable_Basic;
386 	//if( StarBASIC::GetGlobalLanguageMode() == SB_LANG_JAVASCRIPT )
387 	//	pTokTable = aTokTable_Java;
388 	TokenTable *tp;
389 	bEof = bAs = sal_False;
390 	eCurTok = NIL;
391 	ePush = NIL;
392 	bEos = bKeywords = bErrorIsSymbol = sal_True;
393 	if( !nToken )
394 		for( nToken = 0, tp = pTokTable; tp->t; nToken++, tp++ ) {}
395 }
396 
397 SbiTokenizer::~SbiTokenizer()
398 {
399 }
400 
401 // Wiederablage (Pushback) eines Tokens. (Bis zu 2 Tokens)
402 
403 void SbiTokenizer::Push( SbiToken t )
404 {
405 	if( ePush != NIL )
406 		Error( SbERR_INTERNAL_ERROR, "PUSH" );
407 	else ePush = t;
408 }
409 
410 void SbiTokenizer::Error( SbError code, const char* pMsg )
411 {
412 	aError = String::CreateFromAscii( pMsg );
413 	Error( code );
414 }
415 
416 void SbiTokenizer::Error( SbError code, String aMsg )
417 {
418 	aError = aMsg;
419 	Error( code );
420 }
421 
422 void SbiTokenizer::Error( SbError code, SbiToken tok )
423 {
424 	aError = Symbol( tok );
425 	Error( code );
426 }
427 
428 // Einlesen des naechsten Tokens, ohne dass das Token geschluckt wird
429 
430 SbiToken SbiTokenizer::Peek()
431 {
432 	if( ePush == NIL )
433 	{
434 		sal_uInt16 nOldLine = nLine;
435 		sal_uInt16 nOldCol1 = nCol1;
436 		sal_uInt16 nOldCol2 = nCol2;
437 		ePush = Next();
438 		nPLine = nLine; nLine = nOldLine;
439 		nPCol1 = nCol1; nCol1 = nOldCol1;
440 		nPCol2 = nCol2; nCol2 = nOldCol2;
441 	}
442 	return eCurTok = ePush;
443 }
444 
445 // Dies ist fuer die Decompilation.
446 // Zahlen und Symbole liefern einen Leerstring zurueck.
447 
448 const String& SbiTokenizer::Symbol( SbiToken t )
449 {
450 	// Zeichen-Token?
451 	if( t < FIRSTKWD )
452 	{
453 		aSym = (char) t;
454 		return aSym;
455 	}
456 	switch( t )
457 	{
458 		case NEG   : aSym = '-'; return aSym;
459 		case EOS   : aSym = String::CreateFromAscii( ":/CRLF" ); return aSym;
460 		case EOLN  : aSym = String::CreateFromAscii( "CRLF" ); return aSym;
461 		default: break;
462 	}
463 	TokenTable* tp = pTokTable;
464 	for( short i = 0; i < nToken; i++, tp++ )
465 	{
466 		if( tp->t == t )
467 		{
468 			aSym = String::CreateFromAscii( tp->s );
469 			return aSym;
470 		}
471 	}
472 	const sal_Unicode *p = aSym.GetBuffer();
473 	if (*p <= ' ') aSym = String::CreateFromAscii( "???" );
474 	return aSym;
475 }
476 
477 // Einlesen des naechsten Tokens und Ablage desselben
478 // Tokens, die nicht in der Token-Tabelle vorkommen, werden
479 // direkt als Zeichen zurueckgeliefert.
480 // Einige Worte werden gesondert behandelt.
481 
482 SbiToken SbiTokenizer::Next()
483 {
484 	if (bEof) return EOLN;
485 	// Schon eines eingelesen?
486 	if( ePush != NIL )
487 	{
488 		eCurTok = ePush;
489 		ePush = NIL;
490 		nLine = nPLine;
491 		nCol1 = nPCol1;
492 		nCol2 = nPCol2;
493 		bEos = IsEoln( eCurTok );
494 		return eCurTok;
495 	}
496 	TokenTable *tp;
497 
498 	// Sonst einlesen:
499 	if( !NextSym() )
500 	{
501 		bEof = bEos = sal_True;
502 		return eCurTok = EOLN;
503 	}
504 	// Zeilenende?
505 	if( aSym.GetBuffer()[0] == '\n' )
506 	{
507 		bEos = sal_True; return eCurTok = EOLN;
508 	}
509 	bEos = sal_False;
510 
511 	// Zahl?
512 	if( bNumber )
513 		return eCurTok = NUMBER;
514 
515 	// String?
516 	else if( ( eScanType == SbxDATE || eScanType == SbxSTRING ) && !bSymbol )
517 		return eCurTok = FIXSTRING;
518 	// Sonderfaelle von Zeichen, die zwischen "Z" und "a" liegen. ICompare()
519 	// wertet die Position dieser Zeichen unterschiedlich aus.
520 	else if( aSym.GetBuffer()[0] == '^' )
521 		return eCurTok = EXPON;
522 	else if( aSym.GetBuffer()[0] == '\\' )
523 		return eCurTok = IDIV;
524 	else
525 	{
526 		// Mit Typkennung oder ein Symbol und keine Keyword-Erkennung?
527 		// Dann kein Token-Test
528 		if( eScanType != SbxVARIANT
529 		 || ( !bKeywords && bSymbol ) )
530 			return eCurTok = SYMBOL;
531 		// Gueltiges Token?
532 		short lb = 0;
533 		short ub = nToken-1;
534 		short delta;
535 		do
536 		{
537 			delta = (ub - lb) >> 1;
538 			tp = &pTokTable[ lb + delta ];
539 			StringCompare res = aSym.CompareIgnoreCaseToAscii( tp->s );
540 			// Gefunden?
541 			if( res == COMPARE_EQUAL )
542 				goto special;
543 			// Groesser? Dann untere Haelfte
544 			if( res == COMPARE_LESS )
545 			{
546 				if ((ub - lb) == 2) ub = lb;
547 				else ub = ub - delta;
548 			}
549 			// Kleiner? Dann obere Haelfte
550 			else
551 			{
552 				if ((ub -lb) == 2) lb = ub;
553 				else lb = lb + delta;
554 			}
555 		} while( delta );
556 		// Symbol? Wenn nicht >= Token
557 		sal_Unicode ch = aSym.GetBuffer()[0];
558 		if( !BasicSimpleCharClass::isAlpha( ch, bCompatible ) && !bSymbol )
559 			return eCurTok = (SbiToken) (ch & 0x00FF);
560 		return eCurTok = SYMBOL;
561 	}
562 special:
563 	// #i92642
564 	bool bStartOfLine = (eCurTok == NIL || eCurTok == REM || eCurTok == EOLN);
565 	if( !bStartOfLine && (tp->t == NAME || tp->t == LINE) )
566 		return eCurTok = SYMBOL;
567 	else if( tp->t == TEXT )
568 		return eCurTok = SYMBOL;
569 
570 	// #i92642: Special LINE token handling -> SbiParser::Line()
571 
572 	// END IF, CASE, SUB, DEF, FUNCTION, TYPE, CLASS, WITH
573 	if( tp->t == END )
574 	{
575 		// AB, 15.3.96, Spezialbehandlung fuer END, beim Peek() geht die
576 		// aktuelle Zeile verloren, daher alles merken und danach restaurieren
577 		sal_uInt16 nOldLine = nLine;
578 		sal_uInt16 nOldCol  = nCol;
579 		sal_uInt16 nOldCol1 = nCol1;
580 		sal_uInt16 nOldCol2 = nCol2;
581 		String aOldSym = aSym;
582 		SaveLine();				// pLine im Scanner sichern
583 
584 		eCurTok = Peek();
585 		switch( eCurTok )
586 		{
587 			case IF: 	   Next(); eCurTok = ENDIF; break;
588 			case SELECT:   Next(); eCurTok = ENDSELECT; break;
589 			case SUB: 	   Next(); eCurTok = ENDSUB; break;
590 			case FUNCTION: Next(); eCurTok = ENDFUNC; break;
591 			case PROPERTY: Next(); eCurTok = ENDPROPERTY; break;
592 			case TYPE: 	   Next(); eCurTok = ENDTYPE; break;
593 			case ENUM: 	   Next(); eCurTok = ENDENUM; break;
594 			case WITH: 	   Next(); eCurTok = ENDWITH; break;
595 			default : 	   eCurTok = END;
596 		}
597 		nCol1 = nOldCol1;
598 		if( eCurTok == END )
599 		{
600 			// Alles zuruecksetzen, damit Token nach END ganz neu gelesen wird
601 			ePush = NIL;
602 			nLine = nOldLine;
603 			nCol  = nOldCol;
604 			nCol2 = nOldCol2;
605 			aSym = aOldSym;
606 			RestoreLine();		// pLine im Scanner restaurieren
607 		}
608 		return eCurTok;
609 	}
610 	// Sind Datentypen Keywords?
611 	// Nur nach AS, sonst sind es Symbole!
612 	// Es gibt ja ERROR(), DATA(), STRING() etc.
613 	eCurTok = tp->t;
614 	// AS: Datentypen sind Keywords
615 	if( tp->t == AS )
616 		bAs = sal_True;
617 	else
618 	{
619 		if( bAs )
620 			bAs = sal_False;
621 		else if( eCurTok >= DATATYPE1 && eCurTok <= DATATYPE2 && (bErrorIsSymbol || eCurTok != _ERROR_) )
622 			eCurTok = SYMBOL;
623 	}
624 
625 	// CLASSMODULE, PROPERTY, GET, ENUM token only visible in compatible mode
626 	SbiToken eTok = tp->t;
627 	if( bCompatible )
628 	{
629 		// #129904 Suppress system
630 		if( eTok == STOP && aSym.CompareIgnoreCaseToAscii( "system" ) == COMPARE_EQUAL )
631 			eCurTok = SYMBOL;
632 
633 		if( eTok == GET && bStartOfLine )
634 			eCurTok = SYMBOL;
635 	}
636 	else
637 	{
638 		if( eTok == CLASSMODULE ||
639 			eTok == IMPLEMENTS ||
640 			eTok == PARAMARRAY ||
641 			eTok == ENUM ||
642 			eTok == PROPERTY ||
643 			eTok == GET ||
644 			eTok == TYPEOF )
645 		{
646 			eCurTok = SYMBOL;
647 		}
648 	}
649 
650 	bEos = IsEoln( eCurTok );
651 	return eCurTok;
652 }
653 
654 #ifdef _MSC_VER
655 #pragma optimize("",off)
656 #endif
657 
658 // Kann das aktuell eingelesene Token ein Label sein?
659 
660 sal_Bool SbiTokenizer::MayBeLabel( sal_Bool bNeedsColon )
661 {
662 	if( eCurTok == SYMBOL || m_aTokenLabelInfo.canTokenBeLabel( eCurTok ) )
663 		return bNeedsColon ? DoesColonFollow() : sal_True;
664 	else
665 		return sal_Bool( eCurTok == NUMBER
666 				  && eScanType == SbxINTEGER
667 				  && nVal >= 0 );
668 }
669 
670 #ifdef _MSC_VER
671 #pragma optimize("",off)
672 #endif
673 
674 
675 void SbiTokenizer::Hilite( SbTextPortions& rList )
676 {
677 	bErrors = sal_False;
678 	bUsedForHilite = sal_True;
679 	SbiToken eLastTok = NIL;
680 	for( ;; )
681 	{
682 		Next();
683 		if( IsEof() )
684 			break;
685 		SbTextPortion aRes;
686 		aRes.nLine = nLine;
687 		aRes.nStart = nCol1;
688 		aRes.nEnd = nCol2;
689 		switch( eCurTok )
690 		{
691 			case REM:
692 				aRes.eType = SB_COMMENT; break;
693 			case SYMBOL:
694 				aRes.eType = SB_SYMBOL; break;
695 			case FIXSTRING:
696 				aRes.eType = SB_STRING; break;
697 			case NUMBER:
698 				aRes.eType = SB_NUMBER; break;
699 			default:
700 				if( ( eCurTok >= FIRSTKWD && eCurTok <= LASTKWD )
701 				 || (eCurTok >= _CDECL_ ) )
702 					aRes.eType = SB_KEYWORD;
703 				else
704 					aRes.eType = SB_PUNCTUATION;
705 		}
706 		// Die Folge xxx.Keyword sollte nicht als Kwd geflagt werden
707 		if( aRes.eType == SB_KEYWORD
708 		 && ( eLastTok == DOT|| eLastTok == EXCLAM ) )
709 			aRes.eType = SB_SYMBOL;
710 		if( eCurTok != EOLN && aRes.nStart <= aRes.nEnd )
711 			rList.Insert( aRes, rList.Count() );
712 		if( aRes.eType == SB_COMMENT )
713 			break;
714 		eLastTok = eCurTok;
715 	}
716 	bUsedForHilite = sal_False;
717 }
718 
719