LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/basic/source/comp - parser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 246 414 59.4 %
Date: 2013-07-09 Functions: 21 27 77.8 %
Legend: Lines: hit not hit

          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         162 : SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
     116         162 :         : SbiTokenizer( pm->GetSource32(), pb ),
     117             :           aGblStrings( this ),
     118             :           aLclStrings( this ),
     119             :           aGlobals( aGblStrings, SbGLOBAL ),
     120             :           aPublics( aGblStrings, SbPUBLIC ),
     121             :           aRtlSyms( aGblStrings, SbRTL ),
     122         162 :           aGen( *pm, this, 1024 )
     123             : {
     124         162 :     pBasic   = pb;
     125         162 :     eCurExpr = SbSYMBOL;
     126         162 :     eEndTok  = NIL;
     127         162 :     pProc    = NULL;
     128         162 :     pStack   = NULL;
     129         162 :     pWithVar = NULL;
     130         162 :     nBase    = 0;
     131             :     bText    =
     132             :     bGblDefs =
     133             :     bNewGblDefs =
     134             :     bSingleLineIf =
     135         162 :     bExplicit = false;
     136         162 :     bClassModule = ( pm->GetModuleType() == com::sun::star::script::ModuleType::CLASS );
     137             :     OSL_TRACE("Parser - %s, bClassModule %d", OUStringToOString( pm->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), bClassModule );
     138         162 :     pPool    = &aPublics;
     139        4374 :     for( short i = 0; i < 26; i++ )
     140        4212 :         eDefTypes[ i ] = SbxVARIANT;    // no explicit default type
     141             : 
     142         162 :     aPublics.SetParent( &aGlobals );
     143         162 :     aGlobals.SetParent( &aRtlSyms );
     144             : 
     145             : 
     146         162 :     nGblChain = aGen.Gen( _JUMP, 0 );
     147             : 
     148         162 :     rTypeArray = new SbxArray; // array for user defined types
     149         162 :     rEnumArray = new SbxArray; // array for Enum types
     150         162 :     bVBASupportOn = pm->IsVBACompat();
     151         162 :     if ( bVBASupportOn )
     152         137 :         EnableCompatibility();
     153             : 
     154         162 : }
     155             : 
     156             : 
     157             : // part of the runtime-library?
     158        1775 : SbiSymDef* SbiParser::CheckRTLForSym( const OUString& rSym, SbxDataType eType )
     159             : {
     160        1775 :     SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
     161        1775 :     SbiSymDef* pDef = NULL;
     162        1775 :     if( pVar )
     163             :     {
     164         198 :         if( pVar->IsA( TYPE(SbxMethod) ) )
     165             :         {
     166         139 :             SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
     167         139 :             pProc_->SetType( pVar->GetType() );
     168         139 :             pDef = pProc_;
     169             :         }
     170             :         else
     171             :         {
     172          59 :             pDef = aRtlSyms.AddSym( rSym );
     173          59 :             pDef->SetType( eType );
     174             :         }
     175             :     }
     176        1775 :     return pDef;
     177             : }
     178             : 
     179             : // close global chain
     180             : 
     181         162 : bool SbiParser::HasGlobalCode()
     182             : {
     183         162 :     if( bGblDefs && nGblChain )
     184             :     {
     185          34 :         aGen.BackChain( nGblChain );
     186          34 :         aGen.Gen( _LEAVE );
     187          34 :         nGblChain = 0;
     188             :     }
     189         162 :     return bGblDefs;
     190             : }
     191             : 
     192         441 : void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
     193             : {
     194         441 :     SbiParseStack* p = new SbiParseStack;
     195         441 :     p->eExitTok = eTok;
     196         441 :     p->nChain   = 0;
     197         441 :     p->pWithVar = pWithVar;
     198         441 :     p->pNext    = pStack;
     199         441 :     pStack      = p;
     200         441 :     pWithVar    = pVar;
     201             : 
     202             :     // #29955 service the for-loop level
     203         441 :     if( eTok == FOR )
     204          40 :         aGen.IncForLevel();
     205         441 : }
     206             : 
     207         441 : void SbiParser::CloseBlock()
     208             : {
     209         441 :     if( pStack )
     210             :     {
     211         441 :         SbiParseStack* p = pStack;
     212             : 
     213             :         // #29955 service the for-loop level
     214         441 :         if( p->eExitTok == FOR )
     215          40 :             aGen.DecForLevel();
     216             : 
     217         441 :         aGen.BackChain( p->nChain );
     218         441 :         pStack = p->pNext;
     219         441 :         pWithVar = p->pWithVar;
     220         441 :         delete p;
     221             :     }
     222         441 : }
     223             : 
     224             : // EXIT ...
     225             : 
     226          71 : void SbiParser::Exit()
     227             : {
     228          71 :     SbiToken eTok = Next();
     229          71 :     for( SbiParseStack* p = pStack; p; p = p->pNext )
     230             :     {
     231          71 :         SbiToken eExitTok = p->eExitTok;
     232          71 :         if( eTok == eExitTok ||
     233           0 :             (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) )   // #i109051
     234             :         {
     235          71 :             p->nChain = aGen.Gen( _JUMP, p->nChain );
     236         142 :             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        1450 : bool SbiParser::TestSymbol( bool bKwdOk )
     246             : {
     247        1450 :     Peek();
     248        1450 :     if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
     249             :     {
     250        1450 :         Next(); return true;
     251             :     }
     252           0 :     Error( SbERR_SYMBOL_EXPECTED );
     253           0 :     return false;
     254             : }
     255             : 
     256             : 
     257             : 
     258        3012 : bool SbiParser::TestToken( SbiToken t )
     259             : {
     260        3012 :     if( Peek() == t )
     261             :     {
     262        3012 :         Next(); return true;
     263             :     }
     264             :     else
     265             :     {
     266           0 :         Error( SbERR_EXPECTED, t );
     267           0 :         return false;
     268             :     }
     269             : }
     270             : 
     271             : 
     272             : 
     273         857 : bool SbiParser::TestComma()
     274             : {
     275         857 :     SbiToken eTok = Peek();
     276         857 :     if( IsEoln( eTok ) )
     277             :     {
     278         761 :         Next();
     279         761 :         return false;
     280             :     }
     281          96 :     else if( eTok != COMMA )
     282             :     {
     283           0 :         Error( SbERR_EXPECTED, COMMA );
     284           0 :         return false;
     285             :     }
     286          96 :     Next();
     287          96 :     return true;
     288             : }
     289             : 
     290             : 
     291             : 
     292         109 : void SbiParser::TestEoln()
     293             : {
     294         109 :     if( !IsEoln( Next() ) )
     295             :     {
     296           0 :         Error( SbERR_EXPECTED, EOLN );
     297           0 :         while( !IsEoln( Next() ) ) {}
     298             :     }
     299         109 : }
     300             : 
     301             : 
     302             : 
     303         549 : void SbiParser::StmntBlock( SbiToken eEnd )
     304             : {
     305         549 :     SbiToken xe = eEndTok;
     306         549 :     eEndTok = eEnd;
     307         549 :     while( !bAbort && Parse() ) {}
     308         549 :     eEndTok = xe;
     309         549 :     if( IsEof() )
     310             :     {
     311           0 :         Error( SbERR_BAD_BLOCK, eEnd );
     312           0 :         bAbort = sal_True;
     313             :     }
     314         549 : }
     315             : 
     316             : 
     317             : 
     318       13825 : bool SbiParser::Parse()
     319             : {
     320       13825 :     if( bAbort ) return false;
     321             : 
     322       13825 :     EnableErrors();
     323             : 
     324       13825 :     bErrorIsSymbol = false;
     325       13825 :     Peek();
     326       13825 :     bErrorIsSymbol = true;
     327             : 
     328       13825 :     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         162 :         if( bNewGblDefs && nGblChain == 0 )
     335           0 :             nGblChain = aGen.Gen( _JUMP, 0 );
     336         162 :         return false;
     337             :     }
     338             : 
     339             : 
     340       13663 :     if( IsEoln( eCurTok ) )
     341             :     {
     342        7482 :         Next(); return true;
     343             :     }
     344             : 
     345        6181 :     if( !bSingleLineIf && MayBeLabel( true ) )
     346             :     {
     347             :         // is a label
     348          51 :         if( !pProc )
     349           0 :             Error( SbERR_NOT_IN_MAIN, aSym );
     350             :         else
     351          51 :             pProc->GetLabels().Define( aSym );
     352          51 :         Next(); Peek();
     353             : 
     354          51 :         if( IsEoln( eCurTok ) )
     355             :         {
     356          51 :             Next(); return true;
     357             :         }
     358             :     }
     359             : 
     360             :     // end of parsing?
     361        6130 :     if( eCurTok == eEndTok ||
     362        4325 :         ( bVBASupportOn &&      // #i109075
     363        8652 :           (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
     364           2 :           (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
     365             :     {
     366         549 :         Next();
     367         549 :         if( eCurTok != NIL )
     368         549 :             aGen.Statement();
     369         549 :         return false;
     370             :     }
     371             : 
     372             :     // comment?
     373        5581 :     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        5581 :         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        5581 :     if( eCurTok == SYMBOL || eCurTok == DOT )
     394             :     {
     395        6320 :         if( !pProc )
     396           0 :             Error( SbERR_EXPECTED, SUB );
     397             :         else
     398             :         {
     399             :             // for correct line and column...
     400        3160 :             Next();
     401        3160 :             Push( eCurTok );
     402        3160 :             aGen.Statement();
     403        3160 :                 Symbol();
     404             :         }
     405             :     }
     406             :     else
     407             :     {
     408        2421 :         Next();
     409             : 
     410             :         // statement parsers
     411             : 
     412             :         SbiStatement* p;
     413       67069 :         for( p = StmntTable; p->eTok != NIL; p++ )
     414       67069 :             if( p->eTok == eCurTok )
     415        2421 :                 break;
     416        2421 :         if( p->eTok != NIL )
     417             :         {
     418        2421 :             if( !pProc && !p->bMain )
     419           0 :                 Error( SbERR_NOT_IN_MAIN, eCurTok );
     420        2421 :             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        2628 :                 if( bNewGblDefs && nGblChain == 0 &&
     427         410 :                     ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
     428             :                 {
     429          34 :                     nGblChain = aGen.Gen( _JUMP, 0 );
     430          34 :                     bNewGblDefs = false;
     431             :                 }
     432             :                 // statement-opcode at the beginning of a sub, too, please
     433        4842 :                 if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
     434        3438 :                         eCurTok == SUB || eCurTok == FUNCTION )
     435        2153 :                     aGen.Statement();
     436        2421 :                 (this->*( p->Func ) )();
     437        2421 :                 SbxError nSbxErr = SbxBase::GetError();
     438        2421 :                 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        5581 :     if( !IsEos() )
     450             :     {
     451         952 :         Peek();
     452         952 :         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        5581 :     return true;
     462             : }
     463             : 
     464             : 
     465          53 : SbiExprNode* SbiParser::GetWithVar()
     466             : {
     467          53 :     if( pWithVar )
     468          53 :         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        3160 : void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
     485             : {
     486        3160 :     SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
     487        3160 :     SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );
     488             : 
     489        3160 :     bool bEQ = ( Peek() == EQ );
     490        3160 :     if( !bEQ && bVBASupportOn && aVar.IsBracket() )
     491           0 :         Error( SbERR_EXPECTED, "=" );
     492             : 
     493        3160 :     RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
     494        3160 :     bool bSpecialMidHandling = false;
     495        3160 :     SbiSymDef* pDef = aVar.GetRealVar();
     496        3160 :     if( bEQ && pDef && pDef->GetScope() == SbRTL )
     497             :     {
     498           1 :         OUString aRtlName = pDef->GetName();
     499           1 :         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           1 :         }
     518             :     }
     519        3160 :     aVar.Gen( eRecMode );
     520        3160 :     if( !bSpecialMidHandling )
     521             :     {
     522        3160 :         if( !bEQ )
     523             :         {
     524         883 :             aGen.Gen( _GET );
     525             :         }
     526             :         else
     527             :         {
     528             :             // so it must be an assignment!
     529        2277 :             if( !aVar.IsLvalue() )
     530           0 :                 Error( SbERR_LVALUE_EXPECTED );
     531        2277 :             TestToken( EQ );
     532        2277 :             SbiExpression aExpr( this );
     533        2277 :             aExpr.Gen();
     534        2277 :             SbiOpcode eOp = _PUT;
     535        2277 :             if( pDef )
     536             :             {
     537        2277 :                 if( pDef->GetConstDef() )
     538           0 :                     Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     539        2277 :                 if( pDef->GetType() == SbxOBJECT )
     540             :                 {
     541          99 :                     eOp = _SET;
     542          99 :                     if( pDef->GetTypeId() )
     543             :                     {
     544           8 :                         aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     545        3168 :                         return;
     546             :                     }
     547             :                 }
     548             :             }
     549        2269 :             aGen.Gen( eOp );
     550             :         }
     551        3152 :     }
     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         145 : void SbiParser::Set()
     577             : {
     578         145 :     SbiExpression aLvalue( this, SbLVALUE );
     579         145 :     SbxDataType eType = aLvalue.GetType();
     580         145 :     if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
     581           0 :         Error( SbERR_INVALID_OBJECT );
     582         145 :     TestToken( EQ );
     583         145 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     584         145 :     if( pDef && pDef->GetConstDef() )
     585           0 :         Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     586             : 
     587         145 :     SbiToken eTok = Peek();
     588         145 :     if( eTok == NEW )
     589             :     {
     590           0 :         Next();
     591           0 :         OUString 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         145 :         SbiExpression aExpr( this );
     602         145 :         aLvalue.Gen();
     603         145 :         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         145 :         if( pDef->GetTypeId() )
     610             :         {
     611         121 :             if ( bVBASupportOn )
     612         121 :                 aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
     613             :             else
     614           0 :                 aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     615             :         }
     616             :         else
     617             :         {
     618          24 :             if ( bVBASupportOn )
     619          24 :                 aGen.Gen( _VBASET );
     620             :             else
     621           0 :                 aGen.Gen( _SET );
     622         145 :         }
     623         145 :     }
     624         145 : }
     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           1 : void SbiParser::Stop()
     696             : {
     697           1 :     aGen.Gen( _STOP );
     698           1 :     Peek();     // #35694: only Peek(), so that EOL is recognized in Single-Line-If
     699           1 : }
     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         274 : void SbiParser::EnableCompatibility()
     745             : {
     746         274 :     if( !bCompatible )
     747         137 :         AddConstants();
     748         274 :     bCompatible = sal_True;
     749         274 : }
     750             : 
     751             : // OPTION
     752             : 
     753         154 : void SbiParser::Option()
     754             : {
     755         154 :     switch( Next() )
     756             :     {
     757             :         case EXPLICIT:
     758          16 :             bExplicit = true; break;
     759             :         case BASE:
     760           1 :             if( Next() == NUMBER )
     761             :             {
     762           1 :                 if( nVal == 0 || nVal == 1 )
     763             :                 {
     764           1 :                     nBase = (short) nVal;
     765           1 :                     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         137 :             if( Next() == NUMBER )
     806             :             {
     807         137 :                 if ( nVal == 1 || nVal == 0 )
     808             :                 {
     809         137 :                     bVBASupportOn = ( nVal == 1 );
     810         137 :                     if ( bVBASupportOn )
     811             :                     {
     812         137 :                         EnableCompatibility();
     813             :                     }
     814             :                     // if the module setting is different
     815             :                     // reset it to what the Option tells us
     816         137 :                     if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
     817             :                     {
     818           0 :                         aGen.GetModule().SetVBACompat( bVBASupportOn );
     819             :                     }
     820         137 :                     break;
     821             :                 }
     822             :             }
     823           0 :             Error( SbERR_EXPECTED, "0/1" );
     824           0 :             break;
     825             :         default:
     826           0 :             Error( SbERR_BAD_OPTION, eCurTok );
     827             :     }
     828         154 : }
     829             : 
     830        1233 : void addStringConst( SbiSymPool& rPool, const char* pSym, const OUString& rStr )
     831             : {
     832        1233 :     SbiConstDef* pConst = new SbiConstDef( OUString::createFromAscii( pSym ) );
     833        1233 :     pConst->SetType( SbxSTRING );
     834        1233 :     pConst->Set( rStr );
     835        1233 :     rPool.Add( pConst );
     836        1233 : }
     837             : 
     838        1096 : inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
     839             : {
     840        1096 :     addStringConst( rPool, pSym, OUString::createFromAscii( pStr ) );
     841        1096 : }
     842             : 
     843         137 : void SbiParser::AddConstants( void )
     844             : {
     845             :     // #113063 Create constant RTL symbols
     846         137 :     addStringConst( aPublics, "vbCr", "\x0D" );
     847         137 :     addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
     848         137 :     addStringConst( aPublics, "vbFormFeed", "\x0C" );
     849         137 :     addStringConst( aPublics, "vbLf", "\x0A" );
     850             : #if defined(UNX)
     851         137 :     addStringConst( aPublics, "vbNewLine", "\x0A" );
     852             : #else
     853             :     addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
     854             : #endif
     855         137 :     addStringConst( aPublics, "vbNullString", "" );
     856         137 :     addStringConst( aPublics, "vbTab", "\x09" );
     857         137 :     addStringConst( aPublics, "vbVerticalTab", "\x0B" );
     858             : 
     859             :     // Force length 1 and make char 0 afterwards
     860         137 :     OUString aNullCharStr((sal_Unicode)0);
     861         137 :     addStringConst( aPublics, "vbNullChar", aNullCharStr );
     862         137 : }
     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: */

Generated by: LCOV version 1.10