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

Generated by: LCOV version 1.10