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 : #include <svtools/miscopt.hxx>
24 :
25 : struct SbiParseStack { // "Stack" for statement-blocks
26 : SbiParseStack* pNext; // Chain
27 : SbiExprNode* pWithVar;
28 : SbiToken eExitTok;
29 : sal_uInt32 nChain; // JUMP-Chain
30 : };
31 :
32 : struct SbiStatement {
33 : SbiToken eTok;
34 : void( SbiParser::*Func )();
35 : bool bMain; // true: OK outside the SUB
36 : bool bSubr; // true: OK inside the SUB
37 : };
38 :
39 : #define Y true
40 : #define N false
41 :
42 : static const SbiStatement StmntTable [] = {
43 : { ATTRIBUTE, &SbiParser::Attribute, Y, Y, }, // ATTRIBUTE
44 : { CALL, &SbiParser::Call, N, Y, }, // CALL
45 : { CLOSE, &SbiParser::Close, N, Y, }, // CLOSE
46 : { _CONST_, &SbiParser::Dim, Y, Y, }, // CONST
47 : { DECLARE, &SbiParser::Declare, Y, N, }, // DECLARE
48 : { DEFBOOL, &SbiParser::DefXXX, Y, N, }, // DEFBOOL
49 : { DEFCUR, &SbiParser::DefXXX, Y, N, }, // DEFCUR
50 : { DEFDATE, &SbiParser::DefXXX, Y, N, }, // DEFDATE
51 : { DEFDBL, &SbiParser::DefXXX, Y, N, }, // DEFDBL
52 : { DEFERR, &SbiParser::DefXXX, Y, N, }, // DEFERR
53 : { DEFINT, &SbiParser::DefXXX, Y, N, }, // DEFINT
54 : { DEFLNG, &SbiParser::DefXXX, Y, N, }, // DEFLNG
55 : { DEFOBJ, &SbiParser::DefXXX, Y, N, }, // DEFOBJ
56 : { DEFSNG, &SbiParser::DefXXX, Y, N, }, // DEFSNG
57 : { DEFSTR, &SbiParser::DefXXX, Y, N, }, // DEFSTR
58 : { DEFVAR, &SbiParser::DefXXX, Y, N, }, // DEFVAR
59 : { DIM, &SbiParser::Dim, Y, Y, }, // DIM
60 : { DO, &SbiParser::DoLoop, N, Y, }, // DO
61 : { ELSE, &SbiParser::NoIf, N, Y, }, // ELSE
62 : { ELSEIF, &SbiParser::NoIf, N, Y, }, // ELSEIF
63 : { ENDIF, &SbiParser::NoIf, N, Y, }, // ENDIF
64 : { END, &SbiParser::Stop, N, Y, }, // END
65 : { ENUM, &SbiParser::Enum, Y, N, }, // TYPE
66 : { ERASE, &SbiParser::Erase, N, Y, }, // ERASE
67 : { _ERROR_, &SbiParser::ErrorStmnt, N, Y, }, // ERROR
68 : { EXIT, &SbiParser::Exit, N, Y, }, // EXIT
69 : { FOR, &SbiParser::For, N, Y, }, // FOR
70 : { FUNCTION, &SbiParser::SubFunc, Y, N, }, // FUNCTION
71 : { GOSUB, &SbiParser::Goto, N, Y, }, // GOSUB
72 : { GLOBAL, &SbiParser::Dim, Y, N, }, // GLOBAL
73 : { GOTO, &SbiParser::Goto, N, Y, }, // GOTO
74 : { IF, &SbiParser::If, N, Y, }, // IF
75 : { IMPLEMENTS, &SbiParser::Implements, Y, N, }, // IMPLEMENTS
76 : { INPUT, &SbiParser::Input, N, Y, }, // INPUT
77 : { LET, &SbiParser::Assign, N, Y, }, // LET
78 : { LINE, &SbiParser::Line, N, Y, }, // LINE, -> LINE INPUT (#i92642)
79 : { LINEINPUT,&SbiParser::LineInput, N, Y, }, // LINE INPUT
80 : { LOOP, &SbiParser::BadBlock, N, Y, }, // LOOP
81 : { LSET, &SbiParser::LSet, N, Y, }, // LSET
82 : { NAME, &SbiParser::Name, N, Y, }, // NAME
83 : { NEXT, &SbiParser::BadBlock, N, Y, }, // NEXT
84 : { ON, &SbiParser::On, N, Y, }, // ON
85 : { OPEN, &SbiParser::Open, N, Y, }, // OPEN
86 : { OPTION, &SbiParser::Option, Y, N, }, // OPTION
87 : { PRINT, &SbiParser::Print, N, Y, }, // PRINT
88 : { PRIVATE, &SbiParser::Dim, Y, N, }, // PRIVATE
89 : { PROPERTY, &SbiParser::SubFunc, Y, N, }, // FUNCTION
90 : { PUBLIC, &SbiParser::Dim, Y, N, }, // PUBLIC
91 : { REDIM, &SbiParser::ReDim, N, Y, }, // DIM
92 : { RESUME, &SbiParser::Resume, N, Y, }, // RESUME
93 : { RETURN, &SbiParser::Return, N, Y, }, // RETURN
94 : { RSET, &SbiParser::RSet, N, Y, }, // RSET
95 : { SELECT, &SbiParser::Select, N, Y, }, // SELECT
96 : { SET, &SbiParser::Set, N, Y, }, // SET
97 : { STATIC, &SbiParser::Static, Y, Y, }, // STATIC
98 : { STOP, &SbiParser::Stop, N, Y, }, // STOP
99 : { SUB, &SbiParser::SubFunc, Y, N, }, // SUB
100 : { TYPE, &SbiParser::Type, Y, N, }, // TYPE
101 : { UNTIL, &SbiParser::BadBlock, N, Y, }, // UNTIL
102 : { WHILE, &SbiParser::While, N, Y, }, // WHILE
103 : { WEND, &SbiParser::BadBlock, N, Y, }, // WEND
104 : { WITH, &SbiParser::With, N, Y, }, // WITH
105 : { WRITE, &SbiParser::Write, N, Y, }, // WRITE
106 :
107 : { NIL, NULL, N, N }
108 : };
109 :
110 :
111 348 : SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
112 348 : : SbiTokenizer( pm->GetSource32(), pb ),
113 : aGblStrings( this ),
114 : aLclStrings( this ),
115 : aGlobals( aGblStrings, SbGLOBAL ),
116 : aPublics( aGblStrings, SbPUBLIC ),
117 : aRtlSyms( aGblStrings, SbRTL ),
118 348 : aGen( *pm, this, 1024 )
119 : {
120 348 : pBasic = pb;
121 348 : eCurExpr = SbSYMBOL;
122 348 : eEndTok = NIL;
123 348 : pProc = NULL;
124 348 : pStack = NULL;
125 348 : pWithVar = NULL;
126 348 : nBase = 0;
127 : bText =
128 : bGblDefs =
129 : bNewGblDefs =
130 : bSingleLineIf =
131 : bCodeCompleting =
132 348 : bExplicit = false;
133 348 : bClassModule = ( pm->GetModuleType() == com::sun::star::script::ModuleType::CLASS );
134 : OSL_TRACE("Parser - %s, bClassModule %d", OUStringToOString( pm->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), bClassModule );
135 348 : pPool = &aPublics;
136 9396 : for( short i = 0; i < 26; i++ )
137 9048 : eDefTypes[ i ] = SbxVARIANT; // no explicit default type
138 :
139 348 : aPublics.SetParent( &aGlobals );
140 348 : aGlobals.SetParent( &aRtlSyms );
141 :
142 :
143 348 : nGblChain = aGen.Gen( _JUMP, 0 );
144 :
145 348 : rTypeArray = new SbxArray; // array for user defined types
146 348 : rEnumArray = new SbxArray; // array for Enum types
147 348 : bVBASupportOn = pm->IsVBACompat();
148 348 : if ( bVBASupportOn )
149 280 : EnableCompatibility();
150 :
151 348 : }
152 :
153 : // part of the runtime-library?
154 3670 : SbiSymDef* SbiParser::CheckRTLForSym( const OUString& rSym, SbxDataType eType )
155 : {
156 3670 : SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
157 3670 : SbiSymDef* pDef = NULL;
158 3670 : if( pVar )
159 : {
160 452 : if( pVar->IsA( TYPE(SbxMethod) ) )
161 : {
162 314 : SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
163 314 : pProc_->SetType( pVar->GetType() );
164 314 : pDef = pProc_;
165 : }
166 : else
167 : {
168 138 : pDef = aRtlSyms.AddSym( rSym );
169 138 : pDef->SetType( eType );
170 : }
171 : }
172 3670 : return pDef;
173 : }
174 :
175 : // close global chain
176 :
177 348 : bool SbiParser::HasGlobalCode()
178 : {
179 348 : if( bGblDefs && nGblChain )
180 : {
181 74 : aGen.BackChain( nGblChain );
182 74 : aGen.Gen( _LEAVE );
183 74 : nGblChain = 0;
184 : }
185 348 : return bGblDefs;
186 : }
187 :
188 920 : void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
189 : {
190 920 : SbiParseStack* p = new SbiParseStack;
191 920 : p->eExitTok = eTok;
192 920 : p->nChain = 0;
193 920 : p->pWithVar = pWithVar;
194 920 : p->pNext = pStack;
195 920 : pStack = p;
196 920 : pWithVar = pVar;
197 :
198 : // #29955 service the for-loop level
199 920 : if( eTok == FOR )
200 80 : aGen.IncForLevel();
201 920 : }
202 :
203 920 : void SbiParser::CloseBlock()
204 : {
205 920 : if( pStack )
206 : {
207 920 : SbiParseStack* p = pStack;
208 :
209 : // #29955 service the for-loop level
210 920 : if( p->eExitTok == FOR )
211 80 : aGen.DecForLevel();
212 :
213 920 : aGen.BackChain( p->nChain );
214 920 : pStack = p->pNext;
215 920 : pWithVar = p->pWithVar;
216 920 : delete p;
217 : }
218 920 : }
219 :
220 : // EXIT ...
221 :
222 150 : void SbiParser::Exit()
223 : {
224 150 : SbiToken eTok = Next();
225 150 : for( SbiParseStack* p = pStack; p; p = p->pNext )
226 : {
227 150 : SbiToken eExitTok = p->eExitTok;
228 150 : if( eTok == eExitTok ||
229 0 : (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) ) // #i109051
230 : {
231 150 : p->nChain = aGen.Gen( _JUMP, p->nChain );
232 300 : return;
233 : }
234 : }
235 0 : if( pStack )
236 0 : Error( SbERR_EXPECTED, pStack->eExitTok );
237 : else
238 0 : Error( SbERR_BAD_EXIT );
239 : }
240 :
241 3034 : bool SbiParser::TestSymbol( bool bKwdOk )
242 : {
243 3034 : Peek();
244 3034 : if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
245 : {
246 3034 : Next(); return true;
247 : }
248 0 : Error( SbERR_SYMBOL_EXPECTED );
249 0 : return false;
250 : }
251 :
252 :
253 :
254 6184 : bool SbiParser::TestToken( SbiToken t )
255 : {
256 6184 : if( Peek() == t )
257 : {
258 6184 : Next(); return true;
259 : }
260 : else
261 : {
262 0 : Error( SbERR_EXPECTED, t );
263 0 : return false;
264 : }
265 : }
266 :
267 :
268 :
269 1770 : bool SbiParser::TestComma()
270 : {
271 1770 : SbiToken eTok = Peek();
272 1770 : if( IsEoln( eTok ) )
273 : {
274 1580 : Next();
275 1580 : return false;
276 : }
277 190 : else if( eTok != COMMA )
278 : {
279 0 : Error( SbERR_EXPECTED, COMMA );
280 0 : return false;
281 : }
282 190 : Next();
283 190 : return true;
284 : }
285 :
286 :
287 :
288 216 : void SbiParser::TestEoln()
289 : {
290 216 : if( !IsEoln( Next() ) )
291 : {
292 0 : Error( SbERR_EXPECTED, EOLN );
293 0 : while( !IsEoln( Next() ) ) {}
294 : }
295 216 : }
296 :
297 :
298 :
299 1164 : void SbiParser::StmntBlock( SbiToken eEnd )
300 : {
301 1164 : SbiToken xe = eEndTok;
302 1164 : eEndTok = eEnd;
303 1164 : while( !bAbort && Parse() ) {}
304 1164 : eEndTok = xe;
305 1164 : if( IsEof() )
306 : {
307 0 : Error( SbERR_BAD_BLOCK, eEnd );
308 0 : bAbort = true;
309 : }
310 1164 : }
311 :
312 0 : void SbiParser::SetCodeCompleting( const bool& b )
313 : {
314 0 : bCodeCompleting = b;
315 0 : }
316 :
317 :
318 28740 : bool SbiParser::Parse()
319 : {
320 28740 : if( bAbort ) return false;
321 :
322 28740 : EnableErrors();
323 :
324 28740 : bErrorIsSymbol = false;
325 28740 : Peek();
326 28740 : bErrorIsSymbol = true;
327 :
328 28740 : 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 348 : if( bNewGblDefs && nGblChain == 0 )
335 0 : nGblChain = aGen.Gen( _JUMP, 0 );
336 348 : return false;
337 : }
338 :
339 :
340 28392 : if( IsEoln( eCurTok ) )
341 : {
342 15638 : Next(); return true;
343 : }
344 :
345 12754 : if( !bSingleLineIf && MayBeLabel( true ) )
346 : {
347 : // is a label
348 110 : if( !pProc )
349 0 : Error( SbERR_NOT_IN_MAIN, aSym );
350 : else
351 110 : pProc->GetLabels().Define( aSym );
352 110 : Next(); Peek();
353 :
354 110 : if( IsEoln( eCurTok ) )
355 : {
356 110 : Next(); return true;
357 : }
358 : }
359 :
360 : // end of parsing?
361 12644 : if( eCurTok == eEndTok ||
362 8936 : ( bVBASupportOn && // #i109075
363 17876 : (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
364 4 : (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
365 : {
366 1164 : Next();
367 1164 : if( eCurTok != NIL )
368 1164 : aGen.Statement();
369 1164 : return false;
370 : }
371 :
372 : // comment?
373 11480 : 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 11480 : 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 11480 : if( eCurTok == SYMBOL || eCurTok == DOT )
394 : {
395 12960 : if( !pProc )
396 0 : Error( SbERR_EXPECTED, SUB );
397 : else
398 : {
399 : // for correct line and column...
400 6480 : Next();
401 6480 : Push( eCurTok );
402 6480 : aGen.Statement();
403 6480 : Symbol();
404 : }
405 : }
406 : else
407 : {
408 5000 : Next();
409 :
410 : // statement parsers
411 :
412 : const SbiStatement* p;
413 138680 : for( p = StmntTable; p->eTok != NIL; p++ )
414 138680 : if( p->eTok == eCurTok )
415 5000 : break;
416 5000 : if( p->eTok != NIL )
417 : {
418 5000 : if( !pProc && !p->bMain )
419 0 : Error( SbERR_NOT_IN_MAIN, eCurTok );
420 5000 : 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 5430 : if( bNewGblDefs && nGblChain == 0 &&
427 852 : ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
428 : {
429 70 : nGblChain = aGen.Gen( _JUMP, 0 );
430 70 : bNewGblDefs = false;
431 : }
432 : // statement-opcode at the beginning of a sub, too, please
433 10000 : if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
434 7140 : eCurTok == SUB || eCurTok == FUNCTION )
435 4446 : aGen.Statement();
436 5000 : (this->*( p->Func ) )();
437 5000 : SbxError nSbxErr = SbxBase::GetError();
438 5000 : if( nSbxErr )
439 0 : 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 necessary be a : before the ELSE!
448 :
449 11480 : if( !IsEos() )
450 : {
451 2002 : Peek();
452 2002 : 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 11480 : return true;
462 : }
463 :
464 :
465 106 : SbiExprNode* SbiParser::GetWithVar()
466 : {
467 106 : if( pWithVar )
468 106 : 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 6480 : void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
485 : {
486 6480 : SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
487 6480 : SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );
488 :
489 6480 : bool bEQ = ( Peek() == EQ );
490 6480 : if( !bEQ && bVBASupportOn && aVar.IsBracket() )
491 0 : Error( SbERR_EXPECTED, "=" );
492 :
493 6480 : RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
494 6480 : bool bSpecialMidHandling = false;
495 6480 : SbiSymDef* pDef = aVar.GetRealVar();
496 6480 : if( bEQ && pDef && pDef->GetScope() == SbRTL )
497 : {
498 2 : OUString aRtlName = pDef->GetName();
499 2 : if( aRtlName.equalsIgnoreAsciiCase("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 2 : }
518 : }
519 6480 : aVar.Gen( eRecMode );
520 6480 : if( !bSpecialMidHandling )
521 : {
522 6480 : if( !bEQ )
523 : {
524 1784 : aGen.Gen( _GET );
525 : }
526 : else
527 : {
528 : // so it must be an assignment!
529 4696 : if( !aVar.IsLvalue() )
530 0 : Error( SbERR_LVALUE_EXPECTED );
531 4696 : TestToken( EQ );
532 4696 : SbiExpression aExpr( this );
533 4696 : aExpr.Gen();
534 4696 : SbiOpcode eOp = _PUT;
535 4696 : if( pDef )
536 : {
537 4696 : if( pDef->GetConstDef() )
538 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
539 4696 : if( pDef->GetType() == SbxOBJECT )
540 : {
541 200 : eOp = _SET;
542 200 : if( pDef->GetTypeId() )
543 : {
544 16 : aGen.Gen( _SETCLASS, pDef->GetTypeId() );
545 6496 : return;
546 : }
547 : }
548 : }
549 4680 : aGen.Gen( eOp );
550 : }
551 6464 : }
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 292 : void SbiParser::Set()
577 : {
578 292 : SbiExpression aLvalue( this, SbLVALUE );
579 292 : SbxDataType eType = aLvalue.GetType();
580 292 : if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
581 0 : Error( SbERR_INVALID_OBJECT );
582 292 : TestToken( EQ );
583 292 : SbiSymDef* pDef = aLvalue.GetRealVar();
584 292 : if( pDef->GetConstDef() )
585 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
586 :
587 292 : SbiToken eTok = Peek();
588 292 : if( eTok == NEW )
589 : {
590 0 : Next();
591 0 : OUString aStr;
592 0 : SbiSymDef* pTypeDef = new SbiSymDef( aStr );
593 0 : TypeDecl( *pTypeDef, 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 292 : SbiExpression aExpr( this );
602 292 : aLvalue.Gen();
603 292 : aExpr.Gen();
604 : // Its a good idea to distinguish between
605 : // set something = another &
606 : // something = another
607 : // ( its necessary for vba objects where set is object
608 : // specific and also doesn't involve processing default params )
609 292 : if( pDef->GetTypeId() )
610 : {
611 242 : if ( bVBASupportOn )
612 242 : aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
613 : else
614 0 : aGen.Gen( _SETCLASS, pDef->GetTypeId() );
615 : }
616 : else
617 : {
618 50 : if ( bVBASupportOn )
619 48 : aGen.Gen( _VBASET );
620 : else
621 2 : aGen.Gen( _SET );
622 292 : }
623 292 : }
624 292 : }
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 : {
632 0 : Error( SbERR_INVALID_OBJECT );
633 : }
634 0 : TestToken( EQ );
635 0 : SbiSymDef* pDef = aLvalue.GetRealVar();
636 0 : if( pDef && pDef->GetConstDef() )
637 : {
638 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
639 : }
640 0 : SbiExpression aExpr( this );
641 0 : aLvalue.Gen();
642 0 : aExpr.Gen();
643 0 : aGen.Gen( _LSET );
644 0 : }
645 :
646 : // JSM 07.10.95
647 0 : void SbiParser::RSet()
648 : {
649 0 : SbiExpression aLvalue( this, SbLVALUE );
650 0 : if( aLvalue.GetType() != SbxSTRING )
651 : {
652 0 : Error( SbERR_INVALID_OBJECT );
653 : }
654 0 : TestToken( EQ );
655 0 : SbiSymDef* pDef = aLvalue.GetRealVar();
656 0 : if( pDef && pDef->GetConstDef() )
657 0 : Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
658 0 : SbiExpression aExpr( this );
659 0 : aLvalue.Gen();
660 0 : aExpr.Gen();
661 0 : aGen.Gen( _RSET );
662 0 : }
663 :
664 : // DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR and so on
665 :
666 0 : void SbiParser::DefXXX()
667 : {
668 : sal_Unicode ch1, ch2;
669 0 : SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER );
670 :
671 0 : while( !bAbort )
672 : {
673 0 : if( Next() != SYMBOL ) break;
674 0 : ch1 = aSym.toAsciiUpperCase()[0];
675 0 : ch2 = 0;
676 0 : if( Peek() == MINUS )
677 : {
678 0 : Next();
679 0 : if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED );
680 : else
681 : {
682 0 : ch2 = aSym.toAsciiUpperCase()[0];
683 0 : if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0;
684 : }
685 : }
686 0 : if (!ch2) ch2 = ch1;
687 0 : ch1 -= 'A'; ch2 -= 'A';
688 0 : for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t;
689 0 : if( !TestComma() ) break;
690 : }
691 0 : }
692 :
693 : // STOP/SYSTEM
694 :
695 2 : void SbiParser::Stop()
696 : {
697 2 : aGen.Gen( _STOP );
698 2 : Peek(); // #35694: only Peek(), so that EOL is recognized in Single-Line-If
699 2 : }
700 :
701 : // IMPLEMENTS
702 :
703 0 : void SbiParser::Implements()
704 : {
705 0 : if( !bClassModule )
706 : {
707 0 : Error( SbERR_UNEXPECTED, IMPLEMENTS );
708 0 : return;
709 : }
710 :
711 0 : Peek();
712 0 : if( eCurTok != SYMBOL )
713 : {
714 0 : Error( SbERR_SYMBOL_EXPECTED );
715 0 : return;
716 : }
717 :
718 0 : OUString aImplementedIface = aSym;
719 0 : Next();
720 0 : if( Peek() == DOT )
721 : {
722 0 : OUString aDotStr( '.' );
723 0 : while( Peek() == DOT )
724 : {
725 0 : aImplementedIface += aDotStr;
726 0 : Next();
727 0 : SbiToken ePeekTok = Peek();
728 0 : if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
729 : {
730 0 : Next();
731 0 : aImplementedIface += aSym;
732 : }
733 : else
734 : {
735 0 : Next();
736 0 : Error( SbERR_SYMBOL_EXPECTED );
737 0 : break;
738 : }
739 0 : }
740 : }
741 0 : aIfaceVector.push_back( aImplementedIface );
742 : }
743 :
744 560 : void SbiParser::EnableCompatibility()
745 : {
746 560 : if( !bCompatible )
747 280 : AddConstants();
748 560 : bCompatible = true;
749 560 : }
750 :
751 : // OPTION
752 :
753 320 : void SbiParser::Option()
754 : {
755 320 : switch( Next() )
756 : {
757 : case BASIC_EXPLICIT:
758 38 : bExplicit = true; break;
759 : case BASE:
760 2 : if( Next() == NUMBER )
761 : {
762 2 : if( nVal == 0 || nVal == 1 )
763 : {
764 2 : nBase = (short) nVal;
765 2 : break;
766 : }
767 : }
768 0 : Error( SbERR_EXPECTED, "0/1" );
769 0 : break;
770 : case PRIVATE:
771 : {
772 0 : OUString aString = SbiTokenizer::Symbol(Next());
773 0 : if( !aString.equalsIgnoreAsciiCase("Module") )
774 : {
775 0 : Error( SbERR_EXPECTED, "Module" );
776 : }
777 0 : break;
778 : }
779 : case COMPARE:
780 : {
781 0 : SbiToken eTok = Next();
782 0 : if( eTok == BINARY )
783 : {
784 0 : bText = false;
785 : }
786 0 : else if( eTok == SYMBOL && GetSym().equalsIgnoreAsciiCase("text") )
787 : {
788 0 : bText = true;
789 : }
790 : else
791 : {
792 0 : Error( SbERR_EXPECTED, "Text/Binary" );
793 : }
794 0 : break;
795 : }
796 : case COMPATIBLE:
797 0 : EnableCompatibility();
798 0 : break;
799 :
800 : case CLASSMODULE:
801 0 : bClassModule = true;
802 0 : aGen.GetModule().SetModuleType( com::sun::star::script::ModuleType::CLASS );
803 0 : break;
804 : case VBASUPPORT: // Option VBASupport used to override the module mode ( in fact this must reset the mode
805 280 : if( Next() == NUMBER )
806 : {
807 280 : if ( nVal == 1 || nVal == 0 )
808 : {
809 280 : bVBASupportOn = ( nVal == 1 );
810 280 : if ( bVBASupportOn )
811 : {
812 280 : EnableCompatibility();
813 : }
814 : // if the module setting is different
815 : // reset it to what the Option tells us
816 280 : if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
817 : {
818 0 : aGen.GetModule().SetVBACompat( bVBASupportOn );
819 : }
820 280 : break;
821 : }
822 : }
823 0 : Error( SbERR_EXPECTED, "0/1" );
824 0 : break;
825 : default:
826 0 : Error( SbERR_BAD_OPTION, eCurTok );
827 : }
828 320 : }
829 :
830 2520 : void addStringConst( SbiSymPool& rPool, const char* pSym, const OUString& rStr )
831 : {
832 2520 : SbiConstDef* pConst = new SbiConstDef( OUString::createFromAscii( pSym ) );
833 2520 : pConst->SetType( SbxSTRING );
834 2520 : pConst->Set( rStr );
835 2520 : rPool.Add( pConst );
836 2520 : }
837 :
838 2240 : inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
839 : {
840 2240 : addStringConst( rPool, pSym, OUString::createFromAscii( pStr ) );
841 2240 : }
842 :
843 280 : void SbiParser::AddConstants( void )
844 : {
845 : // #113063 Create constant RTL symbols
846 280 : addStringConst( aPublics, "vbCr", "\x0D" );
847 280 : addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
848 280 : addStringConst( aPublics, "vbFormFeed", "\x0C" );
849 280 : addStringConst( aPublics, "vbLf", "\x0A" );
850 : #ifndef WNT
851 280 : addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
852 : #else
853 : addStringConst( aPublics, "vbNewLine", "\x0A" );
854 : #endif
855 280 : addStringConst( aPublics, "vbNullString", "" );
856 280 : addStringConst( aPublics, "vbTab", "\x09" );
857 280 : addStringConst( aPublics, "vbVerticalTab", "\x0B" );
858 :
859 : // Force length 1 and make char 0 afterwards
860 280 : OUString aNullCharStr((sal_Unicode)0);
861 280 : addStringConst( aPublics, "vbNullChar", aNullCharStr );
862 280 : }
863 :
864 : // ERROR n
865 :
866 0 : void SbiParser::ErrorStmnt()
867 : {
868 0 : SbiExpression aPar( this );
869 0 : aPar.Gen();
870 0 : aGen.Gen( _ERROR );
871 0 : }
872 :
873 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|