LibreOffice Module formula (master) 1
FormulaCompiler.hxx
Go to the documentation of this file.
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#ifndef INCLUDED_FORMULA_FORMULACOMPILER_HXX
21#define INCLUDED_FORMULA_FORMULACOMPILER_HXX
22
23#include <memory>
24#include <unordered_map>
25#include <vector>
26
27#include <com/sun/star/uno/Sequence.hxx>
29#include <formula/grammar.hxx>
30#include <formula/opcode.hxx>
32#include <formula/types.hxx>
34#include <rtl/ustrbuf.hxx>
35#include <rtl/ustring.hxx>
36#include <sal/types.h>
37#include <tools/debug.hxx>
38
39#define FORMULA_MAXJUMPCOUNT 32 /* maximum number of jumps (ocChoose) */
40#define FORMULA_MAXTOKENS 8192 /* maximum number of tokens in formula */
41#define FORMULA_MAXPARAMS 255 /* maximum number of parameters per function (byte) */
42#define FORMULA_MAXPARAMSII 8 /* maximum number of parameters for functions that have implicit intersection ranges */
43
44
45namespace com::sun::star {
46 namespace sheet {
47 struct FormulaOpCodeMapEntry;
48 struct FormulaToken;
49 }
50}
51
52class CharClass;
53enum class FormulaError : sal_uInt16;
54enum class SvNumFormatType : sal_Int16;
55
56namespace formula
57{
58
60{
64 sal_uInt16 nIndex;
65 bool bTemp;
66};
67
68typedef std::unordered_map< OUString, OpCode > OpCodeHashMap;
69typedef std::unordered_map< OUString, OUString > ExternalHashMap;
70
72{
73private:
76public:
77 FormulaCompiler(bool bComputeII = false, bool bMatrixFlag = false);
78 FormulaCompiler(FormulaTokenArray& _rArr, bool bComputeII = false, bool bMatrixFlag = false);
79 virtual ~FormulaCompiler();
80
83 {
85 std::unique_ptr<OUString[]> mpTable;
89 sal_uInt16 mnSymbols;
90 bool mbCore : 1;
91 bool mbEnglish : 1;
92 bool mbEnglishLocale : 1;
93
94 OpCodeMap( const OpCodeMap& ) = delete;
95 OpCodeMap& operator=( const OpCodeMap& ) = delete;
96
97 public:
98
99 OpCodeMap(sal_uInt16 nSymbols, bool bCore, FormulaGrammar::Grammar eGrammar ) :
100 maHashMap(nSymbols),
101 mpTable( new OUString[ nSymbols ]),
102 meGrammar( eGrammar),
103 mnSymbols( nSymbols),
104 mbCore( bCore),
105 mbEnglish ( FormulaGrammar::isEnglish(eGrammar) ),
106 mbEnglishLocale ( mbEnglish )
107 {
108 }
109
116 void copyFrom( const OpCodeMap& r );
117
119 const OpCodeHashMap& getHashMap() const { return maHashMap; }
120
122 const ExternalHashMap& getExternalHashMap() const { return maExternalHashMap; }
123
125 const ExternalHashMap& getReverseExternalHashMap() const { return maReverseExternalHashMap; }
126
128 const OUString& getSymbol( const OpCode eOp ) const
129 {
130 DBG_ASSERT( sal_uInt16(eOp) < mnSymbols, "OpCodeMap::getSymbol: OpCode out of range");
131 if (sal_uInt16(eOp) < mnSymbols)
132 return mpTable[ eOp ];
133 static OUString s_sEmpty;
134 return s_sEmpty;
135 }
136
138 sal_Unicode getSymbolChar( const OpCode eOp ) const { return getSymbol(eOp)[0]; };
139
141 FormulaGrammar::Grammar getGrammar() const { return meGrammar; }
142
144 sal_uInt16 getSymbolCount() const { return mnSymbols; }
145
148 bool isEnglish() const { return mbEnglish; }
149
152 bool isEnglishLocale() const { return mbEnglishLocale; }
153
155 bool isPODF() const { return FormulaGrammar::isPODF( meGrammar); }
156
157 /* TODO: add isAPI() once a FormulaLanguage was added. */
158
160 bool isODFF() const { return FormulaGrammar::isODFF( meGrammar); }
161
163 bool isOOXML() const { return FormulaGrammar::isOOXML( meGrammar); }
164
166 bool hasExternals() const { return !maExternalHashMap.empty(); }
167
169 void putOpCode( const OUString & rStr, const OpCode eOp, const CharClass* pCharClass );
170
172 void putExternal( const OUString & rSymbol, const OUString & rAddIn );
173
177 void putExternalSoftly( const OUString & rSymbol, const OUString & rAddIn );
178
180 css::uno::Sequence< css::sheet::FormulaToken >
181 createSequenceOfFormulaTokens(const FormulaCompiler& _rCompiler,
182 const css::uno::Sequence< OUString >& rNames ) const;
183
185 css::uno::Sequence< css::sheet::FormulaOpCodeMapEntry >
186 createSequenceOfAvailableMappings( const FormulaCompiler& _rCompiler,const sal_Int32 nGroup ) const;
187
190 static sal_Int32 getOpCodeUnknown() { return -1; }
191
192 private:
193
198 void putCopyOpCode( const OUString& rSymbol, OpCode eOp );
199 };
200
201public:
202 typedef std::shared_ptr< const OpCodeMap > OpCodeMapPtr;
203 typedef std::shared_ptr< OpCodeMap > NonConstOpCodeMapPtr;
204
205protected:
218 OpCodeMapPtr GetFinalOpCodeMap( const sal_Int32 nLanguage ) const;
219
220public:
233 OpCodeMapPtr GetOpCodeMap( const sal_Int32 nLanguage ) const;
234
246 void DestroyOpCodeMap( const sal_Int32 nLanguage );
247
253 bool HasOpCodeMap( const sal_Int32 nLanguage ) const;
254
259 static OpCodeMapPtr CreateOpCodeMap(
260 const css::uno::Sequence< const css::sheet::FormulaOpCodeMapEntry > & rMapping,
261 bool bEnglish );
262
264 const OpCodeMapPtr& GetCurrentOpCodeMap() const { return mxSymbols; }
265
271 OpCode GetEnglishOpCode( const OUString& rName ) const;
272
273 FormulaError GetErrorConstant( const OUString& rName ) const;
274 void AppendErrorConstant( OUStringBuffer& rBuffer, FormulaError nError ) const;
275
276 void EnableJumpCommandReorder( bool bEnable );
277 void EnableStopOnError( bool bEnable );
278
279 static bool IsOpCodeVolatile( OpCode eOp );
280 static bool IsOpCodeJumpCommand( OpCode eOp );
281
282 static bool DeQuote( OUString& rStr );
283
284
285 static const OUString& GetNativeSymbol( OpCode eOp );
286 static sal_Unicode GetNativeSymbolChar( OpCode eOp );
287 static bool IsMatrixFunction(OpCode _eOpCode); // if a function _always_ returns a Matrix
288
289 SvNumFormatType GetNumFormatType() const { return nNumFmt; }
290 bool CompileTokenArray();
291
292 void CreateStringFromTokenArray( OUString& rFormula );
293 void CreateStringFromTokenArray( OUStringBuffer& rBuffer );
294 const FormulaToken* CreateStringFromToken( OUString& rFormula, const FormulaToken* pToken );
295 const FormulaToken* CreateStringFromToken( OUStringBuffer& rBuffer, const FormulaToken* pToken,
296 bool bAllowArrAdvance = false );
297
298 void AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const;
299 void AppendDouble( OUStringBuffer& rBuffer, double fVal ) const;
300 static void AppendString( OUStringBuffer& rBuffer, const OUString & rStr );
301
304 FormulaGrammar::Grammar GetGrammar() const { return meGrammar; }
305
310 bool NeedsTableRefTransformation() const;
311
315 virtual formula::ParamClass GetForceArrayParameter( const FormulaToken* pToken, sal_uInt16 nParam ) const;
316
317 static void UpdateSeparatorsNative( const OUString& rSep, const OUString& rArrayColSep, const OUString& rArrayRowSep );
318 static void ResetNativeSymbols();
319 static void SetNativeSymbols( const OpCodeMapPtr& xMap );
320
322 void SetComputeIIFlag(bool bSet) { mbComputeII = bSet; }
323
325 void SetMatrixFlag(bool bSet) { mbMatrixFlag = bSet; }
326
331 enum class SeparatorType
332 {
333 RESOURCE_BASE,
334 SEMICOLON_BASE
335 };
336
337protected:
338 virtual OUString FindAddInFunction( const OUString& rUpperName, bool bLocalFirst ) const;
339 virtual void fillFromAddInCollectionUpperName( const NonConstOpCodeMapPtr& xMap ) const;
340 virtual void fillFromAddInMap( const NonConstOpCodeMapPtr& xMap, FormulaGrammar::Grammar _eGrammar ) const;
341 virtual void fillFromAddInCollectionEnglishName( const NonConstOpCodeMapPtr& xMap ) const;
342 virtual void fillAddInToken(::std::vector< css::sheet::FormulaOpCodeMapEntry >& _rVec, bool _bIsEnglish) const;
343
344 virtual void SetError(FormulaError nError);
345 virtual FormulaTokenRef ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2 );
346 virtual bool HandleExternalReference(const FormulaToken& _aToken);
347 virtual bool HandleRange();
348 virtual bool HandleColRowName();
349 virtual bool HandleDbData();
350 virtual bool HandleTableRef();
351
352 virtual void CreateStringFromExternal( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
353 virtual void CreateStringFromSingleRef( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
354 virtual void CreateStringFromDoubleRef( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
355 virtual void CreateStringFromMatrix( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
356 virtual void CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
357 virtual void LocalizeString( OUString& rName ) const; // modify rName - input: exact name
358
359 bool GetToken();
361 void PutCode( FormulaTokenRef& );
362 void Factor();
363 void RangeLine();
364 void UnionLine();
365 void IntersectionLine();
366 void UnaryLine();
367 void PostOpLine();
368 void PowLine();
369 void MulDivLine();
370 void AddSubLine();
371 void ConcatLine();
372 void CompareLine();
374 void PopTokenArray();
375 void PushTokenArray( FormulaTokenArray*, bool );
376
377 bool MergeRangeReference( FormulaToken * * const pCode1, FormulaToken * const * const pCode2 );
378
379 // Returns whether the opcode has implicit intersection ranges as parameters.
380 // Called for (most) opcodes to possibly handle implicit intersection for the parameters.
381 virtual void HandleIIOpCode(FormulaToken* /*token*/,
382 FormulaToken*** /*pppToken*/, sal_uInt8 /*nNumParams*/) {}
383
384 // Called from CompileTokenArray() after RPN code generation is done.
385 virtual void PostProcessCode() {}
386
387 virtual void AnnotateOperands() {}
388
389 OUString aCorrectedFormula; // autocorrected Formula
390 OUString aCorrectedSymbol; // autocorrected Symbol
391
392 OpCodeMapPtr mxSymbols; // which symbols are used
393
394 FormulaTokenRef mpToken; // current token
395 FormulaTokenRef pCurrentFactorToken; // current factor token (of Factor() method)
396 sal_uInt16 nCurrentFactorParam; // current factor token's parameter, 1-based
400
403
405 short nRecursion; // GetToken() recursions
406 SvNumFormatType nNumFmt; // set during CompileTokenArray()
407 sal_uInt16 pc; // program counter
408
409 FormulaGrammar::Grammar meGrammar; // The grammar used, language plus convention.
410
411 bool bAutoCorrect; // whether to apply AutoCorrection
412 bool bCorrected; // AutoCorrection was applied
413 bool glSubTotal; // if code contains one or more subtotal functions
414 bool needsRPNTokenCheck; // whether to make FormulaTokenArray check all tokens at the end
415
418
419 bool mbComputeII; // whether to attempt computing implicit intersection ranges while building the RPN array.
420 bool mbMatrixFlag; // whether the formula is a matrix formula (needed for II computation)
421
422public:
424 {
425 ASK = 0,
427 DESTROY
428 };
429
430private:
431 bool InitSymbolsNative( InitSymbols ) const;
432 bool InitSymbolsEnglish( InitSymbols ) const;
433 bool InitSymbolsPODF( InitSymbols ) const;
434 bool InitSymbolsAPI( InitSymbols ) const;
435 bool InitSymbolsODFF( InitSymbols ) const;
436 bool InitSymbolsEnglishXL( InitSymbols ) const;
437 bool InitSymbolsOOXML( InitSymbols ) const;
438
439 void loadSymbols(const std::pair<const char*, int>* pSymbols, FormulaGrammar::Grammar eGrammar, NonConstOpCodeMapPtr& rxMap,
440 SeparatorType eSepType = SeparatorType::SEMICOLON_BASE) const;
441
446 void CheckSetForceArrayParameter( FormulaTokenRef const & rCurr, sal_uInt8 nParam );
447
448 void ForceArrayOperator( FormulaTokenRef const & rCurr );
449
451 {
453 sal_uInt16 nPrevParam;
455 CurrentFactor( const CurrentFactor& ) = delete;
457 public:
459 : pPrevFac( pComp->pCurrentFactorToken )
460 , nPrevParam( pComp->nCurrentFactorParam )
461 , pCompiler( pComp )
462 {}
464 {
465 pCompiler->pCurrentFactorToken = pPrevFac;
466 pCompiler->nCurrentFactorParam = nPrevParam;
467 }
468 // yes, this operator= may modify the RValue
469 void operator=( FormulaTokenRef const & r )
470 {
471 pCompiler->ForceArrayOperator( r );
472 pCompiler->pCurrentFactorToken = r;
473 pCompiler->nCurrentFactorParam = 0;
474 }
476 {
477 FormulaTokenRef xTemp( p );
478 *this = xTemp;
479 }
480 operator FormulaTokenRef&()
481 { return pCompiler->pCurrentFactorToken; }
483 { return pCompiler->pCurrentFactorToken.operator->(); }
484 operator FormulaToken*()
485 { return operator->(); }
486 };
487
488
489 mutable NonConstOpCodeMapPtr mxSymbolsODFF; // ODFF symbols
490 mutable NonConstOpCodeMapPtr mxSymbolsPODF; // ODF 1.1 symbols
491 mutable NonConstOpCodeMapPtr mxSymbolsAPI; // XFunctionAccess API symbols
492 mutable NonConstOpCodeMapPtr mxSymbolsNative; // native symbols
493 mutable NonConstOpCodeMapPtr mxSymbolsEnglish; // English symbols
494 mutable NonConstOpCodeMapPtr mxSymbolsEnglishXL; // English Excel symbols (for VBA formula parsing)
495 mutable NonConstOpCodeMapPtr mxSymbolsOOXML; // Excel OOXML symbols
496
498};
499
500} // formula
501
502
503#endif // INCLUDED_FORMULA_FORMULACOMPILER_HXX
504
505
506/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
CurrentFactor(const CurrentFactor &)=delete
CurrentFactor & operator=(const CurrentFactor &)=delete
void operator=(FormulaTokenRef const &r)
Mappings from strings to OpCodes and vice versa.
OpCodeMap(const OpCodeMap &)=delete
If English locale for numbers.
FormulaGrammar::Grammar meGrammar
Hash map of ocExternal, AddIn String -> Filter String.
sal_Unicode getSymbolChar(const OpCode eOp) const
Get the first character of the symbol string matching an OpCode.
bool hasExternals() const
Does it have external symbol/name mappings?
FormulaGrammar::Grammar getGrammar() const
Get the grammar.
sal_uInt16 mnSymbols
Grammar, language and reference convention.
sal_uInt16 getSymbolCount() const
Get the symbol count.
const ExternalHashMap & getExternalHashMap() const
Get the symbol String -> AddIn String hash map for finds.
bool isODFF() const
Is it an ODFF / ODF 1.2 mapping?
bool isOOXML() const
Is it an OOXML mapping?
std::unique_ptr< OUString[]> mpTable
Hash map of symbols, OUString -> OpCode.
bool isEnglishLocale() const
Are inline numbers parsed/formatted in en-US locale, as opposed to default locale?
static sal_Int32 getOpCodeUnknown()
The value used in createSequenceOfAvailableMappings() and thus in XFormulaOpCodeMapper::getMappings()...
const OUString & getSymbol(const OpCode eOp) const
Get the symbol string matching an OpCode.
OpCodeMap & operator=(const OpCodeMap &)=delete
bool mbEnglishLocale
If English symbols and external names.
ExternalHashMap maExternalHashMap
Array of symbols, OpCode -> OUString, offset==OpCode.
const ExternalHashMap & getReverseExternalHashMap() const
Get the AddIn String -> symbol String hash map for finds.
bool isEnglish() const
Are these English symbols, as opposed to native language (which may be English as well)?
bool isPODF() const
Is it an ODF 1.1 compatibility mapping?
const OpCodeHashMap & getHashMap() const
Get the symbol String -> OpCode hash map for finds.
bool mbCore
Count of OpCode symbols.
ExternalHashMap maReverseExternalHashMap
Hash map of ocExternal, Filter String -> AddIn String.
OpCodeMap(sal_uInt16 nSymbols, bool bCore, FormulaGrammar::Grammar eGrammar)
bool mbEnglish
If mapping was setup by core, not filters.
FormulaTokenRef pCurrentFactorToken
FormulaCompiler & operator=(const FormulaCompiler &)=delete
NonConstOpCodeMapPtr mxSymbolsOOXML
NonConstOpCodeMapPtr mxSymbolsPODF
FormulaTokenArray * pArr
NonConstOpCodeMapPtr mxSymbolsEnglishXL
FormulaArrayStack * pStack
FormulaCompiler(const FormulaCompiler &)=delete
SvNumFormatType GetNumFormatType() const
static FormulaTokenArray smDummyTokenArray
NonConstOpCodeMapPtr mxSymbolsAPI
bool mbComputeII
Whether to stop compilation on first encountered error.
void ForceArrayOperator(FormulaTokenRef const &rCurr)
void SetMatrixFlag(bool bSet)
Sets the matrix flag for the formula.
bool mbStopOnError
Whether or not to reorder RPN for jump commands.
SeparatorType
Separators mapped when loading opcodes from the resource, values other than RESOURCE_BASE may overrid...
FormulaTokenArrayPlainIterator maArrIterator
std::shared_ptr< OpCodeMap > NonConstOpCodeMapPtr
void SetComputeIIFlag(bool bSet)
Sets the implicit intersection compute flag.
FormulaGrammar::Grammar meGrammar
NonConstOpCodeMapPtr mxSymbolsEnglish
std::shared_ptr< const OpCodeMap > OpCodeMapPtr
virtual void HandleIIOpCode(FormulaToken *, FormulaToken ***, sal_uInt8)
FormulaGrammar::Grammar GetGrammar() const
Set symbol map corresponding to one of predefined formula::FormulaGrammar::Grammar,...
const OpCodeMapPtr & GetCurrentOpCodeMap() const
Get current OpCodeMap in effect.
NonConstOpCodeMapPtr mxSymbolsNative
NonConstOpCodeMapPtr mxSymbolsODFF
Grammars digested by ScCompiler.
Definition: grammar.hxx:33
static bool isODFF(const Grammar eGrammar)
If grammar is of ODFF.
Definition: grammar.hxx:199
static bool isPODF(const Grammar eGrammar)
If grammar is of ODF 1.1.
Definition: grammar.hxx:192
Grammar
Values encoding the formula language plus address reference convention plus English parsing/formattin...
Definition: grammar.hxx:68
static bool isOOXML(const Grammar eGrammar)
If grammar is of OOXML.
Definition: grammar.hxx:206
#define DBG_ASSERT(sCon, aError)
FormulaError
Definition: errorcodes.hxx:32
#define FORMULA_DLLPUBLIC
Definition: formuladllapi.h:28
void * p
std::unordered_map< OUString, OUString > ExternalHashMap
::boost::intrusive_ptr< FormulaToken > FormulaTokenRef
Definition: types.hxx:27
std::unordered_map< OUString, OpCode > OpCodeHashMap
OpCode
Definition: opcode.hxx:29
FormulaArrayStack * pNext
FormulaTokenArray * pArr
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
int SetError()
SvNumFormatType