1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: token.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
37 struct TokenTable
{ SbiToken t
; const char *s
; };
39 static short nToken
; // Anzahl der Tokens
41 static TokenTable
* pTokTable
;
43 static TokenTable aTokTable_Basic
[] = { // Token-Tabelle:
64 { ATTRIBUTE
,"Attribute" },
67 { TBOOLEAN
, "Boolean" },
74 { CLASSMODULE
, "ClassModule" },
76 { COMPARE
, "Compare" },
77 { COMPATIBLE
,"Compatible" },
79 { TCURRENCY
,"Currency" },
81 { DECLARE
, "Declare" },
82 { DEFBOOL
, "DefBool" },
84 { DEFDATE
, "DefDate" },
95 { TDOUBLE
, "Double" },
100 { ENDENUM
, "End Enum" },
101 { ENDFUNC
, "End Function" },
103 { ENDPROPERTY
, "End Property" },
104 { ENDSELECT
,"End Select" },
105 { ENDSUB
, "End Sub" },
106 { ENDTYPE
, "End Type" },
111 { _ERROR_
, "Error" },
113 { EXPLICIT
, "Explicit" },
115 { FUNCTION
, "Function" },
117 { GLOBAL
, "Global" },
122 { IMPLEMENTS
, "Implements" },
124 { INPUT
, "Input" }, // auch INPUT #
125 { TINTEGER
, "Integer" },
131 { LINEINPUT
,"Line Input" },
136 { LPRINT
, "LPrint" },
137 { LSET
, "LSet" }, // JSM
143 { TOBJECT
, "Object" },
146 { OPTION
, "Option" },
147 { _OPTIONAL_
, "Optional" },
149 { OUTPUT
, "Output" },
150 { PARAMARRAY
, "ParamArray" },
151 { PRESERVE
, "Preserve" },
153 { PRIVATE
, "Private" },
154 { PROPERTY
, "Property" },
155 { PUBLIC
, "Public" },
156 { RANDOM
, "Random" },
160 { RESUME
, "Resume" },
161 { RETURN
, "Return" },
162 { RSET
, "RSet" }, // JSM
163 { SELECT
, "Select" },
169 { SHARED
, "Shared" },
174 { TSINGLE
, "Single" },
175 { STATIC
, "Static" },
178 { TSTRING
, "String" },
185 { TYPEOF
, "TypeOf" },
187 { TVARIANT
, "Variant" },
188 { VBASUPPORT
, "VbaSupport" },
192 { WRITE
, "Write" }, // auch WRITE #
198 TokenTable aTokTable_Java [] = { // Token-Tabelle:
203 { JS_ASS_MOD, "%=" },
205 { JS_LOG_AND, "&&" },
206 { JS_ASS_AND, "&=" },
210 { JS_ASS_MUL, "*=" },
213 { JS_ASS_PLUS, "+=" },
217 { JS_ASS_MINUS, "-=" },
219 { JS_ASS_DIV, "/=" },
220 { JS_COND_SEL, ":" },
223 { JS_ASS_LSHIFT,"<<=" },
226 { JS_ASSIGNMENT,"=" },
230 { JS_ASS_RSHIFT,">>=" },
231 { JS_RSHIFT_Z, ">>>" },
232 { JS_ASS_RSHIFT_Z,">>>=" },
234 { JS_COND_QUEST,"?" },
235 { ACCESS, "Access" },
239 { APPEND, "Append" },
242 { BINARY, "Binary" },
243 { TBOOLEAN, "Boolean" },
247 { _CDECL_, "Cdecl" },
249 { COMPARE, "Compare" },
250 { _CONST_, "Const" },
251 { TCURRENCY,"Currency" },
253 { DECLARE, "Declare" },
254 { DEFBOOL, "DefBool" },
255 { DEFCUR, "DefCur" },
256 { DEFDATE, "DefDate" },
257 { DEFDBL, "DefDbl" },
258 { DEFERR, "DefErr" },
259 { DEFINT, "DefInt" },
260 { DEFLNG, "DefLng" },
261 { DEFOBJ, "DefObj" },
262 { DEFSNG, "DefSng" },
263 { DEFSTR, "DefStr" },
264 { DEFVAR, "DefVar" },
267 { TDOUBLE, "Double" },
270 { ELSEIF, "ElseIf" },
272 { ENDFUNC, "End Function" },
274 { ENDSELECT,"End Select" },
275 { ENDSUB, "End Sub" },
276 { ENDTYPE, "End Type" },
280 { _ERROR_, "Error" },
282 { EXPLICIT, "Explicit" },
284 { FUNCTION, "Function" },
285 { GLOBAL, "Global" },
291 { INPUT, "Input" }, // auch INPUT #
292 { TINTEGER, "Integer" },
297 { LINEINPUT,"Line Input" },
302 { LPRINT, "LPrint" },
303 { LSET, "LSet" }, // JSM
309 { TOBJECT, "Object" },
312 { OPTION, "Option" },
313 { _OPTIONAL_, "Optional" },
315 { OUTPUT, "Output" },
316 { PRESERVE, "Preserve" },
318 { PRIVATE, "Private" },
319 { PUBLIC, "Public" },
320 { RANDOM, "Random" },
324 { RESUME, "Resume" },
325 { RETURN, "Return" },
326 { RSET, "RSet" }, // JSM
327 { SELECT, "Select" },
329 { SHARED, "Shared" },
330 { TSINGLE, "Single" },
331 { STATIC, "Static" },
334 { TSTRING, "String" },
342 { TVARIANT, "Variant" },
346 { WRITE, "Write" }, // auch WRITE #
351 { JS_ASS_XOR, "^=" },
360 // Der Konstruktor ermittelt die Laenge der Token-Tabelle.
362 SbiTokenizer::SbiTokenizer( const ::rtl::OUString
& rSrc
, StarBASIC
* pb
)
363 : SbiScanner( rSrc
, pb
)
365 pTokTable
= aTokTable_Basic
;
366 //if( StarBASIC::GetGlobalLanguageMode() == SB_LANG_JAVASCRIPT )
367 // pTokTable = aTokTable_Java;
372 bEos
= bKeywords
= bErrorIsSymbol
= TRUE
;
374 for( nToken
= 0, tp
= pTokTable
; tp
->t
; nToken
++, tp
++ ) {}
377 SbiTokenizer::~SbiTokenizer()
380 // Wiederablage (Pushback) eines Tokens. (Bis zu 2 Tokens)
382 void SbiTokenizer::Push( SbiToken t
)
385 Error( SbERR_INTERNAL_ERROR
, "PUSH" );
389 void SbiTokenizer::Error( SbError code
, const char* pMsg
)
391 aError
= String::CreateFromAscii( pMsg
);
395 void SbiTokenizer::Error( SbError code
, String aMsg
)
401 void SbiTokenizer::Error( SbError code
, SbiToken tok
)
403 aError
= Symbol( tok
);
407 // Einlesen des naechsten Tokens, ohne dass das Token geschluckt wird
409 SbiToken
SbiTokenizer::Peek()
413 USHORT nOldLine
= nLine
;
414 USHORT nOldCol1
= nCol1
;
415 USHORT nOldCol2
= nCol2
;
417 nPLine
= nLine
; nLine
= nOldLine
;
418 nPCol1
= nCol1
; nCol1
= nOldCol1
;
419 nPCol2
= nCol2
; nCol2
= nOldCol2
;
421 return eCurTok
= ePush
;
424 // Dies ist fuer die Decompilation.
425 // Zahlen und Symbole liefern einen Leerstring zurueck.
427 const String
& SbiTokenizer::Symbol( SbiToken t
)
437 case NEG
: aSym
= '-'; return aSym
;
438 case EOS
: aSym
= String::CreateFromAscii( ":/CRLF" ); return aSym
;
439 case EOLN
: aSym
= String::CreateFromAscii( "CRLF" ); return aSym
;
442 TokenTable
* tp
= pTokTable
;
443 for( short i
= 0; i
< nToken
; i
++, tp
++ )
447 aSym
= String::CreateFromAscii( tp
->s
);
451 const sal_Unicode
*p
= aSym
.GetBuffer();
452 if (*p
<= ' ') aSym
= String::CreateFromAscii( "???" );
456 // Einlesen des naechsten Tokens und Ablage desselben
457 // Tokens, die nicht in der Token-Tabelle vorkommen, werden
458 // direkt als Zeichen zurueckgeliefert.
459 // Einige Worte werden gesondert behandelt.
461 SbiToken
SbiTokenizer::Next()
463 if (bEof
) return EOLN
;
464 // Schon eines eingelesen?
472 bEos
= IsEoln( eCurTok
);
481 return eCurTok
= EOLN
;
484 if( aSym
.GetBuffer()[0] == '\n' )
486 bEos
= TRUE
; return eCurTok
= EOLN
;
492 return eCurTok
= NUMBER
;
495 else if( ( eScanType
== SbxDATE
|| eScanType
== SbxSTRING
) && !bSymbol
)
496 return eCurTok
= FIXSTRING
;
497 // Sonderfaelle von Zeichen, die zwischen "Z" und "a" liegen. ICompare()
498 // wertet die Position dieser Zeichen unterschiedlich aus.
499 else if( aSym
.GetBuffer()[0] == '^' )
500 return eCurTok
= EXPON
;
501 else if( aSym
.GetBuffer()[0] == '\\' )
502 return eCurTok
= IDIV
;
505 // Mit Typkennung oder ein Symbol und keine Keyword-Erkennung?
506 // Dann kein Token-Test
507 if( eScanType
!= SbxVARIANT
508 || ( !bKeywords
&& bSymbol
) )
509 return eCurTok
= SYMBOL
;
516 delta
= (ub
- lb
) >> 1;
517 tp
= &pTokTable
[ lb
+ delta
];
518 StringCompare res
= aSym
.CompareIgnoreCaseToAscii( tp
->s
);
520 if( res
== COMPARE_EQUAL
) goto special
;
521 // Groesser? Dann untere Haelfte
522 if( res
== COMPARE_LESS
)
524 if ((ub
- lb
) == 2) ub
= lb
;
525 else ub
= ub
- delta
;
527 // Kleiner? Dann obere Haelfte
530 if ((ub
-lb
) == 2) lb
= ub
;
531 else lb
= lb
+ delta
;
534 // Symbol? Wenn nicht >= Token
535 sal_Unicode ch
= aSym
.GetBuffer()[0];
536 if( !BasicSimpleCharClass::isAlpha( ch
, bCompatible
) && !bSymbol
)
537 return eCurTok
= (SbiToken
) (ch
& 0x00FF);
538 return eCurTok
= SYMBOL
;
545 String aOldSym
= aSym
;
547 if( eCurTok
== INPUT
)
551 return eCurTok
= LINEINPUT
;
556 return eCurTok
= LINE
;
559 // END IF, CASE, SUB, DEF, FUNCTION, TYPE, CLASS, WITH
562 // AB, 15.3.96, Spezialbehandlung fuer END, beim Peek() geht die
563 // aktuelle Zeile verloren, daher alles merken und danach restaurieren
564 USHORT nOldLine
= nLine
;
565 USHORT nOldCol
= nCol
;
566 USHORT nOldCol1
= nCol1
;
567 USHORT nOldCol2
= nCol2
;
568 String aOldSym
= aSym
;
569 SaveLine(); // pLine im Scanner sichern
574 case IF
: Next(); eCurTok
= ENDIF
; break;
575 case SELECT
: Next(); eCurTok
= ENDSELECT
; break;
576 case SUB
: Next(); eCurTok
= ENDSUB
; break;
577 case FUNCTION
: Next(); eCurTok
= ENDFUNC
; break;
578 case PROPERTY
: Next(); eCurTok
= ENDPROPERTY
; break;
579 case TYPE
: Next(); eCurTok
= ENDTYPE
; break;
580 case ENUM
: Next(); eCurTok
= ENDENUM
; break;
581 case WITH
: Next(); eCurTok
= ENDWITH
; break;
582 default : eCurTok
= END
;
587 // Alles zuruecksetzen, damit Token nach END ganz neu gelesen wird
593 RestoreLine(); // pLine im Scanner restaurieren
598 // check whether the keyword has been dim as a variable
599 if( IsSymbol( tp
->t
) )
601 return eCurTok
= SYMBOL
;
604 // Sind Datentypen Keywords?
605 // Nur nach AS, sonst sind es Symbole!
606 // Es gibt ja ERROR(), DATA(), STRING() etc.
608 // AS: Datentypen sind Keywords
615 else if( eCurTok
>= DATATYPE1
&& eCurTok
<= DATATYPE2
&& (bErrorIsSymbol
|| eCurTok
!= _ERROR_
) )
619 // CLASSMODULE, PROPERTY, GET, ENUM token only visible in compatible mode
620 SbiToken eTok
= tp
->t
;
623 // #129904 Suppress system
624 if( eTok
== STOP
&& aSym
.CompareIgnoreCaseToAscii( "system" ) == COMPARE_EQUAL
)
629 if( eTok
== CLASSMODULE
||
630 eTok
== IMPLEMENTS
||
631 eTok
== PARAMARRAY
||
641 bEos
= IsEoln( eCurTok
);
646 #pragma optimize("",off)
649 // Kann das aktuell eingelesene Token ein Label sein?
651 BOOL
SbiTokenizer::MayBeLabel( BOOL bNeedsColon
)
653 if( eCurTok
== SYMBOL
)
654 return bNeedsColon
? DoesColonFollow() : TRUE
;
656 return BOOL( eCurTok
== NUMBER
657 && eScanType
== SbxINTEGER
662 #pragma optimize("",off)
666 void SbiTokenizer::Hilite( SbTextPortions
& rList
)
669 bUsedForHilite
= TRUE
;
670 SbiToken eLastTok
= NIL
;
683 aRes
.eType
= SB_COMMENT
; break;
685 aRes
.eType
= SB_SYMBOL
; break;
687 aRes
.eType
= SB_STRING
; break;
689 aRes
.eType
= SB_NUMBER
; break;
691 if( ( eCurTok
>= FIRSTKWD
&& eCurTok
<= LASTKWD
)
692 || (eCurTok
>= _CDECL_
) )
693 aRes
.eType
= SB_KEYWORD
;
695 aRes
.eType
= SB_PUNCTUATION
;
697 // Die Folge xxx.Keyword sollte nicht als Kwd geflagt werden
698 if( aRes
.eType
== SB_KEYWORD
699 && ( eLastTok
== DOT
|| eLastTok
== EXCLAM
) )
700 aRes
.eType
= SB_SYMBOL
;
701 if( eCurTok
!= EOLN
&& aRes
.nStart
<= aRes
.nEnd
)
702 rList
.Insert( aRes
, rList
.Count() );
703 if( aRes
.eType
== SB_COMMENT
)
707 bUsedForHilite
= FALSE
;