/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// reading in a complete identifier // an identifier has the following form: // name[(Parameter)][.Name[(parameter)]]... // structure elements are coupled via the element pNext, // so that they're not in the tree.
// Are there parameters without brackets following? This may be a number, // a string, a symbol or also a comma (if the 1st parameter is missing)
staticbool DoParametersFollow( const SbiParser* p, SbiExprType eCurExpr, SbiToken eTok )
{ if( eTok == LPAREN )
{ returntrue;
} // but only if similar to CALL! if( !p->WhiteSpace() || eCurExpr != SbSYMBOL )
{ returnfalse;
} if ( eTok == NUMBER || eTok == MINUS || eTok == FIXSTRING ||
eTok == SYMBOL || eTok == COMMA || eTok == DOT || eTok == NOT || eTok == BYVAL )
{ returntrue;
} else// check for default params with reserved names ( e.g. names of tokens )
{
SbiTokenizer tokens( *static_cast<const SbiTokenizer*>(p) ); // Urk the Next() / Peek() semantics are... weird
tokens.Next(); if ( tokens.Peek() == ASSIGN )
{ returntrue;
}
} returnfalse;
}
// definition of a new symbol
static SbiSymDef* AddSym ( SbiToken eTok, SbiSymPool& rPool, SbiExprType eCurExpr, const OUString& rName, SbxDataType eType, const SbiExprList* pPar )
{
SbiSymDef* pDef; // A= is not a procedure bool bHasType = ( eTok == EQ || eTok == DOT ); if( ( !bHasType && eCurExpr == SbSYMBOL ) || pPar )
{ // so this is a procedure // the correct pool should be found out, as // procs must always get into a public pool
SbiSymPool* pPool = &rPool; if( pPool->GetScope() != SbPUBLIC )
{
pPool = &rPool.GetParser()->aPublics;
}
SbiProcDef* pProc = pPool->AddProc( rName );
// special treatment for Colls like Documents(1) if( eCurExpr == SbSTDEXPR )
{
bHasType = true;
}
pDef = pProc;
pDef->SetType( bHasType ? eType : SbxEMPTY ); if( pPar )
{ // generate dummy parameters for( sal_Int32 n = 1; n <= pPar->GetSize(); n++ )
{
OUString aPar = "PAR" + OUString::number( n );
pProc->GetParams().AddSym( aPar );
}
}
} else
{ // or a normal symbol
pDef = rPool.AddSym( rName );
pDef->SetType( eType );
} return pDef;
}
// currently even keywords are allowed (because of Dflt properties of the same name)
// i75443 check for additional sets of parameters while( eTok == LPAREN )
{ if( pvMoreParLcl == nullptr )
{
pvMoreParLcl.reset(new SbiExprListVector);
}
SbiExprListPtr pAddPar = SbiExprList::ParseParameters( pParser );
bError = bError || !pAddPar->IsValid();
pvMoreParLcl->push_back( std::move(pAddPar) );
eTok = pParser->Peek();
}
} // It might be an object part, if . or ! is following. // In case of . the variable must already be defined; // it's an object, if pDef is NULL after the search. bool bObj = ( ( eTok == DOT || eTok == EXCLAM )
&& !pParser->WhiteSpace() ); if( bObj )
{
bBracket = false; // Now the bracket for the first term is obsolete if( eType == SbxVARIANT )
{
eType = SbxOBJECT;
} else
{ // Name%. really does not work!
pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
bError = true;
}
} // Search:
SbiSymDef* pDef = pParser->pPool->Find( aSym ); if( !pDef )
{ // Part of the Runtime-Library? // from 31.3.1996: swapped out to parser-method // (is also needed in SbiParser::DefVar() in DIM.CXX)
pDef = pParser->CheckRTLForSym( aSym, eType );
// #i109184: Check if symbol is or later will be defined inside module
SbModule& rMod = pParser->aGen.GetModule(); if( rMod.FindMethod( aSym, SbxClassType::DontCare ) )
{
pDef = nullptr;
}
} if( !pDef )
{ if( bObj )
{
eType = SbxOBJECT;
}
pDef = AddSym( eTok, *pParser->pPool, eCurExpr, aSym, eType, pPar.get() ); // Looks like this is a local ( but undefined variable ) // if it is in a static procedure then make this Symbol // static if ( !bObj && pParser->pProc && pParser->pProc->IsStatic() )
{
pDef->SetStatic();
}
} else
{
// 0 parameters come up to () if( pDef->GetDims() )
{ if( pPar && pPar->GetSize() && pPar->GetSize() != pDef->GetDims() )
{
pParser->Error( ERRCODE_BASIC_WRONG_DIMS );
}
} if( pDef->IsDefinedAs() )
{
SbxDataType eDefType = pDef->GetType(); // #119187 Only error if types conflict if( eType >= SbxINTEGER && eType <= SbxSTRING && eType != eDefType )
{ // How? Define with AS first and take a Suffix then?
pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
bError = true;
} elseif ( eType == SbxVARIANT )
{ // if there's nothing named, take the type of the entry, // but only if the var hasn't been defined with AS XXX // so that we catch n% = 5 : print n
eType = eDefType;
}
} // checking type of variables: // is there named anything different in the scanner? // That's OK for methods! if( eType != SbxVARIANT && // Variant takes everything
eType != pDef->GetType() &&
!pDef->GetProcDef() )
{ // maybe pDef describes an object that so far has only been // recognized as SbxVARIANT - then change type of pDef // from 16.12.95 (similar cases possible perhaps?!?) if( eType == SbxOBJECT && pDef->GetType() == SbxVARIANT )
{ // Do not modify the type of procedure arguments if (pDef->GetScope() != SbPARAM)
pDef->SetType(SbxOBJECT);
} else
{
pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
bError = true;
}
}
} auto pNd = std::make_unique<SbiExprNode>( *pDef, eType ); if( !pPar )
{
pPar = SbiExprList::ParseParameters( pParser,false,false );
}
pNd->aVar.pPar = pPar.release();
pNd->aVar.pvMorePar = pvMoreParLcl.release(); if( bObj )
{ // from 8.1.95: Object may also be of the type SbxVARIANT // (but do not modify type of procedure arguments) if (pDef->GetType() == SbxVARIANT && pDef->GetScope() != SbPARAM)
pDef->SetType( SbxOBJECT ); // if we scan something with point, // the type must be SbxOBJECT if( pDef->GetType() != SbxOBJECT && pDef->GetType() != SbxVARIANT )
{ // defer error until runtime if in vba mode if ( !pParser->IsVBASupportOn() )
{
pParser->Error( ERRCODE_BASIC_BAD_DECLARATION, aSym );
bError = true;
}
} if( !bError )
{
pNd->aVar.pNext = ObjTerm( *pDef ).release();
}
}
pParser->UnlockColumn(); return pNd;
}
// construction of an object term. A term of this kind is part // of an expression that begins with an object variable.
std::unique_ptr<SbiExprNode> SbiExpression::ObjTerm( SbiSymDef& rObj )
{
pParser->Next();
SbiToken eTok = pParser->Next(); if( eTok != SYMBOL && !SbiTokenizer::IsKwd( eTok ) && !SbiTokenizer::IsExtra( eTok ) )
{ // #66745 Some operators can also be allowed // as identifiers, important for StarOne if( eTok != MOD && eTok != NOT && eTok != AND && eTok != OR &&
eTok != XOR && eTok != EQV && eTok != IMP && eTok != IS )
{
pParser->Error( ERRCODE_BASIC_VAR_EXPECTED );
bError = true;
}
}
// the parameter list is completely parsed // "procedurename()" is OK // it's a function without parameters then // i. e. you give an array as procedure parameter
// #i79918/#i80532: bConst has never been set to true // -> reused as bStandaloneExpression //SbiParameters::SbiParameters( SbiParser* p, sal_Bool bConst, sal_Bool bPar) :
SbiExprListPtr SbiExprList::ParseParameters( SbiParser* pParser, bool bStandaloneExpression, bool bPar)
{ auto pExprList = std::make_unique<SbiExprList>(); if( !bPar )
{ return pExprList;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.