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

Generated by: LCOV version 1.11