LCOV - code coverage report
Current view: top level - basic/source/comp - parser.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 419 0.0 %
Date: 2014-04-14 Functions: 0 29 0.0 %
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           0 : SbiParser::SbiParser( StarBASIC* pb, SbModule* pm )
     112           0 :         : SbiTokenizer( pm->GetSource32(), pb ),
     113             :           aGblStrings( this ),
     114             :           aLclStrings( this ),
     115             :           aGlobals( aGblStrings, SbGLOBAL ),
     116             :           aPublics( aGblStrings, SbPUBLIC ),
     117             :           aRtlSyms( aGblStrings, SbRTL ),
     118           0 :           aGen( *pm, this, 1024 )
     119             : {
     120           0 :     pBasic   = pb;
     121           0 :     eCurExpr = SbSYMBOL;
     122           0 :     eEndTok  = NIL;
     123           0 :     pProc    = NULL;
     124           0 :     pStack   = NULL;
     125           0 :     pWithVar = NULL;
     126           0 :     nBase    = 0;
     127             :     bText    =
     128             :     bGblDefs =
     129             :     bNewGblDefs =
     130             :     bSingleLineIf =
     131             :     bCodeCompleting =
     132           0 :     bExplicit = false;
     133           0 :     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           0 :     pPool    = &aPublics;
     136           0 :     for( short i = 0; i < 26; i++ )
     137           0 :         eDefTypes[ i ] = SbxVARIANT;    // no explicit default type
     138             : 
     139           0 :     aPublics.SetParent( &aGlobals );
     140           0 :     aGlobals.SetParent( &aRtlSyms );
     141             : 
     142             : 
     143           0 :     nGblChain = aGen.Gen( _JUMP, 0 );
     144             : 
     145           0 :     rTypeArray = new SbxArray; // array for user defined types
     146           0 :     rEnumArray = new SbxArray; // array for Enum types
     147           0 :     bVBASupportOn = pm->IsVBACompat();
     148           0 :     if ( bVBASupportOn )
     149           0 :         EnableCompatibility();
     150             : 
     151           0 : }
     152             : 
     153             : // part of the runtime-library?
     154           0 : SbiSymDef* SbiParser::CheckRTLForSym( const OUString& rSym, SbxDataType eType )
     155             : {
     156           0 :     SbxVariable* pVar = GetBasic()->GetRtl()->Find( rSym, SbxCLASS_DONTCARE );
     157           0 :     SbiSymDef* pDef = NULL;
     158           0 :     if( pVar )
     159             :     {
     160           0 :         if( pVar->IsA( TYPE(SbxMethod) ) )
     161             :         {
     162           0 :             SbiProcDef* pProc_ = aRtlSyms.AddProc( rSym );
     163           0 :             pProc_->SetType( pVar->GetType() );
     164           0 :             pDef = pProc_;
     165             :         }
     166             :         else
     167             :         {
     168           0 :             pDef = aRtlSyms.AddSym( rSym );
     169           0 :             pDef->SetType( eType );
     170             :         }
     171             :     }
     172           0 :     return pDef;
     173             : }
     174             : 
     175             : // close global chain
     176             : 
     177           0 : bool SbiParser::HasGlobalCode()
     178             : {
     179           0 :     if( bGblDefs && nGblChain )
     180             :     {
     181           0 :         aGen.BackChain( nGblChain );
     182           0 :         aGen.Gen( _LEAVE );
     183           0 :         nGblChain = 0;
     184             :     }
     185           0 :     return bGblDefs;
     186             : }
     187             : 
     188           0 : void SbiParser::OpenBlock( SbiToken eTok, SbiExprNode* pVar )
     189             : {
     190           0 :     SbiParseStack* p = new SbiParseStack;
     191           0 :     p->eExitTok = eTok;
     192           0 :     p->nChain   = 0;
     193           0 :     p->pWithVar = pWithVar;
     194           0 :     p->pNext    = pStack;
     195           0 :     pStack      = p;
     196           0 :     pWithVar    = pVar;
     197             : 
     198             :     // #29955 service the for-loop level
     199           0 :     if( eTok == FOR )
     200           0 :         aGen.IncForLevel();
     201           0 : }
     202             : 
     203           0 : void SbiParser::CloseBlock()
     204             : {
     205           0 :     if( pStack )
     206             :     {
     207           0 :         SbiParseStack* p = pStack;
     208             : 
     209             :         // #29955 service the for-loop level
     210           0 :         if( p->eExitTok == FOR )
     211           0 :             aGen.DecForLevel();
     212             : 
     213           0 :         aGen.BackChain( p->nChain );
     214           0 :         pStack = p->pNext;
     215           0 :         pWithVar = p->pWithVar;
     216           0 :         delete p;
     217             :     }
     218           0 : }
     219             : 
     220             : // EXIT ...
     221             : 
     222           0 : void SbiParser::Exit()
     223             : {
     224           0 :     SbiToken eTok = Next();
     225           0 :     for( SbiParseStack* p = pStack; p; p = p->pNext )
     226             :     {
     227           0 :         SbiToken eExitTok = p->eExitTok;
     228           0 :         if( eTok == eExitTok ||
     229           0 :             (eTok == PROPERTY && (eExitTok == GET || eExitTok == LET) ) )   // #i109051
     230             :         {
     231           0 :             p->nChain = aGen.Gen( _JUMP, p->nChain );
     232           0 :             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           0 : bool SbiParser::TestSymbol( bool bKwdOk )
     242             : {
     243           0 :     Peek();
     244           0 :     if( eCurTok == SYMBOL || ( bKwdOk && IsKwd( eCurTok ) ) )
     245             :     {
     246           0 :         Next(); return true;
     247             :     }
     248           0 :     Error( SbERR_SYMBOL_EXPECTED );
     249           0 :     return false;
     250             : }
     251             : 
     252             : 
     253             : 
     254           0 : bool SbiParser::TestToken( SbiToken t )
     255             : {
     256           0 :     if( Peek() == t )
     257             :     {
     258           0 :         Next(); return true;
     259             :     }
     260             :     else
     261             :     {
     262           0 :         Error( SbERR_EXPECTED, t );
     263           0 :         return false;
     264             :     }
     265             : }
     266             : 
     267             : 
     268             : 
     269           0 : bool SbiParser::TestComma()
     270             : {
     271           0 :     SbiToken eTok = Peek();
     272           0 :     if( IsEoln( eTok ) )
     273             :     {
     274           0 :         Next();
     275           0 :         return false;
     276             :     }
     277           0 :     else if( eTok != COMMA )
     278             :     {
     279           0 :         Error( SbERR_EXPECTED, COMMA );
     280           0 :         return false;
     281             :     }
     282           0 :     Next();
     283           0 :     return true;
     284             : }
     285             : 
     286             : 
     287             : 
     288           0 : void SbiParser::TestEoln()
     289             : {
     290           0 :     if( !IsEoln( Next() ) )
     291             :     {
     292           0 :         Error( SbERR_EXPECTED, EOLN );
     293           0 :         while( !IsEoln( Next() ) ) {}
     294             :     }
     295           0 : }
     296             : 
     297             : 
     298             : 
     299           0 : void SbiParser::StmntBlock( SbiToken eEnd )
     300             : {
     301           0 :     SbiToken xe = eEndTok;
     302           0 :     eEndTok = eEnd;
     303           0 :     while( !bAbort && Parse() ) {}
     304           0 :     eEndTok = xe;
     305           0 :     if( IsEof() )
     306             :     {
     307           0 :         Error( SbERR_BAD_BLOCK, eEnd );
     308           0 :         bAbort = true;
     309             :     }
     310           0 : }
     311             : 
     312           0 : void SbiParser::SetCodeCompleting( const bool& b )
     313             : {
     314           0 :     bCodeCompleting = b;
     315           0 : }
     316             : 
     317           0 : bool SbiParser::IsCodeCompleting() const
     318             : {
     319           0 :     return bCodeCompleting;
     320             : }
     321             : 
     322           0 : bool SbiParser::Parse()
     323             : {
     324           0 :     if( bAbort ) return false;
     325             : 
     326           0 :     EnableErrors();
     327             : 
     328           0 :     bErrorIsSymbol = false;
     329           0 :     Peek();
     330           0 :     bErrorIsSymbol = true;
     331             : 
     332           0 :     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           0 :         if( bNewGblDefs && nGblChain == 0 )
     339           0 :             nGblChain = aGen.Gen( _JUMP, 0 );
     340           0 :         return false;
     341             :     }
     342             : 
     343             : 
     344           0 :     if( IsEoln( eCurTok ) )
     345             :     {
     346           0 :         Next(); return true;
     347             :     }
     348             : 
     349           0 :     if( !bSingleLineIf && MayBeLabel( true ) )
     350             :     {
     351             :         // is a label
     352           0 :         if( !pProc )
     353           0 :             Error( SbERR_NOT_IN_MAIN, aSym );
     354             :         else
     355           0 :             pProc->GetLabels().Define( aSym );
     356           0 :         Next(); Peek();
     357             : 
     358           0 :         if( IsEoln( eCurTok ) )
     359             :         {
     360           0 :             Next(); return true;
     361             :         }
     362             :     }
     363             : 
     364             :     // end of parsing?
     365           0 :     if( eCurTok == eEndTok ||
     366           0 :         ( bVBASupportOn &&      // #i109075
     367           0 :           (eCurTok == ENDFUNC || eCurTok == ENDPROPERTY || eCurTok == ENDSUB) &&
     368           0 :           (eEndTok == ENDFUNC || eEndTok == ENDPROPERTY || eEndTok == ENDSUB) ) )
     369             :     {
     370           0 :         Next();
     371           0 :         if( eCurTok != NIL )
     372           0 :             aGen.Statement();
     373           0 :         return false;
     374             :     }
     375             : 
     376             :     // comment?
     377           0 :     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           0 :         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           0 :     if( eCurTok == SYMBOL || eCurTok == DOT )
     398             :     {
     399           0 :         if( !pProc )
     400           0 :             Error( SbERR_EXPECTED, SUB );
     401             :         else
     402             :         {
     403             :             // for correct line and column...
     404           0 :             Next();
     405           0 :             Push( eCurTok );
     406           0 :             aGen.Statement();
     407           0 :                 Symbol();
     408             :         }
     409             :     }
     410             :     else
     411             :     {
     412           0 :         Next();
     413             : 
     414             :         // statement parsers
     415             : 
     416             :         const SbiStatement* p;
     417           0 :         for( p = StmntTable; p->eTok != NIL; p++ )
     418           0 :             if( p->eTok == eCurTok )
     419           0 :                 break;
     420           0 :         if( p->eTok != NIL )
     421             :         {
     422           0 :             if( !pProc && !p->bMain )
     423           0 :                 Error( SbERR_NOT_IN_MAIN, eCurTok );
     424           0 :             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           0 :                 if( bNewGblDefs && nGblChain == 0 &&
     431           0 :                     ( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ) )
     432             :                 {
     433           0 :                     nGblChain = aGen.Gen( _JUMP, 0 );
     434           0 :                     bNewGblDefs = false;
     435             :                 }
     436             :                 // statement-opcode at the beginning of a sub, too, please
     437           0 :                 if( ( p->bSubr && (eCurTok != STATIC || Peek() == SUB || Peek() == FUNCTION ) ) ||
     438           0 :                         eCurTok == SUB || eCurTok == FUNCTION )
     439           0 :                     aGen.Statement();
     440           0 :                 (this->*( p->Func ) )();
     441           0 :                 SbxError nSbxErr = SbxBase::GetError();
     442           0 :                 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           0 :     if( !IsEos() )
     454             :     {
     455           0 :         Peek();
     456           0 :         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           0 :     return true;
     466             : }
     467             : 
     468             : 
     469           0 : SbiExprNode* SbiParser::GetWithVar()
     470             : {
     471           0 :     if( pWithVar )
     472           0 :         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           0 : void SbiParser::Symbol( const KeywordSymbolInfo* pKeywordSymbolInfo )
     489             : {
     490           0 :     SbiExprMode eMode = bVBASupportOn ? EXPRMODE_STANDALONE : EXPRMODE_STANDARD;
     491           0 :     SbiExpression aVar( this, SbSYMBOL, eMode, pKeywordSymbolInfo );
     492             : 
     493           0 :     bool bEQ = ( Peek() == EQ );
     494           0 :     if( !bEQ && bVBASupportOn && aVar.IsBracket() )
     495           0 :         Error( SbERR_EXPECTED, "=" );
     496             : 
     497           0 :     RecursiveMode eRecMode = ( bEQ ? PREVENT_CALL : FORCE_CALL );
     498           0 :     bool bSpecialMidHandling = false;
     499           0 :     SbiSymDef* pDef = aVar.GetRealVar();
     500           0 :     if( bEQ && pDef && pDef->GetScope() == SbRTL )
     501             :     {
     502           0 :         OUString aRtlName = pDef->GetName();
     503           0 :         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           0 :         }
     522             :     }
     523           0 :     aVar.Gen( eRecMode );
     524           0 :     if( !bSpecialMidHandling )
     525             :     {
     526           0 :         if( !bEQ )
     527             :         {
     528           0 :             aGen.Gen( _GET );
     529             :         }
     530             :         else
     531             :         {
     532             :             // so it must be an assignment!
     533           0 :             if( !aVar.IsLvalue() )
     534           0 :                 Error( SbERR_LVALUE_EXPECTED );
     535           0 :             TestToken( EQ );
     536           0 :             SbiExpression aExpr( this );
     537           0 :             aExpr.Gen();
     538           0 :             SbiOpcode eOp = _PUT;
     539           0 :             if( pDef )
     540             :             {
     541           0 :                 if( pDef->GetConstDef() )
     542           0 :                     Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     543           0 :                 if( pDef->GetType() == SbxOBJECT )
     544             :                 {
     545           0 :                     eOp = _SET;
     546           0 :                     if( pDef->GetTypeId() )
     547             :                     {
     548           0 :                         aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     549           0 :                         return;
     550             :                     }
     551             :                 }
     552             :             }
     553           0 :             aGen.Gen( eOp );
     554             :         }
     555           0 :     }
     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           0 : void SbiParser::Set()
     581             : {
     582           0 :     SbiExpression aLvalue( this, SbLVALUE );
     583           0 :     SbxDataType eType = aLvalue.GetType();
     584           0 :     if( eType != SbxOBJECT && eType != SbxEMPTY && eType != SbxVARIANT )
     585           0 :         Error( SbERR_INVALID_OBJECT );
     586           0 :     TestToken( EQ );
     587           0 :     SbiSymDef* pDef = aLvalue.GetRealVar();
     588           0 :     if( pDef->GetConstDef() )
     589           0 :         Error( SbERR_DUPLICATE_DEF, pDef->GetName() );
     590             : 
     591           0 :     SbiToken eTok = Peek();
     592           0 :     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           0 :         SbiExpression aExpr( this );
     606           0 :         aLvalue.Gen();
     607           0 :         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           0 :         if( pDef->GetTypeId() )
     614             :         {
     615           0 :             if ( bVBASupportOn )
     616           0 :                 aGen.Gen( _VBASETCLASS, pDef->GetTypeId() );
     617             :             else
     618           0 :                 aGen.Gen( _SETCLASS, pDef->GetTypeId() );
     619             :         }
     620             :         else
     621             :         {
     622           0 :             if ( bVBASupportOn )
     623           0 :                 aGen.Gen( _VBASET );
     624             :             else
     625           0 :                 aGen.Gen( _SET );
     626           0 :         }
     627           0 :     }
     628           0 : }
     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           0 : void SbiParser::Stop()
     700             : {
     701           0 :     aGen.Gen( _STOP );
     702           0 :     Peek();     // #35694: only Peek(), so that EOL is recognized in Single-Line-If
     703           0 : }
     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           0 : void SbiParser::EnableCompatibility()
     749             : {
     750           0 :     if( !bCompatible )
     751           0 :         AddConstants();
     752           0 :     bCompatible = true;
     753           0 : }
     754             : 
     755             : // OPTION
     756             : 
     757           0 : void SbiParser::Option()
     758             : {
     759           0 :     switch( Next() )
     760             :     {
     761             :         case BASIC_EXPLICIT:
     762           0 :             bExplicit = true; break;
     763             :         case BASE:
     764           0 :             if( Next() == NUMBER )
     765             :             {
     766           0 :                 if( nVal == 0 || nVal == 1 )
     767             :                 {
     768           0 :                     nBase = (short) nVal;
     769           0 :                     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           0 :             if( Next() == NUMBER )
     810             :             {
     811           0 :                 if ( nVal == 1 || nVal == 0 )
     812             :                 {
     813           0 :                     bVBASupportOn = ( nVal == 1 );
     814           0 :                     if ( bVBASupportOn )
     815             :                     {
     816           0 :                         EnableCompatibility();
     817             :                     }
     818             :                     // if the module setting is different
     819             :                     // reset it to what the Option tells us
     820           0 :                     if ( bVBASupportOn != aGen.GetModule().IsVBACompat() )
     821             :                     {
     822           0 :                         aGen.GetModule().SetVBACompat( bVBASupportOn );
     823             :                     }
     824           0 :                     break;
     825             :                 }
     826             :             }
     827           0 :             Error( SbERR_EXPECTED, "0/1" );
     828           0 :             break;
     829             :         default:
     830           0 :             Error( SbERR_BAD_OPTION, eCurTok );
     831             :     }
     832           0 : }
     833             : 
     834           0 : void addStringConst( SbiSymPool& rPool, const char* pSym, const OUString& rStr )
     835             : {
     836           0 :     SbiConstDef* pConst = new SbiConstDef( OUString::createFromAscii( pSym ) );
     837           0 :     pConst->SetType( SbxSTRING );
     838           0 :     pConst->Set( rStr );
     839           0 :     rPool.Add( pConst );
     840           0 : }
     841             : 
     842           0 : inline void addStringConst( SbiSymPool& rPool, const char* pSym, const char* pStr )
     843             : {
     844           0 :     addStringConst( rPool, pSym, OUString::createFromAscii( pStr ) );
     845           0 : }
     846             : 
     847           0 : void SbiParser::AddConstants( void )
     848             : {
     849             :     // #113063 Create constant RTL symbols
     850           0 :     addStringConst( aPublics, "vbCr", "\x0D" );
     851           0 :     addStringConst( aPublics, "vbCrLf", "\x0D\x0A" );
     852           0 :     addStringConst( aPublics, "vbFormFeed", "\x0C" );
     853           0 :     addStringConst( aPublics, "vbLf", "\x0A" );
     854             : #ifndef WNT
     855           0 :     addStringConst( aPublics, "vbNewLine", "\x0D\x0A" );
     856             : #else
     857             :     addStringConst( aPublics, "vbNewLine", "\x0A" );
     858             : #endif
     859           0 :     addStringConst( aPublics, "vbNullString", "" );
     860           0 :     addStringConst( aPublics, "vbTab", "\x09" );
     861           0 :     addStringConst( aPublics, "vbVerticalTab", "\x0B" );
     862             : 
     863             :     // Force length 1 and make char 0 afterwards
     864           0 :     OUString aNullCharStr((sal_Unicode)0);
     865           0 :     addStringConst( aPublics, "vbNullChar", aNullCharStr );
     866           0 : }
     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