xref: /trunk/main/basic/source/comp/token.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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