Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include <basic/sbx.hxx>
21 : : #include "sbcomp.hxx"
22 : : #include <com/sun/star/script/ModuleType.hpp>
23 : :
24 : : struct SbiParseStack { // "Stack" for statement-blocks
25 : : SbiParseStack* pNext; // Chain
26 : : SbiExprNode* pWithVar;
27 : : SbiToken eExitTok;
28 : : sal_uInt32 nChain; // JUMP-Chain
29 : : };
30 : :
31 : : struct SbiStatement {
32 : : SbiToken eTok;
33 : : void( SbiParser::*Func )();
34 : : sal_Bool bMain; // sal_True: OK outside the SUB
35 : : sal_Bool bSubr; // sal_True: OK inside the SUB
36 : : };
37 : :
38 : : #define Y sal_True
39 : : #define N sal_False
40 : :
41 : : static SbiStatement StmntTable [] = {
42 : : { ATTRIBUTE, &SbiParser::Attribute, Y, Y, }, // ATTRIBUTE
43 : : { CALL, &SbiParser::Call, N, Y, }, // CALL
44 : : { CLOSE, &SbiParser::Close, N, Y, }, // CLOSE
45 : : { _CONST_, &SbiParser::Dim, Y, Y, }, // CONST
46 : : { DECLARE, &SbiParser::Declare, Y, N, }, // DECLARE
47 : : { DEFBOOL, &SbiParser::DefXXX, Y, N, }, // DEFBOOL
48 : : { DEFCUR, &SbiParser::DefXXX, Y, N, }, // DEFCUR
49 : : { DEFDATE, &SbiParser::DefXXX, Y, N, }, // DEFDATE
50 : : { DEFDBL, &SbiParser::DefXXX, Y, N, }, // DEFDBL
51 : : { DEFERR, &SbiParser::DefXXX, Y, N, }, // DEFERR
52 : : { DEFINT, &SbiParser::DefXXX, Y, N, }, // DEFINT
53 : : { DEFLNG, &SbiParser::DefXXX, Y, N, }, // DEFLNG
54 : : { DEFOBJ, &SbiParser::DefXXX, Y, N, }, // DEFOBJ
55 : : { DEFSNG, &SbiParser::DefXXX, Y, N, }, // DEFSNG
56 : : { DEFSTR, &SbiParser::DefXXX, Y, N, }, // DEFSTR
57 : : { DEFVAR, &SbiParser::DefXXX, Y, N, }, // DEFVAR
58 : : { DIM, &SbiParser::Dim, Y, Y, }, // DIM
59 : : { DO, &SbiParser::DoLoop, N, Y, }, // DO
60 : : { ELSE, &SbiParser::NoIf, N, Y, }, // ELSE
61 : : { ELSEIF, &SbiParser::NoIf, N, Y, }, // ELSEIF
62 : : { ENDIF, &SbiParser::NoIf, N, Y, }, // ENDIF
63 : : { END, &SbiParser::Stop, N, Y, }, // END
64 : : { ENUM, &SbiParser::Enum, Y, N, }, // TYPE
65 : : { ERASE, &SbiParser::Erase, N, Y, }, // ERASE
66 : : { _ERROR_, &SbiParser::ErrorStmnt, N, Y, }, // ERROR
67 : : { EXIT, &SbiParser::Exit, N, Y, }, // EXIT
68 : : { FOR, &SbiParser::For, N, Y, }, // FOR
69 : : { FUNCTION, &SbiParser::SubFunc, Y, N, }, // FUNCTION
70 : : { GOSUB, &SbiParser::Goto, N, Y, }, // GOSUB
71 : : { GLOBAL, &SbiParser::Dim, Y, N, }, // GLOBAL
72 : : { GOTO, &SbiParser::Goto, N, Y, }, // GOTO
73 : : { IF, &SbiParser::If, N, Y, }, // IF
74 : : { IMPLEMENTS, &SbiParser::Implements, Y, N, }, // IMPLEMENTS
75 : : { INPUT, &SbiParser::Input, N, Y, }, // INPUT
76 : : { LET, &SbiParser::Assign, N, Y, }, // LET
77 : : { LINE, &SbiParser::Line, N, Y, }, // LINE, -> LINE INPUT (#i92642)
78 : : { LINEINPUT,&SbiParser::LineInput, N, Y, }, // LINE INPUT
79 : : { LOOP, &SbiParser::BadBlock, N, Y, }, // LOOP
80 : : { LSET, &SbiParser::LSet, N, Y, }, // LSET
81 : : { NAME, &SbiParser::Name, N, Y, }, // NAME
82 : : { NEXT, &SbiParser::BadBlock, N, Y, }, // NEXT
83 : : { ON, &SbiParser::On, N, Y, }, // ON
84 : : { OPEN, &SbiParser::Open, N, Y, }, // OPEN
85 : : { OPTION, &SbiParser::Option, Y, N, }, // OPTION
86 : : { PRINT, &SbiParser::Print, N, Y, }, // PRINT
87 : : { PRIVATE, &SbiParser::Dim, Y, N, }, // PRIVATE
88 : : { PROPERTY, &SbiParser::SubFunc, Y, N, }, // FUNCTION
89 : : { PUBLIC, &SbiParser::Dim, Y, N, }, // PUBLIC
90 : : { REDIM, &SbiParser::ReDim, N, Y, }, // DIM
91 : : { RESUME, &SbiParser::Resume, N, Y, }, // RESUME
92 : : { RETURN, &SbiParser::Return, N, Y, }, // RETURN
93 : : { RSET, &SbiParser::RSet, N, Y, }, // RSET
94 : : { SELECT, &SbiParser::Select, N, Y, }, // SELECT
95 : : { SET, &SbiParser::Set, N, Y, }, // SET
96 : : { STATIC, &SbiParser::Static, Y, Y, }, // STATIC
97 : : { STOP, &SbiParser::Stop, N, Y, }, // STOP
98 : : { SUB, &SbiParser::SubFunc, Y, N, }, // SUB
99 : : { TYPE, &SbiParser::Type, Y, N, }, // TYPE
100 : : { UNTIL, &SbiParser::BadBlock, N, Y, }, // UNTIL
101 : : { WHILE, &SbiParser::While, N, Y, }, // WHILE
102 : : { WEND, &SbiParser::BadBlock, N, Y, }, // WEND
103 : : { WITH, &SbiParser::With, N, Y, }, // WITH
104 : : { WRITE, &SbiParser::Write, N, Y, }, // WRITE
105 : :
106 : : { NIL, NULL, N, N }
107 : : };
108 : :
109 : :
110 : : #ifdef _MSC_VER
111 : : // 'this' : used in base member initializer list
112 : : #pragma warning( disable: 4355 )
113 : : #endif
114 : :
115 : 65 : SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
116 : 65 : : SbiTokenizer( pm->GetSource32(), pb ),
117 : : aGblStrings( this ),
118 : : aLclStrings( this ),
119 : : aGlobals( aGblStrings, SbGLOBAL ),
120 : : aPublics( aGblStrings, SbPUBLIC ),
121 : : aRtlSyms( aGblStrings, SbRTL ),
122 [ + - ][ + - ]: 65 : aGen( *pm, this, 1024 )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
123 : : {
124 : 65 : pBasic = pb;
125 : 65 : eCurExpr = SbSYMBOL;
126 : 65 : eEndTok = NIL;
127 : 65 : pProc = NULL;
128 : 65 : pStack = NULL;
129 : 65 : pWithVar = NULL;
130 : 65 : nBase = 0;
131 : : bText =
132 : : bGblDefs =
133 : : bNewGblDefs =
134 : : bSingleLineIf =
135 : 65 : bExplicit = false;
136 : 65 : bClassModule = ( pm->GetModuleType() == com::sun::star::script::ModuleType::CLASS );
137 : : OSL_TRACE("Parser - %s, bClassModule %d", rtl::OUStringToOString( pm->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), bClassModule );
138 : 65 : pPool = &aPublics;
139 [ + + ]: 1755 : for( short i = 0; i < 26; i++ )
140 : 1690 : eDefTypes[ i ] = SbxVARIANT; // no explicit default type
141 : :
142 : 65 : aPublics.SetParent( &aGlobals );
143 : 65 : aGlobals.SetParent( &aRtlSyms );
144 : :
145 : :
146 [ + - ]: 65 : nGblChain = aGen.Gen( _JUMP, 0 );
147 : :
148 [ + - ][ + - ]: 65 : rTypeArray = new SbxArray; // array for user defined types
[ + - ]
149 [ + - ][ + - ]: 65 : rEnumArray = new SbxArray; // array for Enum types
[ + - ]
150 [ + - ]: 65 : bVBASupportOn = pm->IsVBACompat();
151 [ + + ]: 65 : if ( bVBASupportOn )
152 [ + - ]: 29 : EnableCompatibility();
153 : :
154 : 65 : }
155 : :
156 : :
157 : : // part of the runtime-library?
158 : 1255 : SbiSymDef* SbiParser::CheckRTLForSym( const String& rSym, SbxDataType eType )
159 : : {
160 [ + - ]: 1255 : SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
161 : 1255 : SbiSymDef* pDef = NULL;
162 [ + + ]: 1255 : if( pVar )
163 : : {
164 [ + + ]: 110 : if( pVar->IsA( TYPE(SbxMethod) ) )
165 : : {
166 : 80 : SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
167 : 80 : pProc_->SetType( pVar->GetType() );
168 : 80 : pDef = pProc_;
169 : : }
170 : : else
171 : : {
172 : 30 : pDef = aRtlSyms.AddSym( rSym );
173 : 30 : pDef->SetType( eType );
174 : : }
175 : : }
176 : 1255 : return pDef;
177 : : }
178 : :
179 : : // close global chain
180 : :
181 : 65 : bool SbiParser::HasGlobalCode()
182 : : {
183 [ + + ][ + - ]: 65 : if( bGblDefs && nGblChain )
184 : : {
185 : 8 : aGen.BackChain( nGblChain );
186 : 8 : aGen.Gen( _LEAVE );
187 : 8 : nGblChain = 0;
188 : : }
189 : 65 : return bGblDefs;
190 : : }
191 : :
192 : 233 : void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
193 : : {
194 : 233 : SbiParseStack* p = new SbiParseStack;
195 : 233 : p->eExitTok = eTok;
196 : 233 : p->nChain = 0;
197 : 233 : p->pWithVar = pWithVar;
198 : 233 : p->pNext = pStack;
199 : 233 : pStack = p;
200 : 233 : pWithVar = pVar;
201 : :
202 : : // #29955 service the for-loop level
203 [ + + ]: 233 : if( eTok == FOR )
204 : 36 : aGen.IncForLevel();
205 : 233 : }
206 : :
207 : 233 : void SbiParser::CloseBlock()
208 : : {
209 [ + - ]: 233 : if( pStack )
210 : : {
211 : 233 : SbiParseStack* p = pStack;
212 : :
213 : : // #29955 service the for-loop level
214 [ + + ]: 233 : if( p->eExitTok == FOR )
215 : 36 : aGen.DecForLevel();
216 : :
217 : 233 : aGen.BackChain( p->nChain );
218 : 233 : pStack = p->pNext;
219 : 233 : pWithVar = p->pWithVar;
220 : 233 : delete p;
221 : : }
222 : 233 : }
223 : :
224 : : // EXIT ...
225 : :
226 : 44 : void SbiParser::Exit()
227 : : {
228 : 44 : SbiToken eTok = Next();
229 [ + - ]: 44 : for( SbiParseStack* p = pStack; p; p = p->pNext )
230 : : {
231 : 44 : SbiToken eExitTok = p->eExitTok;
232 [ - + ][ # # ]: 44 : if( eTok == eExitTok ||
[ # # ][ # # ]
233 : : (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) ) // #i109051
234 : : {
235 : 44 : p->nChain = aGen.Gen( _JUMP, p->nChain );
236 : 44 : return;
237 : : }
238 : : }
239 [ # # ]: 0 : if( pStack )
240 : 0 : Error( SbERR_EXPECTED, pStack->eExitTok );
241 : : else
242 : 0 : Error( SbERR_BAD_EXIT );
243 : : }
244 : :
245 : 897 : bool SbiParser::TestSymbol( bool bKwdOk )
246 : : {
247 : 897 : Peek();
248 [ # # ][ # # ]: 897 : if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
[ + - ][ - + ]
249 : : {
250 : 897 : Next(); return true;
251 : : }
252 : 0 : Error( SbERR_SYMBOL_EXPECTED );
253 : 897 : return false;
254 : : }
255 : :
256 : :
257 : :
258 : 1800 : bool SbiParser::TestToken( SbiToken t )
259 : : {
260 [ + - ]: 1800 : if( Peek() == t )
261 : : {
262 : 1800 : Next(); return true;
263 : : }
264 : : else
265 : : {
266 : 0 : Error( SbERR_EXPECTED, t );
267 : 1800 : return false;
268 : : }
269 : : }
270 : :
271 : :
272 : :
273 : 572 : bool SbiParser::TestComma()
274 : : {
275 : 572 : SbiToken eTok = Peek();
276 [ + + ]: 572 : if( IsEoln( eTok ) )
277 : : {
278 : 418 : Next();
279 : 418 : return false;
280 : : }
281 [ - + ]: 154 : else if( eTok != COMMA )
282 : : {
283 : 0 : Error( SbERR_EXPECTED, COMMA );
284 : 0 : return false;
285 : : }
286 : 154 : Next();
287 : 572 : return true;
288 : : }
289 : :
290 : :
291 : :
292 : 192 : void SbiParser::TestEoln()
293 : : {
294 [ - + ]: 192 : if( !IsEoln( Next() ) )
295 : : {
296 : 0 : Error( SbERR_EXPECTED, EOLN );
297 [ # # ]: 0 : while( !IsEoln( Next() ) ) {}
298 : : }
299 : 192 : }
300 : :
301 : :
302 : :
303 : 295 : void SbiParser::StmntBlock( SbiToken eEnd )
304 : : {
305 : 295 : SbiToken xe = eEndTok;
306 : 295 : eEndTok = eEnd;
307 [ + - ][ + + ]: 4159 : while( !bAbort && Parse() ) {}
[ + + ]
308 : 295 : eEndTok = xe;
309 [ - + ]: 295 : if( IsEof() )
310 : : {
311 : 0 : Error( SbERR_BAD_BLOCK, eEnd );
312 : 0 : bAbort = sal_True;
313 : : }
314 : 295 : }
315 : :
316 : :
317 : :
318 : 6538 : bool SbiParser::Parse()
319 : : {
320 [ - + ]: 6538 : if( bAbort ) return false;
321 : :
322 : 6538 : EnableErrors();
323 : :
324 : 6538 : bErrorIsSymbol = false;
325 : 6538 : Peek();
326 : 6538 : bErrorIsSymbol = true;
327 : :
328 [ + + ]: 6538 : if( IsEof() )
329 : : {
330 : : // AB #33133: If no sub has been created before,
331 : : // the global chain must be closed here!
332 : : // AB #40689: Due to the new static-handling there
333 : : // can be another nGblChain, so ask for it before.
334 [ - + ][ # # ]: 65 : if( bNewGblDefs && nGblChain == 0 )
335 : 0 : nGblChain = aGen.Gen( _JUMP, 0 );
336 : 65 : return false;
337 : : }
338 : :
339 : :
340 [ + + ]: 6473 : if( IsEoln( eCurTok ) )
341 : : {
342 : 3406 : Next(); return true;
343 : : }
344 : :
345 [ + + ][ + + ]: 3067 : if( !bSingleLineIf && MayBeLabel( true ) )
[ + + ]
346 : : {
347 : : // is a label
348 [ - + ]: 16 : if( !pProc )
349 : 0 : Error( SbERR_NOT_IN_MAIN, aSym );
350 : : else
351 [ + - ]: 16 : pProc->GetLabels().Define( aSym );
352 : 16 : Next(); Peek();
353 : :
354 [ + - ]: 16 : if( IsEoln( eCurTok ) )
355 : : {
356 : 16 : Next(); return true;
357 : : }
358 : : }
359 : :
360 : : // end of parsing?
361 [ + + ][ + + ]: 3051 : if( eCurTok == eEndTok ||
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ][ # # ]
362 : : ( bVBASupportOn && // #i109075
363 : : (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
364 : : (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
365 : : {
366 : 295 : Next();
367 [ + - ]: 295 : if( eCurTok != NIL )
368 : 295 : aGen.Statement();
369 : 295 : return false;
370 : : }
371 : :
372 : : // comment?
373 [ - + ]: 2756 : if( eCurTok == REM )
374 : : {
375 : 0 : Next(); return true;
376 : : }
377 : :
378 : : // In vba it's possible to do Error.foobar ( even if it results in
379 : : // a runtime error
380 [ - + ][ # # ]: 2756 : if ( eCurTok == _ERROR_ && IsVBASupportOn() ) // we probably need to define a subset of keywords where this madness applies e.g. if ( IsVBASupportOn() && SymbolCanBeRedined( eCurTok ) )
[ - + ]
381 : : {
382 [ # # ]: 0 : SbiTokenizer tokens( *(SbiTokenizer*)this );
383 [ # # ]: 0 : tokens.Next();
384 [ # # ][ # # ]: 0 : if ( tokens.Peek() == DOT )
385 : : {
386 : 0 : eCurTok = SYMBOL;
387 : 0 : ePush = eCurTok;
388 [ # # ]: 0 : }
389 : : }
390 : : // if there's a symbol, it's either a variable (LET)
391 : : // or a SUB-procedure (CALL without brackets)
392 : : // DOT for assignments in the WITH-block: .A=5
393 [ + + ][ - + ]: 2756 : if( eCurTok == SYMBOL || eCurTok == DOT )
394 : : {
395 [ - + ]: 3208 : if( !pProc )
396 : 0 : Error( SbERR_EXPECTED, SUB );
397 : : else
398 : : {
399 : : // for correct line and column...
400 : 1604 : Next();
401 : 1604 : Push( eCurTok );
402 : 1604 : aGen.Statement();
403 : 1604 : Symbol();
404 : : }
405 : : }
406 : : else
407 : : {
408 : 1152 : Next();
409 : :
410 : : // statement parsers
411 : :
412 : : SbiStatement* p;
413 [ + - ]: 32371 : for( p = StmntTable; p->eTok != NIL; p++ )
414 [ + + ]: 32371 : if( p->eTok == eCurTok )
415 : 1152 : break;
416 [ + - ]: 1152 : if( p->eTok != NIL )
417 : : {
418 [ + + ][ - + ]: 1152 : if( !pProc && !p->bMain )
419 : 0 : Error( SbERR_NOT_IN_MAIN, eCurTok );
420 [ + + ][ - + ]: 1152 : else if( pProc && !p->bSubr )
421 : 0 : Error( SbERR_NOT_IN_SUBR, eCurTok );
422 : : else
423 : : {
424 : : // AB #41606/#40689: Due to the new static-handling there
425 : : // can be another nGblChain, so ask for it before.
426 [ + + ][ + - ]: 1152 : if( bNewGblDefs && nGblChain == 0 &&
[ + + ][ + + ]
[ - + ]
427 : : ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
428 : : {
429 : 8 : nGblChain = aGen.Gen( _JUMP, 0 );
430 : 8 : bNewGblDefs = false;
431 : : }
432 : : // statement-opcode at the beginning of a sub, too, please
433 [ + + ][ - + ]: 1152 : if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
[ # # ][ # # ]
[ + + ][ + + ]
[ + + ]
434 : : eCurTok == SUB || eCurTok == FUNCTION )
435 : 969 : aGen.Statement();
436 [ + - ]: 1152 : (this->*( p->Func ) )();
437 : 1152 : SbxError nSbxErr = SbxBase::GetError();
438 [ - + ]: 1152 : if( nSbxErr )
439 : 1152 : SbxBase::ResetError(), Error( (SbError)nSbxErr );
440 : : }
441 : : }
442 : : else
443 : 0 : Error( SbERR_UNEXPECTED, eCurTok );
444 : : }
445 : :
446 : : // test for the statement's end -
447 : : // might also be an ELSE, as there must not neccessary be a : before the ELSE!
448 : :
449 [ + + ]: 2756 : if( !IsEos() )
450 : : {
451 : 554 : Peek();
452 [ # # ][ - + ]: 554 : if( !IsEos() && eCurTok != ELSE )
[ - + ]
453 : : {
454 : : // if the parsing has been aborted, jump over to the ":"
455 : 0 : Error( SbERR_UNEXPECTED, eCurTok );
456 [ # # ]: 0 : while( !IsEos() ) Next();
457 : : }
458 : : }
459 : : // The parser aborts at the end, the
460 : : // next token has not been fetched yet!
461 : 6538 : return true;
462 : : }
463 : :
464 : :
465 : 0 : SbiExprNode* SbiParser::GetWithVar()
466 : : {
467 [ # # ]: 0 : if( pWithVar )
468 : 0 : return pWithVar;
469 : :
470 : 0 : SbiParseStack* p = pStack;
471 [ # # ]: 0 : while( p )
472 : : {
473 : : // LoopVar can at the moment only be for with
474 [ # # ]: 0 : if( p->pWithVar )
475 : 0 : return p->pWithVar;
476 : 0 : p = p->pNext;
477 : : }
478 : 0 : return NULL;
479 : : }
480 : :
481 : :
482 : : // assignment or subroutine call
483 : :
484 : 1604 : void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
485 : : {
486 [ + + ]: 1604 : SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
487 [ + - ]: 1604 : SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );
488 : :
489 [ + - ]: 1604 : bool bEQ = ( Peek() == EQ );
490 [ + + ][ + + ]: 1604 : if( !bEQ && bVBASupportOn && aVar.IsBracket() )
[ - + ][ - + ]
491 [ # # ]: 0 : Error( SbERR_EXPECTED, "=" );
492 : :
493 [ + + ]: 1604 : RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
494 : 1604 : bool bSpecialMidHandling = false;
495 [ + - ]: 1604 : SbiSymDef* pDef = aVar.GetRealVar();
496 [ + + ][ + - ]: 1604 : if( bEQ && pDef && pDef->GetScope() == SbRTL )
[ + - ][ - + ]
[ - + ]
497 : : {
498 [ # # ][ # # ]: 0 : String aRtlName = pDef->GetName();
499 [ # # ][ # # ]: 0 : if( aRtlName.EqualsIgnoreCaseAscii("Mid") )
500 : : {
501 : 0 : SbiExprNode* pExprNode = aVar.GetExprNode();
502 [ # # ][ # # ]: 0 : if( pExprNode && pExprNode->GetNodeType() == SbxVARVAL )
[ # # ]
503 : : {
504 : 0 : SbiExprList* pPar = pExprNode->GetParameters();
505 [ # # ]: 0 : short nParCount = pPar ? pPar->GetSize() : 0;
506 [ # # ][ # # ]: 0 : if( nParCount == 2 || nParCount == 3 )
507 : : {
508 [ # # ]: 0 : if( nParCount == 2 )
509 [ # # ][ # # ]: 0 : pPar->addExpression( new SbiExpression( this, -1, SbxLONG ) );
[ # # ]
510 : :
511 [ # # ]: 0 : TestToken( EQ );
512 [ # # ][ # # ]: 0 : pPar->addExpression( new SbiExpression( this ) );
[ # # ]
513 : :
514 : 0 : bSpecialMidHandling = true;
515 : : }
516 : : }
517 [ # # ]: 0 : }
518 : : }
519 [ + - ]: 1604 : aVar.Gen( eRecMode );
520 [ + - ]: 1604 : if( !bSpecialMidHandling )
521 : : {
522 [ + + ]: 1604 : if( !bEQ )
523 : : {
524 [ + - ]: 407 : aGen.Gen( _GET );
525 : : }
526 : : else
527 : : {
528 : : // so it must be an assignment!
529 [ + - ][ - + ]: 1197 : if( !aVar.IsLvalue() )
530 [ # # ]: 0 : Error( SbERR_LVALUE_EXPECTED );
531 [ + - ]: 1197 : TestToken( EQ );
532 [ + - ]: 1197 : SbiExpression aExpr( this );
533 [ + - ]: 1197 : aExpr.Gen();
534 : 1197 : SbiOpcode eOp = _PUT;
535 [ + - ]: 1197 : if( pDef )
536 : : {
537 [ + - ][ - + ]: 1197 : if( pDef->GetConstDef() )
538 [ # # ][ # # ]: 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
[ # # ]
539 [ + + ]: 1197 : if( pDef->GetType() == SbxOBJECT )
540 : : {
541 : 104 : eOp = _SET;
542 [ + + ]: 104 : if( pDef->GetTypeId() )
543 : : {
544 [ + - ]: 6 : aGen.Gen( _SETCLASS, pDef->GetTypeId() );
545 : 1604 : return;
546 : : }
547 : : }
548 : : }
549 [ + - ][ + - ]: 1604 : aGen.Gen( eOp );
[ + + ]
550 : : }
551 [ + - ][ + + ]: 1604 : }
552 : : }
553 : :
554 : :
555 : 0 : void SbiParser::Assign()
556 : : {
557 [ # # ]: 0 : SbiExpression aLvalue( this, SbLVALUE );
558 [ # # ]: 0 : TestToken( EQ );
559 [ # # ]: 0 : SbiExpression aExpr( this );
560 [ # # ]: 0 : aLvalue.Gen();
561 [ # # ]: 0 : aExpr.Gen();
562 : 0 : sal_uInt16 nLen = 0;
563 [ # # ]: 0 : SbiSymDef* pDef = aLvalue.GetRealVar();
564 : : {
565 [ # # ][ # # ]: 0 : if( pDef->GetConstDef() )
566 [ # # ][ # # ]: 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
[ # # ]
567 [ # # ]: 0 : nLen = aLvalue.GetRealVar()->GetLen();
568 : : }
569 [ # # ]: 0 : if( nLen )
570 [ # # ]: 0 : aGen.Gen( _PAD, nLen );
571 [ # # ][ # # ]: 0 : aGen.Gen( _PUT );
[ # # ]
572 : 0 : }
573 : :
574 : : // assignments of an object-variable
575 : :
576 : 4 : void SbiParser::Set()
577 : : {
578 [ + - ]: 4 : SbiExpression aLvalue( this, SbLVALUE );
579 : 4 : SbxDataType eType = aLvalue.GetType();
580 [ + - ][ - + ]: 4 : if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
[ + - ]
581 [ # # ]: 0 : Error( SbERR_INVALID_OBJECT );
582 [ + - ]: 4 : TestToken( EQ );
583 [ + - ]: 4 : SbiSymDef* pDef = aLvalue.GetRealVar();
584 [ + - ][ + - ]: 4 : if( pDef && pDef->GetConstDef() )
[ - + ][ - + ]
585 [ # # ][ # # ]: 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
[ # # ]
586 : :
587 [ + - ]: 4 : SbiToken eTok = Peek();
588 [ - + ]: 4 : if( eTok == NEW )
589 : : {
590 [ # # ]: 0 : Next();
591 [ # # ]: 0 : String aStr;
592 [ # # ][ # # ]: 0 : SbiSymDef* pTypeDef = new SbiSymDef( aStr );
593 [ # # ]: 0 : TypeDecl( *pTypeDef, sal_True );
594 : :
595 [ # # ]: 0 : aLvalue.Gen();
596 [ # # ]: 0 : aGen.Gen( _CREATE, pDef->GetId(), pTypeDef->GetTypeId() );
597 [ # # ][ # # ]: 0 : aGen.Gen( _SETCLASS, pDef->GetTypeId() );
598 : : }
599 : : else
600 : : {
601 [ + - ]: 4 : SbiExpression aExpr( this );
602 [ + - ]: 4 : aLvalue.Gen();
603 [ + - ]: 4 : aExpr.Gen();
604 : : // Its a good idea to distinguish between
605 : : // set someting = another &
606 : : // someting = another
607 : : // ( its necessary for vba objects where set is object
608 : : // specific and also doesn't involve processing default params )
609 [ - + ]: 4 : if( pDef->GetTypeId() )
610 : : {
611 [ # # ]: 0 : if ( bVBASupportOn )
612 [ # # ]: 0 : aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
613 : : else
614 [ # # ]: 0 : aGen.Gen( _SETCLASS, pDef->GetTypeId() );
615 : : }
616 : : else
617 : : {
618 [ + - ]: 4 : if ( bVBASupportOn )
619 [ + - ]: 4 : aGen.Gen( _VBASET );
620 : : else
621 [ # # ]: 0 : aGen.Gen( _SET );
622 [ + - ]: 4 : }
623 [ + - ]: 4 : }
624 : 4 : }
625 : :
626 : : // JSM 07.10.95
627 : 0 : void SbiParser::LSet()
628 : : {
629 [ # # ]: 0 : SbiExpression aLvalue( this, SbLVALUE );
630 [ # # ]: 0 : if( aLvalue.GetType() != SbxSTRING )
631 [ # # ]: 0 : Error( SbERR_INVALID_OBJECT );
632 [ # # ]: 0 : TestToken( EQ );
633 [ # # ]: 0 : SbiSymDef* pDef = aLvalue.GetRealVar();
634 [ # # ][ # # ]: 0 : if( pDef && pDef->GetConstDef() )
[ # # ][ # # ]
635 [ # # ][ # # ]: 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
[ # # ]
636 [ # # ]: 0 : SbiExpression aExpr( this );
637 [ # # ]: 0 : aLvalue.Gen();
638 [ # # ]: 0 : aExpr.Gen();
639 [ # # ][ # # ]: 0 : aGen.Gen( _LSET );
[ # # ]
640 : 0 : }
641 : :
642 : : // JSM 07.10.95
643 : 0 : void SbiParser::RSet()
644 : : {
645 [ # # ]: 0 : SbiExpression aLvalue( this, SbLVALUE );
646 [ # # ]: 0 : if( aLvalue.GetType() != SbxSTRING )
647 [ # # ]: 0 : Error( SbERR_INVALID_OBJECT );
648 [ # # ]: 0 : TestToken( EQ );
649 [ # # ]: 0 : SbiSymDef* pDef = aLvalue.GetRealVar();
650 [ # # ][ # # ]: 0 : if( pDef && pDef->GetConstDef() )
[ # # ][ # # ]
651 [ # # ][ # # ]: 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
[ # # ]
652 [ # # ]: 0 : SbiExpression aExpr( this );
653 [ # # ]: 0 : aLvalue.Gen();
654 [ # # ]: 0 : aExpr.Gen();
655 [ # # ][ # # ]: 0 : aGen.Gen( _RSET );
[ # # ]
656 : 0 : }
657 : :
658 : : // DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR and so on
659 : :
660 : 0 : void SbiParser::DefXXX()
661 : : {
662 : : sal_Unicode ch1, ch2;
663 : 0 : SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER );
664 : :
665 [ # # ]: 0 : while( !bAbort )
666 : : {
667 [ # # ]: 0 : if( Next() != SYMBOL ) break;
668 : 0 : ch1 = aSym.toAsciiUpperCase()[0];
669 : 0 : ch2 = 0;
670 [ # # ]: 0 : if( Peek() == MINUS )
671 : : {
672 : 0 : Next();
673 [ # # ]: 0 : if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED );
674 : : else
675 : : {
676 : 0 : ch2 = aSym.toAsciiUpperCase()[0];
677 [ # # ]: 0 : if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0;
678 : : }
679 : : }
680 [ # # ]: 0 : if (!ch2) ch2 = ch1;
681 : 0 : ch1 -= 'A'; ch2 -= 'A';
682 [ # # ]: 0 : for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t;
683 [ # # ]: 0 : if( !TestComma() ) break;
684 : : }
685 : 0 : }
686 : :
687 : : // STOP/SYSTEM
688 : :
689 : 2 : void SbiParser::Stop()
690 : : {
691 : 2 : aGen.Gen( _STOP );
692 : 2 : Peek(); // #35694: only Peek(), so that EOL is recognized in Single-Line-If
693 : 2 : }
694 : :
695 : : // IMPLEMENTS
696 : :
697 : 0 : void SbiParser::Implements()
698 : : {
699 [ # # ]: 0 : if( !bClassModule )
700 : : {
701 [ # # ]: 0 : Error( SbERR_UNEXPECTED, IMPLEMENTS );
702 : : return;
703 : : }
704 : :
705 [ # # ]: 0 : Peek();
706 [ # # ]: 0 : if( eCurTok != SYMBOL )
707 : : {
708 [ # # ]: 0 : Error( SbERR_SYMBOL_EXPECTED );
709 : : return;
710 : : }
711 : :
712 [ # # ]: 0 : String aImplementedIface = aSym;
713 [ # # ]: 0 : Next();
714 [ # # ][ # # ]: 0 : if( Peek() == DOT )
715 : : {
716 : 0 : rtl::OUString aDotStr( '.' );
717 [ # # ][ # # ]: 0 : while( Peek() == DOT )
718 : : {
719 [ # # ]: 0 : aImplementedIface += aDotStr;
720 [ # # ]: 0 : Next();
721 [ # # ]: 0 : SbiToken ePeekTok = Peek();
722 [ # # ][ # # ]: 0 : if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
[ # # ]
723 : : {
724 [ # # ]: 0 : Next();
725 [ # # ]: 0 : aImplementedIface += aSym;
726 : : }
727 : : else
728 : : {
729 [ # # ]: 0 : Next();
730 [ # # ]: 0 : Error( SbERR_SYMBOL_EXPECTED );
731 : 0 : break;
732 : : }
733 : 0 : }
734 : : }
735 [ # # ][ # # ]: 0 : aIfaceVector.push_back( aImplementedIface );
736 : : }
737 : :
738 : 58 : void SbiParser::EnableCompatibility()
739 : : {
740 [ + + ]: 58 : if( !bCompatible )
741 : 29 : AddConstants();
742 : 58 : bCompatible = sal_True;
743 : 58 : }
744 : :
745 : : // OPTION
746 : :
747 : 34 : void SbiParser::Option()
748 : : {
749 [ + - - - : 34 : switch( Next() )
- - + - ]
750 : : {
751 : : case EXPLICIT:
752 : 5 : bExplicit = true; break;
753 : : case BASE:
754 [ # # ]: 0 : if( Next() == NUMBER )
755 : : {
756 [ # # ][ # # ]: 0 : if( nVal == 0 || nVal == 1 )
757 : : {
758 : 0 : nBase = (short) nVal;
759 : 0 : break;
760 : : }
761 : : }
762 : 0 : Error( SbERR_EXPECTED, "0/1" );
763 : 0 : break;
764 : : case PRIVATE:
765 : : {
766 [ # # ][ # # ]: 0 : String aString = SbiTokenizer::Symbol(Next());
[ # # ]
767 [ # # ][ # # ]: 0 : if( !aString.EqualsIgnoreCaseAscii("Module") )
768 [ # # ]: 0 : Error( SbERR_EXPECTED, "Module" );
769 [ # # ]: 0 : break;
770 : : }
771 : : case COMPARE:
772 : : {
773 : 0 : SbiToken eTok = Next();
774 [ # # ]: 0 : if( eTok == BINARY )
775 : 0 : bText = false;
776 [ # # ][ # # ]: 0 : else if( eTok == SYMBOL && GetSym().equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("text")) )
[ # # ]
777 : 0 : bText = true;
778 : : else
779 : 0 : Error( SbERR_EXPECTED, "Text/Binary" );
780 : 0 : break;
781 : : }
782 : : case COMPATIBLE:
783 : 0 : EnableCompatibility();
784 : 0 : break;
785 : :
786 : : case CLASSMODULE:
787 : 0 : bClassModule = true;
788 : 0 : aGen.GetModule().SetModuleType( com::sun::star::script::ModuleType::CLASS );
789 : 0 : break;
790 : : case VBASUPPORT: // Option VBASupport used to override the module mode ( in fact this must reset the mode
791 [ + - ]: 29 : if( Next() == NUMBER )
792 : : {
793 [ - + ][ # # ]: 29 : if ( nVal == 1 || nVal == 0 )
794 : : {
795 : 29 : bVBASupportOn = ( nVal == 1 );
796 [ + - ]: 29 : if ( bVBASupportOn )
797 : 29 : EnableCompatibility();
798 : : // if the module setting is different
799 : : // reset it to what the Option tells us
800 [ - + ]: 29 : if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
801 : 0 : aGen.GetModule().SetVBACompat( bVBASupportOn );
802 : 29 : break;
803 : : }
804 : : }
805 : 0 : Error( SbERR_EXPECTED, "0/1" );
806 : 0 : break;
807 : : default:
808 : 0 : Error( SbERR_BAD_OPTION, eCurTok );
809 : : }
810 : 34 : }
811 : :
812 : 261 : void addStringConst( SbiSymPool& rPool, const char* pSym, const String& rStr )
813 : : {
814 [ + - ][ + - ]: 261 : SbiConstDef* pConst = new SbiConstDef( rtl::OUString::createFromAscii( pSym ) );
[ + - ][ + - ]
815 : 261 : pConst->SetType( SbxSTRING );
816 : 261 : pConst->Set( rStr );
817 : 261 : rPool.Add( pConst );
818 : 261 : }
819 : :
820 : 232 : inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
821 : : {
822 [ + - ][ + - ]: 232 : addStringConst( rPool, pSym, rtl::OUString::createFromAscii( pStr ) );
[ + - ]
823 : 232 : }
824 : :
825 : 29 : void SbiParser::AddConstants( void )
826 : : {
827 : : // #113063 Create constant RTL symbols
828 [ + - ]: 29 : addStringConst( aPublics, "vbCr", "\x0D" );
829 [ + - ]: 29 : addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
830 [ + - ]: 29 : addStringConst( aPublics, "vbFormFeed", "\x0C" );
831 [ + - ]: 29 : addStringConst( aPublics, "vbLf", "\x0A" );
832 : : #if defined(UNX)
833 [ + - ]: 29 : addStringConst( aPublics, "vbNewLine", "\x0A" );
834 : : #else
835 : : addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
836 : : #endif
837 [ + - ]: 29 : addStringConst( aPublics, "vbNullString", "" );
838 [ + - ]: 29 : addStringConst( aPublics, "vbTab", "\x09" );
839 [ + - ]: 29 : addStringConst( aPublics, "vbVerticalTab", "\x0B" );
840 : :
841 : : // Force length 1 and make char 0 afterwards
842 [ + - ]: 29 : String aNullCharStr( rtl::OUString(" ") );
843 [ + - ]: 29 : aNullCharStr.SetChar( 0, 0 );
844 [ + - ][ + - ]: 29 : addStringConst( aPublics, "vbNullChar", aNullCharStr );
845 : 29 : }
846 : :
847 : : // ERROR n
848 : :
849 : 0 : void SbiParser::ErrorStmnt()
850 : : {
851 [ # # ]: 0 : SbiExpression aPar( this );
852 [ # # ]: 0 : aPar.Gen();
853 [ # # ][ # # ]: 0 : aGen.Gen( _ERROR );
854 : 0 : }
855 : :
856 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|