1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/errcode.hxx>
21 #include <vcl/svapp.hxx>
22 #include <basic/sbx.hxx>
25 class SbxSimpleCharClass
28 bool isAlpha( sal_Unicode c
) const
30 bool bRet
= (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z');
34 bool isDigit( sal_Unicode c
) const
36 bool bRet
= (c
>= '0' && c
<= '9');
40 bool isAlphaNumeric( sal_Unicode c
) const
42 bool bRet
= isDigit( c
) || isAlpha( c
);
48 static SbxVariable
* Element
49 ( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
,
50 SbxClassType
, const SbxSimpleCharClass
& rCharClass
);
52 static const sal_Unicode
* SkipWhitespace( const sal_Unicode
* p
)
54 while( *p
&& ( *p
== ' ' || *p
== '\t' ) )
59 // Scanning of a symbol. The symbol were inserted in rSym, the return value
60 // is the new scan position. The symbol is at errors empty.
62 static const sal_Unicode
* Symbol( const sal_Unicode
* p
, OUString
& rSym
, const SbxSimpleCharClass
& rCharClass
)
65 // Did we have a nonstandard symbol?
69 while( *p
&& *p
!= ']' )
77 // A symbol had to begin with a alphabetic character or an underline
78 if( !rCharClass
.isAlpha( *p
) && *p
!= '_' )
80 SbxBase::SetError( SbxERR_SYNTAX
);
85 // The it can contain alphabetic characters, numbers or underlines
86 while( *p
&& (rCharClass
.isAlphaNumeric( *p
) || *p
== '_') )
90 // BASIC-Standard-Suffixes were ignored
91 if( *p
&& (*p
== '%' || *p
== '&' || *p
== '!' || *p
== '#' || *p
== '$' ) )
97 rSym
= rSym
.copy( 0, nLen
);
101 // Qualified name. Element.Element....
103 static SbxVariable
* QualifiedName
104 ( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
, SbxClassType t
)
106 static SbxSimpleCharClass aCharClass
;
108 SbxVariableRef refVar
;
109 const sal_Unicode
* p
= SkipWhitespace( *ppBuf
);
110 if( aCharClass
.isAlpha( *p
) || *p
== '_' || *p
== '[' )
112 // Read in the element
113 refVar
= Element( pObj
, pGbl
, &p
, t
, aCharClass
);
114 while( refVar
.Is() && (*p
== '.' || *p
== '!') )
116 // It follows still an objectelement. The current element
117 // had to be a SBX-Object or had to deliver such an object!
118 pObj
= PTR_CAST(SbxObject
,(SbxVariable
*) refVar
);
120 // Then it had to deliver an object
121 pObj
= PTR_CAST(SbxObject
,refVar
->GetObject());
126 // And the next element please
127 refVar
= Element( pObj
, pGbl
, &p
, t
, aCharClass
);
131 SbxBase::SetError( SbxERR_SYNTAX
);
138 // Read in of an operand. This could be a number, a string or
139 // a function (with optional parameters).
141 static SbxVariable
* Operand
142 ( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
, bool bVar
)
144 static SbxSimpleCharClass aCharClass
;
146 SbxVariableRef
refVar( new SbxVariable
);
147 const sal_Unicode
* p
= SkipWhitespace( *ppBuf
);
148 if( !bVar
&& ( aCharClass
.isDigit( *p
)
149 || ( *p
== '.' && aCharClass
.isDigit( *( p
+1 ) ) )
153 // A number could be scanned in directly!
155 if( !refVar
->Scan( OUString( p
), &nLen
) )
164 else if( !bVar
&& *p
== '"' )
171 // This is perhaps an error
176 // Double quotes are OK
184 aString
+= OUString(*p
++);
186 refVar
->PutString( aString
);
190 refVar
= QualifiedName( pObj
, pGbl
, &p
, SbxCLASS_DONTCARE
);
198 // Read in of a simple term. The operands +, -, * and /
201 static SbxVariable
* MulDiv( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
)
203 const sal_Unicode
* p
= *ppBuf
;
204 SbxVariableRef
refVar( Operand( pObj
, pGbl
, &p
, false ) );
205 p
= SkipWhitespace( p
);
206 while( refVar
.Is() && ( *p
== '*' || *p
== '/' ) )
208 sal_Unicode cOp
= *p
++;
209 SbxVariableRef
refVar2( Operand( pObj
, pGbl
, &p
, false ) );
212 // temporary variable!
213 SbxVariable
* pVar
= refVar
;
214 pVar
= new SbxVariable( *pVar
);
233 static SbxVariable
* PlusMinus( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
)
235 const sal_Unicode
* p
= *ppBuf
;
236 SbxVariableRef
refVar( MulDiv( pObj
, pGbl
, &p
) );
237 p
= SkipWhitespace( p
);
238 while( refVar
.Is() && ( *p
== '+' || *p
== '-' ) )
240 sal_Unicode cOp
= *p
++;
241 SbxVariableRef
refVar2( MulDiv( pObj
, pGbl
, &p
) );
244 // temporaere Variable!
245 SbxVariable
* pVar
= refVar
;
246 pVar
= new SbxVariable( *pVar
);
265 static SbxVariable
* Assign( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
)
267 const sal_Unicode
* p
= *ppBuf
;
268 SbxVariableRef
refVar( Operand( pObj
, pGbl
, &p
, true ) );
269 p
= SkipWhitespace( p
);
274 // Assign only onto properties!
275 if( refVar
->GetClass() != SbxCLASS_PROPERTY
)
277 SbxBase::SetError( SbxERR_BAD_ACTION
);
283 SbxVariableRef
refVar2( PlusMinus( pObj
, pGbl
, &p
) );
286 SbxVariable
* pVar
= refVar
;
287 SbxVariable
* pVar2
= refVar2
;
289 pVar
->SetParameters( NULL
);
294 // Simple call: once activating
295 refVar
->Broadcast( SBX_HINT_DATAWANTED
);
303 // Read in of an element. This is a symbol, optional followed
304 // by a parameter list. The symbol will be searched in the
305 // specified object and the parameter list will be attached if necessary.
307 static SbxVariable
* Element
308 ( SbxObject
* pObj
, SbxObject
* pGbl
, const sal_Unicode
** ppBuf
,
309 SbxClassType t
, const SbxSimpleCharClass
& rCharClass
)
312 const sal_Unicode
* p
= Symbol( *ppBuf
, aSym
, rCharClass
);
313 SbxVariableRef refVar
;
314 if( !aSym
.isEmpty() )
316 sal_uInt16 nOld
= pObj
->GetFlags();
319 pObj
->SetFlag( SBX_GBLSEARCH
);
321 refVar
= pObj
->Find( aSym
, t
);
322 pObj
->SetFlags( nOld
);
325 refVar
->SetParameters( NULL
);
326 // Follow still parameter?
327 p
= SkipWhitespace( p
);
331 SbxArrayRef refPar
= new SbxArray
;
333 // We are once relaxed and accept as well
334 // the line- or commandend as delimiter
335 // Search parameter always global!
336 while( *p
&& *p
!= ')' && *p
!= ']' )
338 SbxVariableRef refArg
= PlusMinus( pGbl
, pGbl
, &p
);
341 // Error during the parsing
342 refVar
.Clear(); break;
346 // One copies the parameter, so that
347 // one have the current status (triggers also
348 // the call per access)
349 SbxVariable
* pArg
= refArg
;
350 refPar
->Put( new SbxVariable( *pArg
), ++nArg
);
352 p
= SkipWhitespace( p
);
359 refVar
->SetParameters( refPar
);
363 SbxBase::SetError( SbxERR_NO_METHOD
);
373 SbxVariable
* SbxObject::Execute( const OUString
& rTxt
)
375 SbxVariable
* pVar
= NULL
;
376 const sal_Unicode
* p
= rTxt
.getStr();
379 p
= SkipWhitespace( p
);
386 SetError( SbxERR_SYNTAX
); break;
388 pVar
= Assign( this, this, &p
);
393 p
= SkipWhitespace( p
);
396 SetError( SbxERR_SYNTAX
); break;
402 SbxVariable
* SbxObject::FindQualified( const OUString
& rName
, SbxClassType t
)
404 SbxVariable
* pVar
= NULL
;
405 const sal_Unicode
* p
= rName
.getStr();
406 p
= SkipWhitespace( p
);
411 pVar
= QualifiedName( this, this, &p
, t
);
412 p
= SkipWhitespace( p
);
415 SetError( SbxERR_SYNTAX
);
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */