LCOV - code coverage report
Current view: top level - basic/source/comp - parser.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 249 419 59.4 %
Date: 2014-04-11 Functions: 22 29 75.9 %
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             : #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         171 : SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
     112         171 :         : SbiTokenizer( pm->GetSource32(), pb ),
     113             :           aGblStrings( this ),
     114             :           aLclStrings( this ),
     115             :           aGlobals( aGblStrings, SbGLOBAL ),
     116             :           aPublics( aGblStrings, SbPUBLIC ),
     117             :           aRtlSyms( aGblStrings, SbRTL ),
     118         171 :           aGen( *pm, this, 1024 )
     119             : {
     120         171 :     pBasic   = pb;
     121         171 :     eCurExpr = SbSYMBOL;
     122         171 :     eEndTok  = NIL;
     123         171 :     pProc    = NULL;
     124         171 :     pStack   = NULL;
     125         171 :     pWithVar = NULL;
     126         171 :     nBase    = 0;
     127             :     bText    =
     128             :     bGblDefs =
     129             :     bNewGblDefs =
     130             :     bSingleLineIf =
     131             :     bCodeCompleting =
     132         171 :     bExplicit = false;
     133         171 :     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         171 :     pPool    = &aPublics;
     136        4617 :     for( short i = 0; i < 26; i++ )
     137        4446 :         eDefTypes[ i ] = SbxVARIANT;    // no explicit default type
     138             : 
     139         171 :     aPublics.SetParent( &aGlobals );
     140         171 :     aGlobals.SetParent( &aRtlSyms );
     141             : 
     142             : 
     143         171 :     nGblChain = aGen.Gen( _JUMP, 0 );
     144             : 
     145         171 :     rTypeArray = new SbxArray; // array for user defined types
     146         171 :     rEnumArray = new SbxArray; // array for Enum types
     147         171 :     bVBASupportOn = pm->IsVBACompat();
     148         171 :     if ( bVBASupportOn )
     149         137 :         EnableCompatibility();
     150             : 
     151         171 : }
     152             : 
     153             : // part of the runtime-library?
     154        1786 : SbiSymDef* SbiParser::CheckRTLForSym( const OUString& rSym, SbxDataType eType )
     155             : {
     156        1786 :     SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
     157        1786 :     SbiSymDef* pDef = NULL;
     158        1786 :     if( pVar )
     159             :     {
     160         207 :         if( pVar->IsA( TYPE(SbxMethod) ) )
     161             :         {
     162         148 :             SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
     163         148 :             pProc_->SetType( pVar->GetType() );
     164         148 :             pDef = pProc_;
     165             :         }
     166             :         else
     167             :         {
     168          59 :             pDef = aRtlSyms.AddSym( rSym );
     169          59 :             pDef->SetType( eType );
     170             :         }
     171             :     }
     172        1786 :     return pDef;
     173             : }
     174             : 
     175             : // close global chain
     176             : 
     177         171 : bool SbiParser::HasGlobalCode()
     178             : {
     179         171 :     if( bGblDefs && nGblChain )
     180             :     {
     181          34 :         aGen.BackChain( nGblChain );
     182          34 :         aGen.Gen( _LEAVE );
     183          34 :         nGblChain = 0;
     184             :     }
     185         171 :     return bGblDefs;
     186             : }
     187             : 
     188         450 : void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
     189             : {
     190         450 :     SbiParseStack* p = new SbiParseStack;
     191         450 :     p->eExitTok = eTok;
     192         450 :     p->nChain   = 0;
     193         450 :     p->pWithVar = pWithVar;
     194         450 :     p->pNext    = pStack;
     195         450 :     pStack      = p;
     196         450 :     pWithVar    = pVar;
     197             : 
     198             :     // #29955 service the for-loop level
     199         450 :     if( eTok == FOR )
     200          40 :         aGen.IncForLevel();
     201         450 : }
     202             : 
     203         450 : void SbiParser::CloseBlock()
     204             : {
     205         450 :     if( pStack )
     206             :     {
     207         450 :         SbiParseStack* p = pStack;
     208             : 
     209             :         // #29955 service the for-loop level
     210         450 :         if( p->eExitTok == FOR )
     211          40 :             aGen.DecForLevel();
     212             : 
     213         450 :         aGen.BackChain( p->nChain );
     214         450 :         pStack = p->pNext;
     215         450 :         pWithVar = p->pWithVar;
     216         450 :         delete p;
     217             :     }
     218         450 : }
     219             : 
     220             : // EXIT ...
     221             : 
     222          72 : void SbiParser::Exit()
     223             : {
     224          72 :     SbiToken eTok = Next();
     225          72 :     for( SbiParseStack* p = pStack; p; p = p->pNext )
     226             :     {
     227          72 :         SbiToken eExitTok = p->eExitTok;
     228          72 :         if( eTok == eExitTok ||
     229           0 :             (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) )   // #i109051
     230             :         {
     231          72 :             p->nChain = aGen.Gen( _JUMP, p->nChain );
     232         144 :             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        1462 : bool SbiParser::TestSymbol( bool bKwdOk )
     242             : {
     243        1462 :     Peek();
     244        1462 :     if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
     245             :     {
     246        1462 :         Next(); return true;
     247             :     }
     248           0 :     Error( SbERR_SYMBOL_EXPECTED );
     249           0 :     return false;
     250             : }
     251             : 
     252             : 
     253             : 
     254        3020 : bool SbiParser::TestToken( SbiToken t )
     255             : {
     256        3020 :     if( Peek() == t )
     257             :     {
     258        3020 :         Next(); return true;
     259             :     }
     260             :     else
     261             :     {
     262           0 :         Error( SbERR_EXPECTED, t );
     263           0 :         return false;
     264             :     }
     265             : }
     266             : 
     267             : 
     268             : 
     269         861 : bool SbiParser::TestComma()
     270             : {
     271         861 :     SbiToken eTok = Peek();
     272         861 :     if( IsEoln( eTok ) )
     273             :     {
     274         766 :         Next();
     275         766 :         return false;
     276             :     }
     277          95 :     else if( eTok != COMMA )
     278             :     {
     279           0 :         Error( SbERR_EXPECTED, COMMA );
     280           0 :         return false;
     281             :     }
     282          95 :     Next();
     283          95 :     return true;
     284             : }
     285             : 
     286             : 
     287             : 
     288         108 : void SbiParser::TestEoln()
     289             : {
     290         108 :     if( !IsEoln( Next() ) )
     291             :     {
     292           0 :         Error( SbERR_EXPECTED, EOLN );
     293           0 :         while( !IsEoln( Next() ) ) {}
     294             :     }
     295         108 : }
     296             : 
     297             : 
     298             : 
     299         566 : void SbiParser::StmntBlock( SbiToken eEnd )
     300             : {
     301         566 :     SbiToken xe = eEndTok;
     302         566 :     eEndTok = eEnd;
     303         566 :     while( !bAbort && Parse() ) {}
     304         566 :     eEndTok = xe;
     305         566 :     if( IsEof() )
     306             :     {
     307           0 :         Error( SbERR_BAD_BLOCK, eEnd );
     308           0 :         bAbort = true;
     309             :     }
     310         566 : }
     311             : 
     312           0 : void SbiParser::SetCodeCompleting( const bool& b )
     313             : {
     314           0 :     bCodeCompleting = b;
     315           0 : }
     316             : 
     317       86468 : bool SbiParser::IsCodeCompleting() const
     318             : {
     319       86468 :     return bCodeCompleting;
     320             : }
     321             : 
     322       13968 : bool SbiParser::Parse()
     323             : {
     324       13968 :     if( bAbort ) return false;
     325             : 
     326       13968 :     EnableErrors();
     327             : 
     328       13968 :     bErrorIsSymbol = false;
     329       13968 :     Peek();
     330       13968 :     bErrorIsSymbol = true;
     331             : 
     332       13968 :     if( IsEof() )
     333             :     {
     334             :         // AB #33133: If no sub has been created before,
     335             :         // the global chain must be closed here!
     336             :         // AB #40689: Due to the new static-handling there
     337             :         // can be another nGblChain, so ask for it before.
     338         171 :         if( bNewGblDefs && nGblChain == 0 )
     339           0 :             nGblChain = aGen.Gen( _JUMP, 0 );
     340         171 :         return false;
     341             :     }
     342             : 
     343             : 
     344       13797 :     if( IsEoln( eCurTok ) )
     345             :     {
     346        7582 :         Next(); return true;
     347             :     }
     348             : 
     349        6215 :     if( !bSingleLineIf && MayBeLabel( true ) )
     350             :     {
     351             :         // is a label
     352          52 :         if( !pProc )
     353           0 :             Error( SbERR_NOT_IN_MAIN, aSym );
     354             :         else
     355          52 :             pProc->GetLabels().Define( aSym );
     356          52 :         Next(); Peek();
     357             : 
     358          52 :         if( IsEoln( eCurTok ) )
     359             :         {
     360          52 :             Next(); return true;
     361             :         }
     362             :     }
     363             : 
     364             :     // end of parsing?
     365        6163 :     if( eCurTok == eEndTok ||
     366        4325 :         ( bVBASupportOn &&      // #i109075
     367        8652 :           (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
     368           2 :           (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
     369             :     {
     370         566 :         Next();
     371         566 :         if( eCurTok != NIL )
     372         566 :             aGen.Statement();
     373         566 :         return false;
     374             :     }
     375             : 
     376             :     // comment?
     377        5597 :     if( eCurTok == REM )
     378             :     {
     379           0 :         Next(); return true;
     380             :     }
     381             : 
     382             :         // In vba it's possible to do Error.foobar ( even if it results in
     383             :     // a runtime error
     384        5597 :         if ( eCurTok == _ERROR_ && IsVBASupportOn() ) // we probably need to define a subset of keywords where this madness applies e.g. if ( IsVBASupportOn() && SymbolCanBeRedined( eCurTok ) )
     385             :         {
     386           0 :             SbiTokenizer tokens( *(SbiTokenizer*)this );
     387           0 :             tokens.Next();
     388           0 :             if ( tokens.Peek()  == DOT )
     389             :             {
     390           0 :                 eCurTok = SYMBOL;
     391           0 :         ePush = eCurTok;
     392           0 :             }
     393             :     }
     394             :     // if there's a symbol, it's either a variable (LET)
     395             :     // or a SUB-procedure (CALL without brackets)
     396             :     // DOT for assignments in the WITH-block: .A=5
     397        5597 :     if( eCurTok == SYMBOL || eCurTok == DOT )
     398             :     {
     399        6320 :         if( !pProc )
     400           0 :             Error( SbERR_EXPECTED, SUB );
     401             :         else
     402             :         {
     403             :             // for correct line and column...
     404        3160 :             Next();
     405        3160 :             Push( eCurTok );
     406        3160 :             aGen.Statement();
     407        3160 :                 Symbol();
     408             :         }
     409             :     }
     410             :     else
     411             :     {
     412        2437 :         Next();
     413             : 
     414             :         // statement parsers
     415             : 
     416             :         const SbiStatement* p;
     417       67483 :         for( p = StmntTable; p->eTok != NIL; p++ )
     418       67483 :             if( p->eTok == eCurTok )
     419        2437 :                 break;
     420        2437 :         if( p->eTok != NIL )
     421             :         {
     422        2437 :             if( !pProc && !p->bMain )
     423           0 :                 Error( SbERR_NOT_IN_MAIN, eCurTok );
     424        2437 :             else if( pProc && !p->bSubr )
     425           0 :                 Error( SbERR_NOT_IN_SUBR, eCurTok );
     426             :             else
     427             :             {
     428             :                 // AB #41606/#40689: Due to the new static-handling there
     429             :                 // can be another nGblChain, so ask for it before.
     430        2642 :                 if( bNewGblDefs && nGblChain == 0 &&
     431         406 :                     ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
     432             :                 {
     433          34 :                     nGblChain = aGen.Gen( _JUMP, 0 );
     434          34 :                     bNewGblDefs = false;
     435             :                 }
     436             :                 // statement-opcode at the beginning of a sub, too, please
     437        4874 :                 if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
     438        3468 :                         eCurTok == SUB || eCurTok == FUNCTION )
     439        2171 :                     aGen.Statement();
     440        2437 :                 (this->*( p->Func ) )();
     441        2437 :                 SbxError nSbxErr = SbxBase::GetError();
     442        2437 :                 if( nSbxErr )
     443           0 :                     SbxBase::ResetError(), Error( (SbError)nSbxErr );
     444             :             }
     445             :         }
     446             :         else
     447           0 :             Error( SbERR_UNEXPECTED, eCurTok );
     448             :     }
     449             : 
     450             :     // test for the statement's end -
     451             :     // might also be an ELSE, as there must not necessary be a : before the ELSE!
     452             : 
     453        5597 :     if( !IsEos() )
     454             :     {
     455         962 :         Peek();
     456         962 :         if( !IsEos() && eCurTok != ELSE )
     457             :         {
     458             :             // if the parsing has been aborted, jump over to the ":"
     459           0 :             Error( SbERR_UNEXPECTED, eCurTok );
     460           0 :             while( !IsEos() ) Next();
     461             :         }
     462             :     }
     463             :     // The parser aborts at the end, the
     464             :     // next token has not been fetched yet!
     465        5597 :     return true;
     466             : }
     467             : 
     468             : 
     469          53 : SbiExprNode* SbiParser::GetWithVar()
     470             : {
     471          53 :     if( pWithVar )
     472          53 :         return pWithVar;
     473             : 
     474           0 :     SbiParseStack* p = pStack;
     475           0 :     while( p )
     476             :     {
     477             :         // LoopVar can at the moment only be for with
     478           0 :         if( p->pWithVar )
     479           0 :             return p->pWithVar;
     480           0 :         p = p->pNext;
     481             :     }
     482           0 :     return NULL;
     483             : }
     484             : 
     485             : 
     486             : // assignment or subroutine call
     487             : 
     488        3160 : void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
     489             : {
     490        3160 :     SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
     491        3160 :     SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );
     492             : 
     493        3160 :     bool bEQ = ( Peek() == EQ );
     494        3160 :     if( !bEQ && bVBASupportOn && aVar.IsBracket() )
     495           0 :         Error( SbERR_EXPECTED, "=" );
     496             : 
     497        3160 :     RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
     498        3160 :     bool bSpecialMidHandling = false;
     499        3160 :     SbiSymDef* pDef = aVar.GetRealVar();
     500        3160 :     if( bEQ && pDef && pDef->GetScope() == SbRTL )
     501             :     {
     502           1 :         OUString aRtlName = pDef->GetName();
     503           1 :         if( aRtlName.equalsIgnoreAsciiCase("Mid") )
     504             :         {
     505           0 :             SbiExprNode* pExprNode = aVar.GetExprNode();
     506           0 :             if( pExprNode && pExprNode->GetNodeType() == SbxVARVAL )
     507             :             {
     508           0 :                 SbiExprList* pPar = pExprNode->GetParameters();
     509           0 :                 short nParCount = pPar ? pPar->GetSize() : 0;
     510           0 :                 if( nParCount == 2 || nParCount == 3 )
     511             :                 {
     512           0 :                     if( nParCount == 2 )
     513           0 :                         pPar->addExpression( new SbiExpression( this, -1, SbxLONG ) );
     514             : 
     515           0 :                     TestToken( EQ );
     516           0 :                     pPar->addExpression( new SbiExpression( this ) );
     517             : 
     518           0 :                     bSpecialMidHandling = true;
     519             :                 }
     520             :             }
     521           1 :         }
     522             :     }
     523        3160 :     aVar.Gen( eRecMode );
     524        3160 :     if( !bSpecialMidHandling )
     525             :     {
     526        3160 :         if( !bEQ )
     527             :         {
     528         872 :             aGen.Gen( _GET );
     529             :         }
     530             :         else
     531             :         {
     532             :             // so it must be an assignment!
     533        2288 :             if( !aVar.IsLvalue() )
     534           0 :                 Error( SbERR_LVALUE_EXPECTED );
     535        2288 :             TestToken( EQ );
     536        2288 :             SbiExpression aExpr( this );
     537        2288 :             aExpr.Gen();
     538        2288 :             SbiOpcode eOp = _PUT;
     539        2288 :             if( pDef )
     540             :             {
     541        2288 :                 if( pDef->GetConstDef() )
     542           0 :                     Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     543        2288 :                 if( pDef->GetType() == SbxOBJECT )
     544             :                 {
     545         100 :                     eOp = _SET;
     546         100 :                     if( pDef->GetTypeId() )
     547             :                     {
     548           8 :                         aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     549        3168 :                         return;
     550             :                     }
     551             :                 }
     552             :             }
     553        2280 :             aGen.Gen( eOp );
     554             :         }
     555        3152 :     }
     556             : }
     557             : 
     558             : 
     559           0 : void SbiParser::Assign()
     560             : {
     561           0 :     SbiExpression aLvalue( this, SbLVALUE );
     562           0 :     TestToken( EQ );
     563           0 :     SbiExpression aExpr( this );
     564           0 :     aLvalue.Gen();
     565           0 :     aExpr.Gen();
     566           0 :     sal_uInt16 nLen = 0;
     567           0 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     568             :     {
     569           0 :         if( pDef->GetConstDef() )
     570           0 :             Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     571           0 :         nLen = aLvalue.GetRealVar()->GetLen();
     572             :     }
     573           0 :     if( nLen )
     574           0 :         aGen.Gen( _PAD, nLen );
     575           0 :     aGen.Gen( _PUT );
     576           0 : }
     577             : 
     578             : // assignments of an object-variable
     579             : 
     580         146 : void SbiParser::Set()
     581             : {
     582         146 :     SbiExpression aLvalue( this, SbLVALUE );
     583         146 :     SbxDataType eType = aLvalue.GetType();
     584         146 :     if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
     585           0 :         Error( SbERR_INVALID_OBJECT );
     586         146 :     TestToken( EQ );
     587         146 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     588         146 :     if( pDef->GetConstDef() )
     589           0 :         Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     590             : 
     591         146 :     SbiToken eTok = Peek();
     592         146 :     if( eTok == NEW )
     593             :     {
     594           0 :         Next();
     595           0 :         OUString aStr;
     596           0 :         SbiSymDef* pTypeDef = new SbiSymDef( aStr );
     597           0 :         TypeDecl( *pTypeDef, true );
     598             : 
     599           0 :         aLvalue.Gen();
     600           0 :         aGen.Gen( _CREATE, pDef->GetId(), pTypeDef->GetTypeId() );
     601           0 :         aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     602             :     }
     603             :     else
     604             :     {
     605         146 :         SbiExpression aExpr( this );
     606         146 :         aLvalue.Gen();
     607         146 :         aExpr.Gen();
     608             :         // Its a good idea to distinguish between
     609             :         // set something = another &
     610             :         // something = another
     611             :         // ( its necessary for vba objects where set is object
     612             :         // specific and also doesn't involve processing default params )
     613         146 :         if( pDef->GetTypeId() )
     614             :         {
     615         121 :             if ( bVBASupportOn )
     616         121 :                 aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
     617             :             else
     618           0 :                 aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     619             :         }
     620             :         else
     621             :         {
     622          25 :             if ( bVBASupportOn )
     623          24 :                 aGen.Gen( _VBASET );
     624             :             else
     625           1 :                 aGen.Gen( _SET );
     626         146 :         }
     627         146 :     }
     628         146 : }
     629             : 
     630             : // JSM 07.10.95
     631           0 : void SbiParser::LSet()
     632             : {
     633           0 :     SbiExpression aLvalue( this, SbLVALUE );
     634           0 :     if( aLvalue.GetType() != SbxSTRING )
     635             :     {
     636           0 :         Error( SbERR_INVALID_OBJECT );
     637             :     }
     638           0 :     TestToken( EQ );
     639           0 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     640           0 :     if( pDef && pDef->GetConstDef() )
     641             :     {
     642           0 :         Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     643             :     }
     644           0 :     SbiExpression aExpr( this );
     645           0 :     aLvalue.Gen();
     646           0 :     aExpr.Gen();
     647           0 :     aGen.Gen( _LSET );
     648           0 : }
     649             : 
     650             : // JSM 07.10.95
     651           0 : void SbiParser::RSet()
     652             : {
     653           0 :     SbiExpression aLvalue( this, SbLVALUE );
     654           0 :     if( aLvalue.GetType() != SbxSTRING )
     655             :     {
     656           0 :         Error( SbERR_INVALID_OBJECT );
     657             :     }
     658           0 :     TestToken( EQ );
     659           0 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     660           0 :     if( pDef && pDef->GetConstDef() )
     661           0 :         Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     662           0 :     SbiExpression aExpr( this );
     663           0 :     aLvalue.Gen();
     664           0 :     aExpr.Gen();
     665           0 :     aGen.Gen( _RSET );
     666           0 : }
     667             : 
     668             : // DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR and so on
     669             : 
     670           0 : void SbiParser::DefXXX()
     671             : {
     672             :     sal_Unicode ch1, ch2;
     673           0 :     SbxDataType t = SbxDataType( eCurTok - DEFINT + SbxINTEGER );
     674             : 
     675           0 :     while( !bAbort )
     676             :     {
     677           0 :         if( Next() != SYMBOL ) break;
     678           0 :         ch1 = aSym.toAsciiUpperCase()[0];
     679           0 :         ch2 = 0;
     680           0 :         if( Peek() == MINUS )
     681             :         {
     682           0 :             Next();
     683           0 :             if( Next() != SYMBOL ) Error( SbERR_SYMBOL_EXPECTED );
     684             :             else
     685             :             {
     686           0 :                 ch2 = aSym.toAsciiUpperCase()[0];
     687           0 :                 if( ch2 < ch1 ) Error( SbERR_SYNTAX ), ch2 = 0;
     688             :             }
     689             :         }
     690           0 :         if (!ch2) ch2 = ch1;
     691           0 :         ch1 -= 'A'; ch2 -= 'A';
     692           0 :         for (; ch1 <= ch2; ch1++) eDefTypes[ ch1 ] = t;
     693           0 :         if( !TestComma() ) break;
     694             :     }
     695           0 : }
     696             : 
     697             : // STOP/SYSTEM
     698             : 
     699           1 : void SbiParser::Stop()
     700             : {
     701           1 :     aGen.Gen( _STOP );
     702           1 :     Peek();     // #35694: only Peek(), so that EOL is recognized in Single-Line-If
     703           1 : }
     704             : 
     705             : // IMPLEMENTS
     706             : 
     707           0 : void SbiParser::Implements()
     708             : {
     709           0 :     if( !bClassModule )
     710             :     {
     711           0 :         Error( SbERR_UNEXPECTED, IMPLEMENTS );
     712           0 :         return;
     713             :     }
     714             : 
     715           0 :     Peek();
     716           0 :     if( eCurTok != SYMBOL )
     717             :     {
     718           0 :         Error( SbERR_SYMBOL_EXPECTED );
     719           0 :         return;
     720             :     }
     721             : 
     722           0 :     OUString aImplementedIface = aSym;
     723           0 :     Next();
     724           0 :     if( Peek() == DOT )
     725             :     {
     726           0 :         OUString aDotStr( '.' );
     727           0 :         while( Peek() == DOT )
     728             :         {
     729           0 :             aImplementedIface += aDotStr;
     730           0 :             Next();
     731           0 :             SbiToken ePeekTok = Peek();
     732           0 :             if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
     733             :             {
     734           0 :                 Next();
     735           0 :                 aImplementedIface += aSym;
     736             :             }
     737             :             else
     738             :             {
     739           0 :                 Next();
     740           0 :                 Error( SbERR_SYMBOL_EXPECTED );
     741           0 :                 break;
     742             :             }
     743           0 :         }
     744             :     }
     745           0 :     aIfaceVector.push_back( aImplementedIface );
     746             : }
     747             : 
     748         274 : void SbiParser::EnableCompatibility()
     749             : {
     750         274 :     if( !bCompatible )
     751         137 :         AddConstants();
     752         274 :     bCompatible = true;
     753         274 : }
     754             : 
     755             : // OPTION
     756             : 
     757         154 : void SbiParser::Option()
     758             : {
     759         154 :     switch( Next() )
     760             :     {
     761             :         case BASIC_EXPLICIT:
     762          16 :             bExplicit = true; break;
     763             :         case BASE:
     764           1 :             if( Next() == NUMBER )
     765             :             {
     766           1 :                 if( nVal == 0 || nVal == 1 )
     767             :                 {
     768           1 :                     nBase = (short) nVal;
     769           1 :                     break;
     770             :                 }
     771             :             }
     772           0 :             Error( SbERR_EXPECTED, "0/1" );
     773           0 :             break;
     774             :         case PRIVATE:
     775             :         {
     776           0 :             OUString aString = SbiTokenizer::Symbol(Next());
     777           0 :             if( !aString.equalsIgnoreAsciiCase("Module") )
     778             :             {
     779           0 :                 Error( SbERR_EXPECTED, "Module" );
     780             :             }
     781           0 :             break;
     782             :         }
     783             :         case COMPARE:
     784             :         {
     785           0 :             SbiToken eTok = Next();
     786           0 :             if( eTok == BINARY )
     787             :             {
     788           0 :                 bText = false;
     789             :             }
     790           0 :             else if( eTok == SYMBOL && GetSym().equalsIgnoreAsciiCase("text") )
     791             :             {
     792           0 :                 bText = true;
     793             :             }
     794             :             else
     795             :             {
     796           0 :                 Error( SbERR_EXPECTED, "Text/Binary" );
     797             :             }
     798           0 :             break;
     799             :         }
     800             :         case COMPATIBLE:
     801           0 :             EnableCompatibility();
     802           0 :             break;
     803             : 
     804             :         case CLASSMODULE:
     805           0 :             bClassModule = true;
     806           0 :             aGen.GetModule().SetModuleType( com::sun::star::script::ModuleType::CLASS );
     807           0 :             break;
     808             :         case VBASUPPORT: // Option VBASupport used to override the module mode ( in fact this must reset the mode
     809         137 :             if( Next() == NUMBER )
     810             :             {
     811         137 :                 if ( nVal == 1 || nVal == 0 )
     812             :                 {
     813         137 :                     bVBASupportOn = ( nVal == 1 );
     814         137 :                     if ( bVBASupportOn )
     815             :                     {
     816         137 :                         EnableCompatibility();
     817             :                     }
     818             :                     // if the module setting is different
     819             :                     // reset it to what the Option tells us
     820         137 :                     if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
     821             :                     {
     822           0 :                         aGen.GetModule().SetVBACompat( bVBASupportOn );
     823             :                     }
     824         137 :                     break;
     825             :                 }
     826             :             }
     827           0 :             Error( SbERR_EXPECTED, "0/1" );
     828           0 :             break;
     829             :         default:
     830           0 :             Error( SbERR_BAD_OPTION, eCurTok );
     831             :     }
     832         154 : }
     833             : 
     834        1233 : void addStringConst( SbiSymPool& rPool, const char* pSym, const OUString& rStr )
     835             : {
     836        1233 :     SbiConstDef* pConst = new SbiConstDef( OUString::createFromAscii( pSym ) );
     837        1233 :     pConst->SetType( SbxSTRING );
     838        1233 :     pConst->Set( rStr );
     839        1233 :     rPool.Add( pConst );
     840        1233 : }
     841             : 
     842        1096 : inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
     843             : {
     844        1096 :     addStringConst( rPool, pSym, OUString::createFromAscii( pStr ) );
     845        1096 : }
     846             : 
     847         137 : void SbiParser::AddConstants( void )
     848             : {
     849             :     // #113063 Create constant RTL symbols
     850         137 :     addStringConst( aPublics, "vbCr", "\x0D" );
     851         137 :     addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
     852         137 :     addStringConst( aPublics, "vbFormFeed", "\x0C" );
     853         137 :     addStringConst( aPublics, "vbLf", "\x0A" );
     854             : #ifndef WNT
     855         137 :     addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
     856             : #else
     857             :     addStringConst( aPublics, "vbNewLine", "\x0A" );
     858             : #endif
     859         137 :     addStringConst( aPublics, "vbNullString", "" );
     860         137 :     addStringConst( aPublics, "vbTab", "\x09" );
     861         137 :     addStringConst( aPublics, "vbVerticalTab", "\x0B" );
     862             : 
     863             :     // Force length 1 and make char 0 afterwards
     864         137 :     OUString aNullCharStr((sal_Unicode)0);
     865         137 :     addStringConst( aPublics, "vbNullChar", aNullCharStr );
     866         137 : }
     867             : 
     868             : // ERROR n
     869             : 
     870           0 : void SbiParser::ErrorStmnt()
     871             : {
     872           0 :     SbiExpression aPar( this );
     873           0 :     aPar.Gen();
     874           0 :     aGen.Gen( _ERROR );
     875           0 : }
     876             : 
     877             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10