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