1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "basiccharclass.hxx"
24 struct TokenTable
{ SbiToken t
; const char *s
; };
26 static short nToken
; // number of tokens
28 static TokenTable
* pTokTable
;
30 static TokenTable aTokTable_Basic
[] = {
50 { ATTRIBUTE
,"Attribute" },
53 { TBOOLEAN
, "Boolean" },
60 { CLASSMODULE
, "ClassModule" },
62 { COMPARE
, "Compare" },
63 { COMPATIBLE
,"Compatible" },
65 { TCURRENCY
,"Currency" },
67 { DECLARE
, "Declare" },
68 { DEFBOOL
, "DefBool" },
70 { DEFDATE
, "DefDate" },
81 { TDOUBLE
, "Double" },
86 { ENDENUM
, "End Enum" },
87 { ENDFUNC
, "End Function" },
89 { ENDPROPERTY
, "End Property" },
90 { ENDSELECT
,"End Select" },
91 { ENDSUB
, "End Sub" },
92 { ENDTYPE
, "End Type" },
99 { EXPLICIT
, "Explicit" },
101 { FUNCTION
, "Function" },
103 { GLOBAL
, "Global" },
108 { IMPLEMENTS
, "Implements" },
110 { INPUT
, "Input" }, // also INPUT #
111 { TINTEGER
, "Integer" },
117 { LINEINPUT
,"Line Input" },
122 { LPRINT
, "LPrint" },
123 { LSET
, "LSet" }, // JSM
129 { TOBJECT
, "Object" },
132 { OPTION
, "Option" },
133 { _OPTIONAL_
, "Optional" },
135 { OUTPUT
, "Output" },
136 { PARAMARRAY
, "ParamArray" },
137 { PRESERVE
, "Preserve" },
139 { PRIVATE
, "Private" },
140 { PROPERTY
, "Property" },
141 { PUBLIC
, "Public" },
142 { RANDOM
, "Random" },
146 { RESUME
, "Resume" },
147 { RETURN
, "Return" },
148 { RSET
, "RSet" }, // JSM
149 { SELECT
, "Select" },
155 { SHARED
, "Shared" },
160 { TSINGLE
, "Single" },
161 { STATIC
, "Static" },
164 { TSTRING
, "String" },
171 { TYPEOF
, "TypeOf" },
173 { TVARIANT
, "Variant" },
174 { VBASUPPORT
, "VbaSupport" },
178 { WITHEVENTS
, "WithEvents" },
179 { WRITE
, "Write" }, // also WRITE #
186 TokenLabelInfo::TokenLabelInfo( void )
188 m_pTokenCanBeLabelTab
= new bool[VBASUPPORT
+1];
189 for( int i
= 0 ; i
<= VBASUPPORT
; ++i
)
191 m_pTokenCanBeLabelTab
[i
] = false;
193 // Token accepted as label by VBA
194 SbiToken eLabelToken
[] = { ACCESS
, ALIAS
, APPEND
, BASE
, BINARY
, CLASSMODULE
,
195 COMPARE
, COMPATIBLE
, DEFERR
, _ERROR_
, EXPLICIT
, LIB
, LINE
, LPRINT
, NAME
,
196 TOBJECT
, OUTPUT
, PROPERTY
, RANDOM
, READ
, STEP
, STOP
, TEXT
, VBASUPPORT
, NIL
};
197 SbiToken
* pTok
= eLabelToken
;
199 for( pTok
= eLabelToken
; (eTok
= *pTok
) != NIL
; ++pTok
)
201 m_pTokenCanBeLabelTab
[eTok
] = true;
205 TokenLabelInfo::~TokenLabelInfo()
207 delete[] m_pTokenCanBeLabelTab
;
211 // the constructor detects the length of the token table
213 SbiTokenizer::SbiTokenizer( const ::rtl::OUString
& rSrc
, StarBASIC
* pb
)
214 : SbiScanner( rSrc
, pb
)
216 pTokTable
= aTokTable_Basic
;
221 bEos
= bKeywords
= bErrorIsSymbol
= true;
224 for( nToken
= 0, tp
= pTokTable
; tp
->t
; nToken
++, tp
++ )
229 SbiTokenizer::~SbiTokenizer()
234 void SbiTokenizer::Push( SbiToken t
)
237 Error( SbERR_INTERNAL_ERROR
, "PUSH" );
241 void SbiTokenizer::Error( SbError code
, const char* pMsg
)
243 aError
= ::rtl::OUString::createFromAscii( pMsg
);
247 void SbiTokenizer::Error( SbError code
, const ::rtl::OUString
&aMsg
)
253 void SbiTokenizer::Error( SbError code
, SbiToken tok
)
255 aError
= Symbol( tok
);
259 // reading in the next token without absorbing it
261 SbiToken
SbiTokenizer::Peek()
265 sal_uInt16 nOldLine
= nLine
;
266 sal_uInt16 nOldCol1
= nCol1
;
267 sal_uInt16 nOldCol2
= nCol2
;
269 nPLine
= nLine
; nLine
= nOldLine
;
270 nPCol1
= nCol1
; nCol1
= nOldCol1
;
271 nPCol2
= nCol2
; nCol2
= nOldCol2
;
273 return eCurTok
= ePush
;
276 // For decompilation. Numbers and symbols return an empty string.
278 const ::rtl::OUString
& SbiTokenizer::Symbol( SbiToken t
)
283 aSym
= ::rtl::OUString::valueOf(sal::static_int_cast
<sal_Unicode
>(t
));
289 aSym
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-"));
292 aSym
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":/CRLF"));
295 aSym
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CRLF"));
300 TokenTable
* tp
= pTokTable
;
301 for( short i
= 0; i
< nToken
; i
++, tp
++ )
305 aSym
= ::rtl::OStringToOUString(tp
->s
, RTL_TEXTENCODING_ASCII_US
);
309 const sal_Unicode
*p
= aSym
.getStr();
312 aSym
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("???"));
317 // Reading in the next token and put it down.
318 // Tokens that don't appear in the token table
319 // are directly returned as a character.
320 // Some words are treated in a special way.
322 SbiToken
SbiTokenizer::Next()
328 // have read in one already?
336 bEos
= IsEoln( eCurTok
);
344 return eCurTok
= EOLN
;
347 if( aSym
[0] == '\n' )
349 bEos
= true; return eCurTok
= EOLN
;
355 return eCurTok
= NUMBER
;
357 else if( ( eScanType
== SbxDATE
|| eScanType
== SbxSTRING
) && !bSymbol
)
359 return eCurTok
= FIXSTRING
;
361 // Special cases of characters that are between "Z" and "a". ICompare()
362 // evaluates the position of these characters in different ways.
363 else if( aSym
[0] == '^' )
365 return eCurTok
= EXPON
;
367 else if( aSym
[0] == '\\' )
369 return eCurTok
= IDIV
;
373 if( eScanType
!= SbxVARIANT
374 || ( !bKeywords
&& bSymbol
) )
375 return eCurTok
= SYMBOL
;
382 delta
= (ub
- lb
) >> 1;
383 tp
= &pTokTable
[ lb
+ delta
];
384 sal_Int32 res
= aSym
.compareToIgnoreAsciiCaseAscii( tp
->s
);
414 // Symbol? if not >= token
415 sal_Unicode ch
= aSym
[0];
416 if( !theBasicCharClass::get().isAlpha( ch
, bCompatible
) && !bSymbol
)
418 return eCurTok
= (SbiToken
) (ch
& 0x00FF);
420 return eCurTok
= SYMBOL
;
424 bool bStartOfLine
= (eCurTok
== NIL
|| eCurTok
== REM
|| eCurTok
== EOLN
);
425 if( !bStartOfLine
&& (tp
->t
== NAME
|| tp
->t
== LINE
) )
427 return eCurTok
= SYMBOL
;
429 else if( tp
->t
== TEXT
)
431 return eCurTok
= SYMBOL
;
433 // maybe we can expand this for other statements that have parameters
434 // that are keywords ( and those keywords are only used within such
436 // what's happening here is that if we come across 'append' ( and we are
437 // not in the middle of parsing a special statement ( like 'Open')
438 // we just treat keyword 'append' as a normal 'SYMBOL'.
439 // Also we accept Dim APPEND
440 else if ( ( !bInStatement
|| eCurTok
== DIM
) && tp
->t
== APPEND
)
442 return eCurTok
= SYMBOL
;
444 // #i92642: Special LINE token handling -> SbiParser::Line()
446 // END IF, CASE, SUB, DEF, FUNCTION, TYPE, CLASS, WITH
449 // from 15.3.96, special treatment for END, at Peek() the current
450 // time is lost, so memorize everything and restore after
451 sal_uInt16 nOldLine
= nLine
;
452 sal_uInt16 nOldCol
= nCol
;
453 sal_uInt16 nOldCol1
= nCol1
;
454 sal_uInt16 nOldCol2
= nCol2
;
455 OUString aOldSym
= aSym
;
456 SaveLine(); // save pLine in the scanner
461 case IF
: Next(); eCurTok
= ENDIF
; break;
462 case SELECT
: Next(); eCurTok
= ENDSELECT
; break;
463 case SUB
: Next(); eCurTok
= ENDSUB
; break;
464 case FUNCTION
: Next(); eCurTok
= ENDFUNC
; break;
465 case PROPERTY
: Next(); eCurTok
= ENDPROPERTY
; break;
466 case TYPE
: Next(); eCurTok
= ENDTYPE
; break;
467 case ENUM
: Next(); eCurTok
= ENDENUM
; break;
468 case WITH
: Next(); eCurTok
= ENDWITH
; break;
469 default : eCurTok
= END
; break;
474 // reset everything so that token is read completely newly after END
484 // are data types keywords?
485 // there is ERROR(), DATA(), STRING() etc.
487 // AS: data types are keywords
498 else if( eCurTok
>= DATATYPE1
&& eCurTok
<= DATATYPE2
&& (bErrorIsSymbol
|| eCurTok
!= _ERROR_
) )
504 // CLASSMODULE, PROPERTY, GET, ENUM token only visible in compatible mode
505 SbiToken eTok
= tp
->t
;
508 // #129904 Suppress system
509 if( eTok
== STOP
&& aSym
.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("system")) )
513 if( eTok
== GET
&& bStartOfLine
)
520 if( eTok
== CLASSMODULE
||
521 eTok
== IMPLEMENTS
||
522 eTok
== PARAMARRAY
||
532 bEos
= IsEoln( eCurTok
);
537 #pragma optimize("",off)
541 bool SbiTokenizer::MayBeLabel( bool bNeedsColon
)
543 if( eCurTok
== SYMBOL
|| m_aTokenLabelInfo
.canTokenBeLabel( eCurTok
) )
545 return bNeedsColon
? DoesColonFollow() : true;
549 return ( eCurTok
== NUMBER
550 && eScanType
== SbxINTEGER
556 #pragma optimize("",off)
560 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */