Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/formula/FormulaCompiler.hxx
Line
Count
Source
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
#pragma once
21
22
#include <memory>
23
#include <unordered_map>
24
#include <vector>
25
#include <optional>
26
27
#include <com/sun/star/uno/Sequence.hxx>
28
#include <formula/formuladllapi.h>
29
#include <formula/grammar.hxx>
30
#include <formula/opcode.hxx>
31
#include <formula/tokenarray.hxx>
32
#include <formula/types.hxx>
33
#include <formula/paramclass.hxx>
34
#include <rtl/ustrbuf.hxx>
35
#include <rtl/ustring.hxx>
36
#include <sal/types.h>
37
#include <tools/debug.hxx>
38
#include <unotools/saveopt.hxx>
39
40
80.1k
#define FORMULA_MAXJUMPCOUNT    32  /* maximum number of jumps (ocChoose) */
41
36.9M
#define FORMULA_MAXTOKENS     8192  /* maximum number of tokens in formula */
42
3.04M
#define FORMULA_MAXPARAMS      255  /* maximum number of parameters per function (byte) */
43
4.03M
#define FORMULA_MAXPARAMSII      8  /* maximum number of parameters for functions that have implicit intersection ranges */
44
45
46
namespace com::sun::star {
47
    namespace sheet {
48
        struct FormulaOpCodeMapEntry;
49
        struct FormulaToken;
50
    }
51
}
52
53
class CharClass;
54
enum class FormulaError : sal_uInt16;
55
enum class SvNumFormatType : sal_Int16;
56
57
namespace formula
58
{
59
60
struct FormulaArrayStack
61
{
62
    FormulaArrayStack*  pNext;
63
    FormulaTokenArray*  pArr;
64
    FormulaTokenRef     mpLastToken;
65
    sal_uInt16          nIndex;
66
    bool bTemp;
67
};
68
69
typedef std::unordered_map< OUString, OpCode > OpCodeHashMap;
70
typedef std::unordered_map< OUString, OUString > ExternalHashMap;
71
72
class FORMULA_DLLPUBLIC FormulaCompiler
73
{
74
private:
75
    FormulaCompiler(const FormulaCompiler&) = delete;
76
    FormulaCompiler& operator=(const FormulaCompiler&) = delete;
77
public:
78
    FormulaCompiler(bool bComputeII = false, bool bMatrixFlag = false);
79
    FormulaCompiler(FormulaTokenArray& _rArr, bool bComputeII = false, bool bMatrixFlag = false);
80
    virtual ~FormulaCompiler();
81
82
    /** Mappings from strings to OpCodes and vice versa. */
83
    class FORMULA_DLLPUBLIC OpCodeMap final
84
    {
85
        OpCodeHashMap           maHashMap;                  /// Hash map of symbols, OUString -> OpCode
86
        std::unique_ptr<OUString[]> mpTable;                /// Array of symbols, OpCode -> OUString, offset==OpCode
87
        ExternalHashMap         maExternalHashMap;          /// Hash map of ocExternal, Filter String -> AddIn String
88
        ExternalHashMap         maReverseExternalHashMap;   /// Hash map of ocExternal, AddIn String -> Filter String
89
        FormulaGrammar::Grammar meGrammar;                  /// Grammar, language and reference convention
90
        sal_uInt16              mnSymbols;                  /// Count of OpCode symbols
91
        bool                    mbCore          : 1;        /// If mapping was setup by core, not filters
92
        bool                    mbEnglish       : 1;        /// If English symbols and external names
93
        bool                    mbEnglishLocale : 1;        /// If English locale for numbers
94
95
        OpCodeMap( const OpCodeMap& ) = delete;
96
        OpCodeMap& operator=( const OpCodeMap& ) = delete;
97
98
    public:
99
100
        OpCodeMap(sal_uInt16 nSymbols, bool bCore, FormulaGrammar::Grammar eGrammar ) :
101
10.8k
            maHashMap(nSymbols),
102
10.8k
            mpTable( new OUString[ nSymbols ]),
103
10.8k
            meGrammar( eGrammar),
104
10.8k
            mnSymbols( nSymbols),
105
10.8k
            mbCore( bCore),
106
10.8k
            mbEnglish ( FormulaGrammar::isEnglish(eGrammar) ),
107
10.8k
            mbEnglishLocale ( mbEnglish )
108
10.8k
        {
109
10.8k
        }
110
111
        /** Copy mappings from r into this map, effectively replacing this map.
112
113
            Override known legacy bad function names with
114
            correct ones if the conditions can be derived from the
115
            current maps.
116
         */
117
        void copyFrom( const OpCodeMap& r );
118
119
        /// Get the symbol String -> OpCode hash map for finds.
120
15.6M
        const OpCodeHashMap& getHashMap() const { return maHashMap; }
121
122
        /// Get the symbol String -> AddIn String hash map for finds.
123
1.82M
        const ExternalHashMap& getExternalHashMap() const { return maExternalHashMap; }
124
125
        /// Get the AddIn String -> symbol String hash map for finds.
126
290
        const ExternalHashMap& getReverseExternalHashMap() const { return maReverseExternalHashMap; }
127
128
        /// Get the symbol string matching an OpCode.
129
        const OUString& getSymbol( const OpCode eOp ) const
130
38.4M
        {
131
38.4M
            DBG_ASSERT( sal_uInt16(eOp) < mnSymbols, "OpCodeMap::getSymbol: OpCode out of range");
132
38.4M
            if (sal_uInt16(eOp) < mnSymbols)
133
38.4M
                return mpTable[ eOp ];
134
0
            static OUString s_sEmpty;
135
0
            return s_sEmpty;
136
38.4M
        }
137
138
        /// Get the first character of the symbol string matching an OpCode.
139
31.9M
        sal_Unicode getSymbolChar( const OpCode eOp ) const {  return getSymbol(eOp)[0]; };
140
141
        /// Get the grammar.
142
2.38M
        FormulaGrammar::Grammar getGrammar() const { return meGrammar; }
143
144
        /// Get the symbol count.
145
2.22M
        sal_uInt16 getSymbolCount() const { return mnSymbols; }
146
147
        /** Are these English symbols, as opposed to native language (which may
148
            be English as well)? */
149
2.93M
        bool isEnglish() const { return mbEnglish; }
150
151
        /** Are inline numbers parsed/formatted in en-US locale, as opposed
152
            to default locale? */
153
27.9M
        bool isEnglishLocale() const { return mbEnglishLocale; }
154
155
        /// Is it an ODF 1.1 compatibility mapping?
156
1.25M
        bool isPODF() const { return FormulaGrammar::isPODF( meGrammar); }
157
158
        /* TODO: add isAPI() once a FormulaLanguage was added. */
159
160
        /// Is it an ODFF / ODF 1.2 mapping?
161
1.35M
        bool isODFF() const { return FormulaGrammar::isODFF( meGrammar); }
162
163
        /// Is it an OOXML mapping?
164
1.29M
        bool isOOXML() const { return FormulaGrammar::isOOXML( meGrammar); }
165
166
        /// Does it have external symbol/name mappings?
167
1.35M
        bool hasExternals() const { return !maExternalHashMap.empty(); }
168
169
        /// Put entry of symbol String and OpCode pair.
170
        void putOpCode( const OUString & rStr, const OpCode eOp, const CharClass* pCharClass );
171
172
        /// Put entry of symbol String and AddIn international String pair.
173
        void putExternal( const OUString & rSymbol, const OUString & rAddIn );
174
175
        /** Put entry of symbol String and AddIn international String pair,
176
            not warning just info as used for AddIn collection and setting up
177
            alias names. */
178
        void putExternalSoftly( const OUString & rSymbol, const OUString & rAddIn );
179
180
        /// Core implementation of XFormulaOpCodeMapper::getMappings()
181
        css::uno::Sequence< css::sheet::FormulaToken >
182
            createSequenceOfFormulaTokens(const FormulaCompiler& _rCompiler,
183
                    const css::uno::Sequence< OUString >& rNames ) const;
184
185
        /// Core implementation of XFormulaOpCodeMapper::getAvailableMappings()
186
        css::uno::Sequence< css::sheet::FormulaOpCodeMapEntry >
187
            createSequenceOfAvailableMappings( const FormulaCompiler& _rCompiler,const sal_Int32 nGroup ) const;
188
189
        /** The value used in createSequenceOfAvailableMappings() and thus in
190
            XFormulaOpCodeMapper::getMappings() for an unknown symbol. */
191
21.6k
        static sal_Int32 getOpCodeUnknown() { return -1; }
192
193
    private:
194
195
        /** Conditionally put a mapping in copyFrom() context.
196
197
            Does NOT check eOp range!
198
         */
199
        void putCopyOpCode( const OUString& rSymbol, OpCode eOp, const CharClass* pCharClass );
200
    };
201
202
public:
203
    typedef std::shared_ptr< const OpCodeMap >  OpCodeMapPtr;
204
    typedef std::shared_ptr< OpCodeMap >        NonConstOpCodeMapPtr;
205
206
protected:
207
    /** Get finalized OpCodeMap for formula language.
208
209
        Creates/returns a singleton instance of an OpCodeMap that contains
210
        external AddIn mappings if the derived class supports them. Do not call
211
        at this base class as it results in a permanent mapping without AddIns
212
        even for derived classes (unless it is for the implementation of the
213
        temporary GetOpCodeMap()).
214
215
        @param nLanguage
216
            One of css::sheet::FormulaLanguage constants.
217
        @return Map for nLanguage. If nLanguage is unknown, a NULL map is returned.
218
     */
219
    OpCodeMapPtr GetFinalOpCodeMap( const sal_Int32 nLanguage ) const;
220
221
public:
222
    /** Get OpCodeMap for formula language.
223
224
        Returns either the finalized OpCodeMap (created by GetFinalOpCodeMap()
225
        of a derived class) for nLanguage if there is such, or if not then a
226
        temporary map of which its singleton is reset immediately and the
227
        temporary will get destroyed by the caller's scope. A temporary map
228
        created at this base class does *not* contain AddIn mappings.
229
230
        @param nLanguage
231
            One of css::sheet::FormulaLanguage constants.
232
        @return Map for nLanguage. If nLanguage is unknown, a NULL map is returned.
233
     */
234
    OpCodeMapPtr GetOpCodeMap( const sal_Int32 nLanguage ) const;
235
236
    /** Destroy the singleton OpCodeMap for formula language.
237
238
        This unconditionally destroys the underlying singleton instance of the
239
        map to be reinitialized again later on the next GetOpCodeMap() call.
240
        Use if the base class FormulaCompiler::GetOpCodeMap() was called and
241
        created the map (i.e. HasOpCodeMap() before returned false) and later a
242
        derived class like ScCompiler shall initialize it including AddIns.
243
244
        @param nLanguage
245
            One of css::sheet::FormulaLanguage constants.
246
     */
247
    void DestroyOpCodeMap( const sal_Int32 nLanguage );
248
249
    /** Whether the singleton OpCodeMap for formula language exists already.
250
251
        @param nLanguage
252
            One of css::sheet::FormulaLanguage constants.
253
     */
254
    bool HasOpCodeMap( const sal_Int32 nLanguage ) const;
255
256
    /** Create an internal symbol map from API mapping.
257
        @param bEnglish
258
            Use English number parser / formatter instead of native.
259
     */
260
    static OpCodeMapPtr CreateOpCodeMap(
261
            const css::uno::Sequence< const css::sheet::FormulaOpCodeMapEntry > & rMapping,
262
            bool bEnglish );
263
264
    /** Get current OpCodeMap in effect. */
265
42.2k
    const OpCodeMapPtr& GetCurrentOpCodeMap() const { return mxSymbols; }
266
267
    /** Get OpCode for English symbol.
268
        Used in XFunctionAccess to create token array.
269
        @param rName
270
            Symbol to lookup. MUST be upper case.
271
     */
272
    OpCode GetEnglishOpCode( const OUString& rName ) const;
273
274
    FormulaError GetErrorConstant( const OUString& rName ) const;
275
    void AppendErrorConstant( OUStringBuffer& rBuffer, FormulaError nError ) const;
276
277
    void EnableJumpCommandReorder( bool bEnable );
278
    void EnableStopOnError( bool bEnable );
279
280
    static bool IsOpCodeVolatile( OpCode eOp );
281
    static bool IsOpCodeJumpCommand( OpCode eOp );
282
283
    static bool DeQuote( OUString& rStr );
284
285
286
    static const OUString&  GetNativeSymbol( OpCode eOp );
287
    static sal_Unicode      GetNativeSymbolChar( OpCode eOp );
288
    static  bool            IsMatrixFunction(OpCode _eOpCode);   // if a function _always_ returns a Matrix
289
290
1.41M
    SvNumFormatType GetNumFormatType() const { return nNumFmt; }
291
    bool  CompileTokenArray();
292
293
    void CreateStringFromTokenArray( OUString& rFormula );
294
    void CreateStringFromTokenArray( OUStringBuffer& rBuffer );
295
    const FormulaToken* CreateStringFromToken( OUString& rFormula, const FormulaToken* pToken );
296
    const FormulaToken* CreateStringFromToken( OUStringBuffer& rBuffer, const FormulaToken* pToken,
297
                                    bool bAllowArrAdvance = false );
298
299
    void AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const;
300
    void AppendDouble( OUStringBuffer& rBuffer, double fVal ) const;
301
    static void AppendString( OUStringBuffer& rBuffer, const OUString & rStr );
302
303
    /** Set symbol map corresponding to one of predefined formula::FormulaGrammar::Grammar,
304
        including an address reference convention. */
305
12.8M
    FormulaGrammar::Grammar   GetGrammar() const { return meGrammar; }
306
307
    /** Whether current symbol set and grammar need transformation of Table
308
        structured references to A1 style references when writing / exporting
309
        (creating strings).
310
     */
311
    bool NeedsTableRefTransformation() const;
312
313
    /** If a parameter nParam (0-based) is to be forced to array for OpCode
314
        eOp, i.e. classified as ParamClass::ForceArray or
315
        ParamClass::ReferenceOrForceArray type. */
316
    virtual formula::ParamClass GetForceArrayParameter( const FormulaToken* pToken, sal_uInt16 nParam ) const;
317
318
    static void UpdateSeparatorsNative( const OUString& rSep, const OUString& rArrayColSep, const OUString& rArrayRowSep );
319
    static void ResetNativeSymbols();
320
    static void SetNativeSymbols( const OpCodeMapPtr& xMap );
321
322
    /** Sets the implicit intersection compute flag */
323
0
    void SetComputeIIFlag(bool bSet) { mbComputeII = bSet; }
324
325
    /** Sets the matrix flag for the formula*/
326
0
    void SetMatrixFlag(bool bSet) { mbMatrixFlag = bSet; }
327
328
    /** Separators mapped when loading opcodes from the resource, values other
329
        than RESOURCE_BASE may override the resource strings. Used by OpCodeList
330
        implementation via loadSymbols().
331
     */
332
    enum class SeparatorType
333
    {
334
        RESOURCE_BASE,
335
        SEMICOLON_BASE
336
    };
337
338
protected:
339
    virtual OUString FindAddInFunction( const OUString& rUpperName, bool bLocalFirst ) const;
340
    virtual void fillFromAddInCollectionUpperName( const NonConstOpCodeMapPtr& xMap ) const;
341
    virtual void fillFromAddInMap( const NonConstOpCodeMapPtr& xMap, FormulaGrammar::Grammar _eGrammar ) const;
342
    virtual void fillFromAddInCollectionEnglishName( const NonConstOpCodeMapPtr& xMap ) const;
343
    virtual void fillFromAddInCollectionExcelName( const NonConstOpCodeMapPtr& xMap ) const;
344
    virtual void fillAddInToken(::std::vector< css::sheet::FormulaOpCodeMapEntry >& _rVec, bool _bIsEnglish) const;
345
346
    virtual void SetError(FormulaError nError);
347
    virtual FormulaTokenRef ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2 );
348
    virtual bool HandleExternalReference(const FormulaToken& _aToken);
349
    virtual bool HandleStringName();
350
    virtual bool HandleRange();
351
    virtual bool HandleColRowName();
352
    virtual bool HandleDbData();
353
    virtual bool HandleTableRef();
354
355
    virtual void CreateStringFromExternal( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
356
    virtual void CreateStringFromSingleRef( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
357
    virtual void CreateStringFromDoubleRef( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
358
    virtual void CreateStringFromMatrix( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
359
    virtual void CreateStringFromIndex( OUStringBuffer& rBuffer, const FormulaToken* pToken ) const;
360
    virtual void LocalizeString( OUString& rName ) const;   // modify rName - input: exact name
361
    virtual bool GetExcelName( OUString& rName ) const;     // modify rName - input: exact name
362
363
    bool   GetToken();
364
    OpCode NextToken();
365
    void PutCode( FormulaTokenRef& );
366
    void Factor();
367
    void RangeLine();
368
    void UnionLine();
369
    void IntersectionLine();
370
    void UnaryLine();
371
    void PostOpLine();
372
    void PowLine();
373
    void MulDivLine();
374
    void AddSubLine();
375
    void ConcatLine();
376
    void CompareLine();
377
    OpCode Expression();
378
    void PopTokenArray();
379
    void PushTokenArray( FormulaTokenArray*, bool );
380
381
    bool MergeRangeReference( FormulaToken * * const pCode1, FormulaToken * const * const pCode2 );
382
383
    // Returns whether the opcode has implicit intersection ranges as parameters.
384
    // Called for (most) opcodes to possibly handle implicit intersection for the parameters.
385
    virtual void HandleIIOpCode(FormulaToken* /*token*/,
386
0
                                FormulaToken*** /*pppToken*/, sal_uInt8 /*nNumParams*/) {}
387
388
    // Called from CompileTokenArray() after RPN code generation is done.
389
0
    virtual void PostProcessCode() {}
390
391
0
    virtual void AnnotateOperands() {}
392
393
    OUString            aCorrectedFormula;      // autocorrected Formula
394
    OUString            aCorrectedSymbol;       // autocorrected Symbol
395
396
    OpCodeMapPtr        mxSymbols;              // which symbols are used
397
398
    FormulaTokenRef     mpToken;                // current token
399
    FormulaTokenRef     pCurrentFactorToken;    // current factor token (of Factor() method)
400
    sal_uInt16          nCurrentFactorParam;    // current factor token's parameter, 1-based
401
    FormulaTokenArray*  pArr;
402
    FormulaTokenArrayPlainIterator maArrIterator;
403
    FormulaTokenRef     mpLastToken;            // last token
404
405
    FormulaToken**      pCode;
406
    FormulaArrayStack*  pStack;
407
408
    OpCode              eLastOp;
409
    short               nRecursion;             // GetToken() recursions
410
    SvNumFormatType     nNumFmt;                // set during CompileTokenArray()
411
    sal_uInt16          pc;                     // program counter
412
413
    FormulaGrammar::Grammar meGrammar;          // The grammar used, language plus convention.
414
415
    bool                bAutoCorrect;           // whether to apply AutoCorrection
416
    bool                bCorrected;             // AutoCorrection was applied
417
    bool                glSubTotal;             // if code contains one or more subtotal functions
418
    bool                needsRPNTokenCheck;     // whether to make FormulaTokenArray check all tokens at the end
419
420
    bool mbJumpCommandReorder; /// Whether or not to reorder RPN for jump commands.
421
    bool mbStopOnError;        /// Whether to stop compilation on first encountered error.
422
423
    bool mbComputeII;  // whether to attempt computing implicit intersection ranges while building the RPN array.
424
    bool mbMatrixFlag; // whether the formula is a matrix formula (needed for II computation)
425
426
    struct LambdaFunc
427
    {
428
        bool bInLambdaFunction = false;
429
        short nBracketPos = 0;
430
        short nParaPos = 0;
431
        short nParaCount = 3; // minimum required parameter count: 3
432
        std::unordered_set<OUString> aNameSet;
433
    } m_aLambda;
434
435
    // ODF version at time of saving. Set by ScXMLExport::WriteCell().
436
    std::optional< SvtSaveOptions::ODFSaneDefaultVersion > m_oODFSavingVersion;
437
438
public:
439
    enum InitSymbols
440
    {
441
        ASK = 0,
442
        INIT,
443
        DESTROY
444
    };
445
446
private:
447
    bool InitSymbolsNative( InitSymbols ) const;    /// only SymbolsNative, on first document creation
448
    bool InitSymbolsEnglish( InitSymbols ) const;   /// only SymbolsEnglish, maybe later
449
    bool InitSymbolsPODF( InitSymbols ) const;      /// only SymbolsPODF, on demand
450
    bool InitSymbolsAPI( InitSymbols ) const;       /// only SymbolsAPI, on demand
451
    bool InitSymbolsODFF( InitSymbols ) const;      /// only SymbolsODFF, on demand
452
    bool InitSymbolsEnglishXL( InitSymbols ) const; /// only SymbolsEnglishXL, on demand
453
    bool InitSymbolsOOXML( InitSymbols ) const;     /// only SymbolsOOXML, on demand
454
455
    void loadSymbols(const std::pair<const char*, int>* pSymbols, FormulaGrammar::Grammar eGrammar, NonConstOpCodeMapPtr& rxMap,
456
            SeparatorType eSepType = SeparatorType::SEMICOLON_BASE) const;
457
458
    /** Check pCurrentFactorToken for nParam's (0-based) ForceArray types and
459
        set ForceArray at rCurr if so. Set nParam+1 as 1-based
460
        nCurrentFactorParam for subsequent ForceArrayOperator() calls.
461
     */
462
    void CheckSetForceArrayParameter( FormulaTokenRef const & rCurr, sal_uInt8 nParam );
463
464
    void ForceArrayOperator( FormulaTokenRef const & rCurr );
465
466
    class CurrentFactor
467
    {
468
        FormulaTokenRef  pPrevFac;
469
        sal_uInt16       nPrevParam;
470
        FormulaCompiler* pCompiler;
471
        CurrentFactor( const CurrentFactor& ) = delete;
472
        CurrentFactor& operator=( const CurrentFactor& ) = delete;
473
    public:
474
        explicit CurrentFactor( FormulaCompiler* pComp )
475
7.47M
            : pPrevFac( pComp->pCurrentFactorToken )
476
7.47M
            , nPrevParam( pComp->nCurrentFactorParam )
477
7.47M
            , pCompiler( pComp )
478
7.47M
            {}
479
        ~CurrentFactor()
480
7.47M
            {
481
7.47M
                pCompiler->pCurrentFactorToken = pPrevFac;
482
7.47M
                pCompiler->nCurrentFactorParam = nPrevParam;
483
7.47M
            }
484
        // yes, this operator= may modify the RValue
485
        void operator=( FormulaTokenRef const & r )
486
3.13M
            {
487
3.13M
                pCompiler->ForceArrayOperator( r );
488
3.13M
                pCompiler->pCurrentFactorToken = r;
489
3.13M
                pCompiler->nCurrentFactorParam = 0;
490
3.13M
            }
491
        void operator=( FormulaToken* p )
492
0
            {
493
0
                FormulaTokenRef xTemp( p );
494
0
                *this = xTemp;
495
0
            }
496
        operator FormulaTokenRef&()
497
3.11M
            { return pCompiler->pCurrentFactorToken; }
498
        FormulaToken* operator->()
499
5.17M
            { return pCompiler->pCurrentFactorToken.operator->(); }
500
        operator FormulaToken*()
501
1.64M
            { return operator->(); }
502
    };
503
504
505
    mutable NonConstOpCodeMapPtr  mxSymbolsODFF;      // ODFF symbols
506
    mutable NonConstOpCodeMapPtr  mxSymbolsPODF;      // ODF 1.1 symbols
507
    mutable NonConstOpCodeMapPtr  mxSymbolsAPI;       // XFunctionAccess API symbols
508
    mutable NonConstOpCodeMapPtr  mxSymbolsNative;    // native symbols
509
    mutable NonConstOpCodeMapPtr  mxSymbolsEnglish;   // English symbols
510
    mutable NonConstOpCodeMapPtr  mxSymbolsEnglishXL; // English Excel symbols (for VBA formula parsing)
511
    mutable NonConstOpCodeMapPtr  mxSymbolsOOXML;     // Excel OOXML symbols
512
513
    static FormulaTokenArray smDummyTokenArray;
514
};
515
516
} // formula
517
518
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */