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 INCLUDED_SC_INC_COMPILER_HXX
21 #define INCLUDED_SC_INC_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
;
83 class CompileFormulaContext
;
87 // constants and data types internal to compiler
91 formula::StackVar eType; // type of data
92 sal_uInt16 nRefCnt; // reference count
93 bool bRaw; // not cloned yet and trimmed to real size
100 formula::StackVar eType
;
101 mutable sal_uInt16 nRefCnt
;
105 struct ScDoubleRawToken
: private ScRawTokenBase
109 { // union only to assure alignment identical to ScRawToken
116 DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken
);
119 struct ScRawToken
: private ScRawTokenBase
121 friend class ScCompiler
;
122 // Friends that use a temporary ScRawToken on the stack (and therefor need
123 // the private dtor) and know what they're doing..
124 friend class ScTokenArray
;
125 static sal_uInt16
sbyteOffset();
133 ScComplexRefData aRef
;
136 sal_Unicode cTabName
[MAXSTRLEN
+1];
137 ScComplexRefData aRef
;
141 sal_Unicode cName
[MAXSTRLEN
+1];
149 rtl_uString
* mpDataIgnoreCase
;
153 sal_Unicode cStr
[ MAXSTRLEN
+1 ]; // string (up to 255 characters + 0)
154 short nJump
[ FORMULA_MAXJUMPCOUNT
+ 1 ]; // If/Chose token
157 //! other members not initialized
158 ScRawToken() { bRaw
= true; }
160 ~ScRawToken() {} //! only delete via Delete()
162 DECL_FIXEDMEMPOOL_NEWDEL( ScRawToken
);
163 formula::StackVar
GetType() const { return (formula::StackVar
) eType
; }
164 OpCode
GetOpCode() const { return (OpCode
) eOp
; }
165 void NewOpCode( OpCode e
) { eOp
= e
; }
166 void IncRef() { nRefCnt
++; }
167 void DecRef() { if( !--nRefCnt
) Delete(); }
168 sal_uInt16
GetRef() const { return nRefCnt
; }
169 SC_DLLPUBLIC
void Delete();
171 // Use these methods only on tokens that are not part of a token array,
172 // since the reference count is cleared!
173 void SetOpCode( OpCode eCode
);
174 void SetString( rtl_uString
* pData
, rtl_uString
* pDataIgoreCase
);
175 void SetSingleReference( const ScSingleRefData
& rRef
);
176 void SetDoubleReference( const ScComplexRefData
& rRef
);
177 void SetDouble( double fVal
);
178 void SetErrorConstant( sal_uInt16 nErr
);
180 // These methods are ok to use, reference count not cleared.
181 void SetName(bool bGlobal
, sal_uInt16 nIndex
);
182 void SetExternalSingleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScSingleRefData
& rRef
);
183 void SetExternalDoubleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScComplexRefData
& rRef
);
184 void SetExternalName( sal_uInt16 nFileId
, const OUString
& rName
);
185 void SetMatrix( ScMatrix
* p
);
186 void SetExternal(const sal_Unicode
* pStr
);
188 /** If the token is a non-external reference, determine if the reference is
189 valid. If the token is an external reference, return true. Else return
190 false. Used only in ScCompiler::NextNewToken() to preserve non-existing
191 sheet names in otherwise valid references.
193 bool IsValidReference() const;
195 ScRawToken
* Clone() const; // real copy!
196 formula::FormulaToken
* CreateToken() const; // create typified token
197 void Load( SvStream
&, sal_uInt16 nVer
);
199 static sal_Int32
GetStrLen( const sal_Unicode
* pStr
); // as long as a "string" is an array
200 static size_t GetStrLenBytes( sal_Int32 nLen
)
201 { return nLen
* sizeof(sal_Unicode
); }
202 static size_t GetStrLenBytes( const sal_Unicode
* pStr
)
203 { return GetStrLenBytes( GetStrLen( pStr
) ); }
206 inline void intrusive_ptr_add_ref(ScRawToken
* p
)
211 inline void intrusive_ptr_release(ScRawToken
* p
)
216 typedef ::boost::intrusive_ptr
<ScRawToken
> ScRawTokenRef
;
218 class SC_DLLPUBLIC ScCompiler
: public formula::FormulaCompiler
222 enum ExtendedErrorDetection
224 EXTENDED_ERROR_DETECTION_NONE
= 0, // no error on unknown symbols, default (interpreter handles it)
225 EXTENDED_ERROR_DETECTION_NAME_BREAK
, // name error on unknown symbols and break, pCode incomplete
226 EXTENDED_ERROR_DETECTION_NAME_NO_BREAK
// name error on unknown symbols, don't break, continue
231 const formula::FormulaGrammar::AddressConvention meConv
;
233 Convention( formula::FormulaGrammar::AddressConvention eConvP
);
234 virtual ~Convention();
236 virtual void makeRefStr(
237 OUStringBuffer
& rBuffer
,
238 formula::FormulaGrammar::Grammar eGram
,
239 const ScAddress
& rPos
,
240 const OUString
& rErrRef
, const std::vector
<OUString
>& rTabNames
,
241 const ScComplexRefData
& rRef
, bool bSingleRef
) const = 0;
243 virtual ::com::sun::star::i18n::ParseResult
244 parseAnyToken( const OUString
& rFormula
,
246 const CharClass
* pCharClass
) const = 0;
249 * Parse the symbol string and pick up the file name and the external
252 * @return true on successful parse, or false otherwise.
254 virtual bool parseExternalName( const OUString
& rSymbol
, OUString
& rFile
, OUString
& rName
,
255 const ScDocument
* pDoc
,
256 const ::com::sun::star::uno::Sequence
<
257 com::sun::star::sheet::ExternalLinkInfo
>* pExternalLinks
) const = 0;
259 virtual OUString
makeExternalNameStr( sal_uInt16 nFileId
, const OUString
& rFile
,
260 const OUString
& rName
) const = 0;
262 virtual void makeExternalRefStr(
263 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
, sal_uInt16 nFileId
, const OUString
& rFileName
,
264 const OUString
& rTabName
, const ScSingleRefData
& rRef
) const = 0;
266 virtual void makeExternalRefStr(
267 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
,
268 sal_uInt16 nFileId
, const OUString
& rFileName
, const std::vector
<OUString
>& rTabNames
,
269 const OUString
& rTabName
, const ScComplexRefData
& rRef
) const = 0;
271 enum SpecialSymbolType
274 * Character between sheet name and address. In OOO A1 this is
275 * '.', while XL A1 and XL R1C1 this is '!'.
280 * In OOO A1, a sheet name may be prefixed with '$' to indicate an
281 * absolute sheet position.
285 virtual sal_Unicode
getSpecialSymbol( SpecialSymbolType eSymType
) const = 0;
287 virtual sal_uLong
getCharTableFlags( sal_Unicode c
, sal_Unicode cLast
) const = 0;
290 const sal_uLong
* mpCharTable
;
292 friend struct Convention
;
296 static CharClass
*pCharClassEnglish
; // character classification for en_US locale
297 static const Convention
*pConventions
[ formula::FormulaGrammar::CONV_LAST
];
299 static struct AddInMap
302 const char* pEnglish
;
303 bool bMapDupToInternal
; // when writing ODFF
304 const char* pOriginal
; // programmatical name
305 const char* pUpper
; // upper case programmatical name
307 static const AddInMap
* GetAddInMap();
308 static size_t GetAddInMapCount();
313 SvNumberFormatter
* mpFormatter
;
315 // For CONV_XL_OOX, may be set via API by MOOXML filter.
316 com::sun::star::uno::Sequence
<com::sun::star::sheet::ExternalLinkInfo
> maExternalLinks
;
318 sal_Unicode cSymbol
[MAXSTRLEN
]; // current Symbol
319 OUString aFormula
; // formula source code
320 sal_Int32 nSrcPos
; // tokenizer position (source code)
321 mutable ScRawToken maRawToken
;
323 const CharClass
* pCharClass
; // which character classification is used for parseAnyToken
324 sal_uInt16 mnPredetectedReference
; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
325 SCsTAB nMaxTab
; // last sheet in document
326 sal_Int32 mnRangeOpPosInSymbol
; // if and where a range operator is in symbol
327 const Convention
*pConv
;
328 ExtendedErrorDetection meExtendedErrorDetection
;
329 bool mbCloseBrackets
; // whether to close open brackets automatically, default TRUE
330 bool mbRewind
; // whether symbol is to be rewound to some step during lexical analysis
331 std::vector
<sal_uInt16
> maExternalFiles
;
333 std::vector
<OUString
> maTabNames
; /// sheet names mangled for the current grammer for output
334 std::vector
<OUString
> &GetSetupTabNames() const; /// get or setup tab names for the current grammar
336 bool NextNewToken(bool bInArray
= false);
338 virtual void SetError(sal_uInt16 nError
) SAL_OVERRIDE
;
339 sal_Int32
NextSymbol(bool bInArray
);
340 bool IsValue( const OUString
& );
341 bool IsOpCode( const OUString
&, bool bInArray
);
342 bool IsOpCode2( const OUString
& );
344 bool IsReference( const OUString
& );
345 bool IsSingleReference( const OUString
& );
346 bool IsPredetectedReference(const OUString
&);
347 bool IsDoubleReference( const OUString
& );
348 bool IsMacro( const OUString
& );
349 bool IsNamedRange( const OUString
& );
350 bool IsExternalNamedRange( const OUString
& rSymbol
, bool& rbInvalidExternalNameRange
);
351 bool IsDBRange( const OUString
& );
352 bool IsColRowName( const OUString
& );
353 bool IsBoolean( const OUString
& );
354 void AutoCorrectParsedSymbol();
356 void SetRelNameReference();
358 /** Obtain range data for ocName token, global or sheet local.
360 Prerequisite: rToken is a FormulaIndexToken so IsGlobal() and
361 GetIndex() can be called on it. We don't check with RTTI.
363 ScRangeData
* GetRangeData( const formula::FormulaToken
& pToken
) const;
365 static void InitCharClassEnglish();
368 ScCompiler( sc::CompileFormulaContext
& rCxt
, const ScAddress
& rPos
);
370 ScCompiler( ScDocument
* pDocument
, const ScAddress
&);
372 ScCompiler( sc::CompileFormulaContext
& rCxt
, const ScAddress
& rPos
, ScTokenArray
& rArr
);
374 ScCompiler( ScDocument
* pDocument
, const ScAddress
&,ScTokenArray
& rArr
);
376 virtual ~ScCompiler();
379 static void DeInit(); /// all
381 // for ScAddress::Format()
382 static void CheckTabQuotes( OUString
& aTabName
,
383 const formula::FormulaGrammar::AddressConvention eConv
= formula::FormulaGrammar::CONV_OOO
);
385 /** Analyzes a string for a 'Doc'#Tab construct, or 'Do''c'#Tab etc..
387 @returns the position of the unquoted # hash mark in 'Doc'#Tab, or
389 static sal_Int32
GetDocTabPos( const OUString
& rString
);
391 static bool EnQuote( OUString
& rStr
);
392 sal_Unicode
GetNativeAddressSymbol( Convention::SpecialSymbolType eType
) const;
394 // Check if it is a valid english function name
395 bool IsEnglishSymbol( const OUString
& rName
);
396 bool IsErrorConstant( const OUString
& ) const;
399 * When auto correction is set, the jump command reorder must be enabled.
401 void SetAutoCorrection( bool bVal
);
402 void SetCloseBrackets( bool bVal
) { mbCloseBrackets
= bVal
; }
403 void SetRefConvention( const Convention
*pConvP
);
404 void SetRefConvention( const formula::FormulaGrammar::AddressConvention eConv
);
406 static const Convention
* GetRefConvention( formula::FormulaGrammar::AddressConvention eConv
);
408 /// Set symbol map if not empty.
409 void SetFormulaLanguage( const OpCodeMapPtr
& xMap
);
411 void SetGrammar( const formula::FormulaGrammar::Grammar eGrammar
);
413 void SetNumberFormatter( SvNumberFormatter
* pFormatter
);
416 /** Set grammar and reference convention from within SetFormulaLanguage()
420 The new grammar to be set and the associated reference convention.
423 The previous grammar that was active before SetFormulaLanguage().
425 void SetGrammarAndRefConvention(
426 const formula::FormulaGrammar::Grammar eNewGrammar
,
427 const formula::FormulaGrammar::Grammar eOldGrammar
);
430 /// Set external link info for ScAddress::CONV_XL_OOX.
431 void SetExternalLinks(
432 const ::com::sun::star::uno::Sequence
<
433 com::sun::star::sheet::ExternalLinkInfo
>& rLinks
)
435 maExternalLinks
= rLinks
;
438 void CreateStringFromXMLTokenArray( OUString
& rFormula
, OUString
& rFormulaNmsp
);
440 void SetExtendedErrorDetection( ExtendedErrorDetection eVal
) { meExtendedErrorDetection
= eVal
; }
442 bool IsCorrected() { return bCorrected
; }
443 const OUString
& GetCorrectedFormula() { return aCorrectedFormula
; }
446 * Tokenize formula expression string into an array of tokens.
448 * @param rFormula formula expression to tokenize.
450 * @return heap allocated token array object. The caller <i>must</i>
451 * manage the life cycle of this object.
453 ScTokenArray
* CompileString( const OUString
& rFormula
);
454 ScTokenArray
* CompileString( const OUString
& rFormula
, const OUString
& rFormulaNmsp
);
455 const ScDocument
* GetDoc() const { return pDoc
; }
456 const ScAddress
& GetPos() const { return aPos
; }
458 void MoveRelWrap( SCCOL nMaxCol
, SCROW nMaxRow
);
459 static void MoveRelWrap( ScTokenArray
& rArr
, ScDocument
* pDoc
, const ScAddress
& rPos
,
460 SCCOL nMaxCol
, SCROW nMaxRow
);
462 /** If the character is allowed as tested by nFlags (SC_COMPILER_C_...
463 bits) for all known address conventions. If more than one bit is given
464 in nFlags, all bits must match. If bTestLetterNumeric is false and
465 char>=128, no LetterNumeric test is done and false is returned. */
466 static bool IsCharFlagAllConventions(
467 OUString
const & rStr
, sal_Int32 nPos
, sal_uLong nFlags
, bool bTestLetterNumeric
= true );
471 virtual OUString
FindAddInFunction( const OUString
& rUpperName
, bool bLocalFirst
) const SAL_OVERRIDE
;
472 virtual void fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr xMap
) const SAL_OVERRIDE
;
473 virtual void fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr xMap
) const SAL_OVERRIDE
;
474 virtual void fillFromAddInMap( NonConstOpCodeMapPtr xMap
, formula::FormulaGrammar::Grammar _eGrammar
) const SAL_OVERRIDE
;
475 virtual void fillAddInToken(::std::vector
< ::com::sun::star::sheet::FormulaOpCodeMapEntry
>& _rVec
,bool _bIsEnglish
) const SAL_OVERRIDE
;
477 virtual bool HandleExternalReference(const formula::FormulaToken
& _aToken
) SAL_OVERRIDE
;
478 virtual bool HandleRange() SAL_OVERRIDE
;
479 virtual bool HandleSingleRef() SAL_OVERRIDE
;
480 virtual bool HandleDbData() SAL_OVERRIDE
;
482 virtual formula::FormulaTokenRef
ExtendRangeReference( formula::FormulaToken
& rTok1
, formula::FormulaToken
& rTok2
, bool bReuseDoubleRef
) SAL_OVERRIDE
;
483 virtual void CreateStringFromExternal(OUStringBuffer
& rBuffer
, formula::FormulaToken
* pTokenP
) const SAL_OVERRIDE
;
484 virtual void CreateStringFromSingleRef(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const SAL_OVERRIDE
;
485 virtual void CreateStringFromDoubleRef(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const SAL_OVERRIDE
;
486 virtual void CreateStringFromMatrix( OUStringBuffer
& rBuffer
, formula::FormulaToken
* _pTokenP
) const SAL_OVERRIDE
;
487 virtual void CreateStringFromIndex(OUStringBuffer
& rBuffer
,formula::FormulaToken
* _pTokenP
) const SAL_OVERRIDE
;
488 virtual void LocalizeString( OUString
& rName
) const SAL_OVERRIDE
; // modify rName - input: exact name
490 /// Access the CharTable flags
491 inline sal_uLong
GetCharTableFlags( sal_Unicode c
, sal_Unicode cLast
)
492 { return c
< 128 ? pConv
->getCharTableFlags(c
, cLast
) : 0; }
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */