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 #ifndef SC_COMPILER_HXX
21 #define SC_COMPILER_HXX
25 #include <tools/mempool.hxx>
28 #include "refdata.hxx"
29 #include "formula/token.hxx"
30 #include "formula/grammar.hxx"
31 #include <unotools/charclass.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/sheet/ExternalLinkInfo.hpp>
36 #include <formula/FormulaCompiler.hxx>
38 #include <boost/intrusive_ptr.hpp>
39 #include <boost/unordered_map.hpp>
41 // constants and data types also for external modules (ScInterpreter et al)
43 #define MAXSTRLEN 1024 /* maximum length of input string of one symbol */
45 // flag values of CharTable
46 #define SC_COMPILER_C_ILLEGAL 0x00000000
47 #define SC_COMPILER_C_CHAR 0x00000001
48 #define SC_COMPILER_C_CHAR_BOOL 0x00000002
49 #define SC_COMPILER_C_CHAR_WORD 0x00000004
50 #define SC_COMPILER_C_CHAR_VALUE 0x00000008
51 #define SC_COMPILER_C_CHAR_STRING 0x00000010
52 #define SC_COMPILER_C_CHAR_DONTCARE 0x00000020
53 #define SC_COMPILER_C_BOOL 0x00000040
54 #define SC_COMPILER_C_WORD 0x00000080
55 #define SC_COMPILER_C_WORD_SEP 0x00000100
56 #define SC_COMPILER_C_VALUE 0x00000200
57 #define SC_COMPILER_C_VALUE_SEP 0x00000400
58 #define SC_COMPILER_C_VALUE_EXP 0x00000800
59 #define SC_COMPILER_C_VALUE_SIGN 0x00001000
60 #define SC_COMPILER_C_VALUE_VALUE 0x00002000
61 #define SC_COMPILER_C_STRING_SEP 0x00004000
62 #define SC_COMPILER_C_NAME_SEP 0x00008000 // there can be only one! '\''
63 #define SC_COMPILER_C_CHAR_IDENT 0x00010000 // identifier (built-in function) or reference start
64 #define SC_COMPILER_C_IDENT 0x00020000 // identifier or reference continuation
65 #define SC_COMPILER_C_ODF_LBRACKET 0x00040000 // ODF '[' reference bracket
66 #define SC_COMPILER_C_ODF_RBRACKET 0x00080000 // ODF ']' reference bracket
67 #define SC_COMPILER_C_ODF_LABEL_OP 0x00100000 // ODF '!!' automatic intersection of labels
68 #define SC_COMPILER_C_ODF_NAME_MARKER 0x00200000 // ODF '$$' marker that starts a defined (range) name
69 #define SC_COMPILER_C_CHAR_NAME 0x00400000 // start character of a defined name
70 #define SC_COMPILER_C_NAME 0x00800000 // continuation character of a defined name
71 #define SC_COMPILER_C_CHAR_ERRCONST 0x01000000 // start character of an error constant ('#')
73 #define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab
78 class ScExternalRefManager
;
81 // constants and data types internal to compiler
85 formula::StackVar eType; // type of data
86 sal_uInt16 nRefCnt; // reference count
87 bool bRaw; // not cloned yet and trimmed to real size
94 formula::StackVar eType
;
95 mutable sal_uInt16 nRefCnt
;
99 struct ScDoubleRawToken
: private ScRawTokenBase
103 { // union only to assure alignment identical to ScRawToken
110 DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken
);
113 struct ScRawToken
: private ScRawTokenBase
115 friend class ScCompiler
;
116 // Friends that use a temporary ScRawToken on the stack (and therefor need
117 // the private dtor) and know what they're doing..
118 friend class ScTokenArray
;
119 static sal_uInt16
sbyteOffset();
127 ScComplexRefData aRef
;
130 sal_Unicode cTabName
[MAXSTRLEN
+1];
131 ScComplexRefData aRef
;
135 sal_Unicode cName
[MAXSTRLEN
+1];
143 rtl_uString
* mpDataIgnoreCase
;
147 sal_Unicode cStr
[ MAXSTRLEN
+1 ]; // string (up to 255 characters + 0)
148 short nJump
[ FORMULA_MAXJUMPCOUNT
+ 1 ]; // If/Chose token
151 //! other members not initialized
152 ScRawToken() { bRaw
= true; }
154 ~ScRawToken() {} //! only delete via Delete()
156 DECL_FIXEDMEMPOOL_NEWDEL( ScRawToken
);
157 formula::StackVar
GetType() const { return (formula::StackVar
) eType
; }
158 OpCode
GetOpCode() const { return (OpCode
) eOp
; }
159 void NewOpCode( OpCode e
) { eOp
= e
; }
160 void IncRef() { nRefCnt
++; }
161 void DecRef() { if( !--nRefCnt
) Delete(); }
162 sal_uInt16
GetRef() const { return nRefCnt
; }
163 SC_DLLPUBLIC
void Delete();
165 // Use these methods only on tokens that are not part of a token array,
166 // since the reference count is cleared!
167 void SetOpCode( OpCode eCode
);
168 void SetString( rtl_uString
* pData
, rtl_uString
* pDataIgoreCase
);
169 void SetSingleReference( const ScSingleRefData
& rRef
);
170 void SetDoubleReference( const ScComplexRefData
& rRef
);
171 void SetDouble( double fVal
);
172 void SetErrorConstant( sal_uInt16 nErr
);
174 // These methods are ok to use, reference count not cleared.
175 void SetName(bool bGlobal
, sal_uInt16 nIndex
);
176 void SetExternalSingleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScSingleRefData
& rRef
);
177 void SetExternalDoubleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScComplexRefData
& rRef
);
178 void SetExternalName( sal_uInt16 nFileId
, const OUString
& rName
);
179 void SetMatrix( ScMatrix
* p
);
180 void SetExternal(const sal_Unicode
* pStr
);
182 /** If the token is a non-external reference, determine if the reference is
183 valid. If the token is an external reference, return true. Else return
184 false. Used only in ScCompiler::NextNewToken() to preserve non-existing
185 sheet names in otherwise valid references.
187 bool IsValidReference() const;
189 ScRawToken
* Clone() const; // real copy!
190 formula::FormulaToken
* CreateToken() const; // create typified token
191 void Load( SvStream
&, sal_uInt16 nVer
);
193 static xub_StrLen
GetStrLen( const sal_Unicode
* pStr
); // as long as a "string" is an array
194 static size_t GetStrLenBytes( xub_StrLen nLen
)
195 { return nLen
* sizeof(sal_Unicode
); }
196 static size_t GetStrLenBytes( const sal_Unicode
* pStr
)
197 { return GetStrLenBytes( GetStrLen( pStr
) ); }
200 inline void intrusive_ptr_add_ref(ScRawToken
* p
)
205 inline void intrusive_ptr_release(ScRawToken
* p
)
210 typedef ::boost::intrusive_ptr
<ScRawToken
> ScRawTokenRef
;
212 class SC_DLLPUBLIC ScCompiler
: public formula::FormulaCompiler
216 enum ExtendedErrorDetection
218 EXTENDED_ERROR_DETECTION_NONE
= 0, // no error on unknown symbols, default (interpreter handles it)
219 EXTENDED_ERROR_DETECTION_NAME_BREAK
, // name error on unknown symbols and break, pCode incomplete
220 EXTENDED_ERROR_DETECTION_NAME_NO_BREAK
// name error on unknown symbols, don't break, continue
225 const formula::FormulaGrammar::AddressConvention meConv
;
227 Convention( formula::FormulaGrammar::AddressConvention eConvP
);
228 virtual ~Convention();
230 virtual void makeRefStr(
231 OUStringBuffer
& rBuffer
,
232 formula::FormulaGrammar::Grammar eGram
,
233 const ScAddress
& rPos
,
234 const OUString
& rErrRef
, const std::vector
<OUString
>& rTabNames
,
235 const ScComplexRefData
& rRef
, bool bSingleRef
) const = 0;
237 virtual ::com::sun::star::i18n::ParseResult
238 parseAnyToken( const OUString
& rFormula
,
240 const CharClass
* pCharClass
) const = 0;
243 * Parse the symbol string and pick up the file name and the external
246 * @return true on successful parse, or false otherwise.
248 virtual bool parseExternalName( const OUString
& rSymbol
, OUString
& rFile
, OUString
& rName
,
249 const ScDocument
* pDoc
,
250 const ::com::sun::star::uno::Sequence
<
251 const ::com::sun::star::sheet::ExternalLinkInfo
> * pExternalLinks
) const = 0;
253 virtual OUString
makeExternalNameStr( const OUString
& rFile
, const OUString
& rName
) const = 0;
255 virtual void makeExternalRefStr(
256 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
, const OUString
& rFileName
,
257 const OUString
& rTabName
, const ScSingleRefData
& rRef
) const = 0;
259 virtual void makeExternalRefStr(
260 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
,
261 const OUString
& rFileName
, const std::vector
<OUString
>& rTabNames
,
262 const OUString
& rTabName
, const ScComplexRefData
& rRef
) const = 0;
264 enum SpecialSymbolType
267 * Character between sheet name and address. In OOO A1 this is
268 * '.', while XL A1 and XL R1C1 this is '!'.
273 * In OOO A1, a sheet name may be prefixed with '$' to indicate an
274 * absolute sheet position.
278 virtual sal_Unicode
getSpecialSymbol( SpecialSymbolType eSymType
) const = 0;
280 virtual sal_uLong
getCharTableFlags( sal_Unicode c
, sal_Unicode cLast
) const = 0;
283 const sal_uLong
* mpCharTable
;
285 friend struct Convention
;
289 static CharClass
*pCharClassEnglish
; // character classification for en_US locale
290 static const Convention
*pConventions
[ formula::FormulaGrammar::CONV_LAST
];
292 static const Convention
* const pConvOOO_A1
;
293 static const Convention
* const pConvOOO_A1_ODF
;
294 static const Convention
* const pConvXL_A1
;
295 static const Convention
* const pConvXL_R1C1
;
296 static const Convention
* const pConvXL_OOX
;
298 static struct AddInMap
301 const char* pEnglish
;
302 bool bMapDupToInternal
; // when writing ODFF
303 const char* pOriginal
; // programmatical name
304 const char* pUpper
; // upper case programmatical name
306 static const AddInMap
* GetAddInMap();
307 static size_t GetAddInMapCount();
312 SvNumberFormatter
* mpFormatter
;
314 // For CONV_XL_OOX, may be set via API by MOOXML filter.
315 ::com::sun::star::uno::Sequence
< const ::com::sun::star::sheet::ExternalLinkInfo
> maExternalLinks
;
317 sal_Unicode cSymbol
[MAXSTRLEN
]; // current Symbol
318 OUString aFormula
; // formula source code
319 sal_Int32 nSrcPos
; // tokenizer position (source code)
320 mutable ScRawTokenRef pRawToken
;
322 const CharClass
* pCharClass
; // which character classification is used for parseAnyToken
323 sal_uInt16 mnPredetectedReference
; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
324 SCsTAB nMaxTab
; // last sheet in document
325 sal_Int32 mnRangeOpPosInSymbol
; // if and where a range operator is in symbol
326 const Convention
*pConv
;
327 ExtendedErrorDetection meExtendedErrorDetection
;
328 bool mbCloseBrackets
; // whether to close open brackets automatically, default TRUE
329 bool mbRewind
; // whether symbol is to be rewound to some step during lexical analysis
330 std::vector
<sal_uInt16
> maExternalFiles
;
331 std::vector
<OUString
> maTabNames
;
333 bool NextNewToken(bool bInArray
= false);
335 virtual void SetError(sal_uInt16 nError
);
336 xub_StrLen
NextSymbol(bool bInArray
);
337 bool IsValue( const OUString
& );
338 bool IsOpCode( const OUString
&, bool bInArray
);
339 bool IsOpCode2( const OUString
& );
341 bool IsReference( const OUString
& );
342 bool IsSingleReference( const OUString
& );
343 bool IsPredetectedReference(const OUString
&);
344 bool IsDoubleReference( const OUString
& );
345 bool IsMacro( const OUString
& );
346 bool IsNamedRange( const OUString
& );
347 bool IsExternalNamedRange( const OUString
& rSymbol
);
348 bool IsDBRange( const OUString
& );
349 bool IsColRowName( const OUString
& );
350 bool IsBoolean( const OUString
& );
351 void AutoCorrectParsedSymbol();
353 void SetRelNameReference();
355 /** Obtain range data for ocName token, global or sheet local.
357 Prerequisite: rToken is a FormulaIndexToken so IsGlobal() and
358 GetIndex() can be called on it. We don't check with RTTI.
360 ScRangeData
* GetRangeData( const formula::FormulaToken
& pToken
) const;
362 static void InitCharClassEnglish();
365 ScCompiler( ScDocument
* pDocument
, const ScAddress
&);
367 ScCompiler( ScDocument
* pDocument
, const ScAddress
&,ScTokenArray
& rArr
);
369 virtual ~ScCompiler();
372 static void DeInit(); /// all
374 // for ScAddress::Format()
375 static void CheckTabQuotes( OUString
& aTabName
,
376 const formula::FormulaGrammar::AddressConvention eConv
= formula::FormulaGrammar::CONV_OOO
);
378 /** Analyzes a string for a 'Doc'#Tab construct, or 'Do''c'#Tab etc..
380 @returns the position of the unquoted # hash mark in 'Doc'#Tab, or
382 static sal_Int32
GetDocTabPos( const OUString
& rString
);
384 static bool EnQuote( OUString
& rStr
);
385 sal_Unicode
GetNativeAddressSymbol( Convention::SpecialSymbolType eType
) const;
387 // Check if it is a valid english function name
388 bool IsEnglishSymbol( const OUString
& rName
);
389 bool IsErrorConstant( const OUString
& ) const;
391 //! _either_ CompileForFAP _or_ AutoCorrection, _not_ both
392 // #i101512# SetCompileForFAP is in formula::FormulaCompiler
393 void SetAutoCorrection( bool bVal
)
394 { bAutoCorrect
= bVal
; bIgnoreErrors
= bVal
; }
395 void SetCloseBrackets( bool bVal
) { mbCloseBrackets
= bVal
; }
396 void SetRefConvention( const Convention
*pConvP
);
397 void SetRefConvention( const formula::FormulaGrammar::AddressConvention eConv
);
399 static const Convention
* GetRefConvention( formula::FormulaGrammar::AddressConvention eConv
);
401 /// Set symbol map if not empty.
402 void SetFormulaLanguage( const OpCodeMapPtr
& xMap
);
404 void SetGrammar( const formula::FormulaGrammar::Grammar eGrammar
);
406 void SetNumberFormatter( SvNumberFormatter
* pFormatter
);
409 /** Set grammar and reference convention from within SetFormulaLanguage()
413 The new grammar to be set and the associated reference convention.
416 The previous grammar that was active before SetFormulaLanguage().
418 void SetGrammarAndRefConvention(
419 const formula::FormulaGrammar::Grammar eNewGrammar
,
420 const formula::FormulaGrammar::Grammar eOldGrammar
);
423 /// Set external link info for ScAddress::CONV_XL_OOX.
424 inline void SetExternalLinks(
425 const ::com::sun::star::uno::Sequence
<
426 const ::com::sun::star::sheet::ExternalLinkInfo
> & rLinks
)
428 maExternalLinks
= rLinks
;
431 void CreateStringFromXMLTokenArray( OUString
& rFormula
, OUString
& rFormulaNmsp
);
433 void SetExtendedErrorDetection( ExtendedErrorDetection eVal
) { meExtendedErrorDetection
= eVal
; }
435 bool IsCorrected() { return bCorrected
; }
436 const OUString
& GetCorrectedFormula() { return aCorrectedFormula
; }
439 * Tokenize formula expression string into an array of tokens.
441 * @param rFormula formula expression to tokenize.
443 * @return heap allocated token array object. The caller <i>must</i>
444 * manage the life cycle of this object.
446 ScTokenArray
* CompileString( const OUString
& rFormula
);
447 ScTokenArray
* CompileString( const OUString
& rFormula
, const OUString
& rFormulaNmsp
);
448 const ScDocument
* GetDoc() const { return pDoc
; }
449 const ScAddress
& GetPos() const { return aPos
; }
451 void MoveRelWrap( SCCOL nMaxCol
, SCROW nMaxRow
);
452 static void MoveRelWrap( ScTokenArray
& rArr
, ScDocument
* pDoc
, const ScAddress
& rPos
,
453 SCCOL nMaxCol
, SCROW nMaxRow
);
455 /** If the character is allowed as tested by nFlags (SC_COMPILER_C_...
456 bits) for all known address conventions. If more than one bit is given
457 in nFlags, all bits must match. If bTestLetterNumeric is false and
458 char>=128, no LetterNumeric test is done and false is returned. */
459 static bool IsCharFlagAllConventions(
460 OUString
const & rStr
, xub_StrLen nPos
, sal_uLong nFlags
, bool bTestLetterNumeric
= true );
464 virtual OUString
FindAddInFunction( const OUString
& rUpperName
, bool bLocalFirst
) const;
465 virtual void fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr xMap
) const;
466 virtual void fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr xMap
) const;
467 virtual void fillFromAddInMap( NonConstOpCodeMapPtr xMap
, formula::FormulaGrammar::Grammar _eGrammar
) const;
468 virtual void fillAddInToken(::std::vector
< ::com::sun::star::sheet::FormulaOpCodeMapEntry
>& _rVec
,bool _bIsEnglish
) const;
470 virtual bool HandleExternalReference(const formula::FormulaToken
& _aToken
);
471 virtual bool HandleRange();
472 virtual bool HandleSingleRef();
473 virtual bool HandleDbData();
475 virtual formula::FormulaTokenRef
ExtendRangeReference( formula::FormulaToken
& rTok1
, formula::FormulaToken
& rTok2
, bool bReuseDoubleRef
);
476 virtual void CreateStringFromExternal(OUStringBuffer
& rBuffer
, formula::FormulaToken
* pTokenP
) const;
477 virtual void CreateStringFromSingleRef(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const;
478 virtual void CreateStringFromDoubleRef(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const;
479 virtual void CreateStringFromMatrix( OUStringBuffer
& rBuffer
, formula::FormulaToken
* _pTokenP
) const;
480 virtual void CreateStringFromIndex(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const;
481 virtual void LocalizeString( OUString
& rName
) const; // modify rName - input: exact name
483 /// Access the CharTable flags
484 inline sal_uLong
GetCharTableFlags( sal_Unicode c
, sal_Unicode cLast
)
485 { return c
< 128 ? pConv
->getCharTableFlags(c
, cLast
) : 0; }
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */