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"
30 #include <formula/token.hxx>
31 #include <formula/grammar.hxx>
32 #include <unotools/charclass.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/sheet/ExternalLinkInfo.hpp>
37 #include <formula/FormulaCompiler.hxx>
39 // constants and data types also for external modules (ScInterpreter et al)
41 #define MAXSTRLEN 1024 /* maximum length of input string of one symbol */
43 // flag values of CharTable
44 #define SC_COMPILER_C_ILLEGAL 0x00000000
45 #define SC_COMPILER_C_CHAR 0x00000001
46 #define SC_COMPILER_C_CHAR_BOOL 0x00000002
47 #define SC_COMPILER_C_CHAR_WORD 0x00000004
48 #define SC_COMPILER_C_CHAR_VALUE 0x00000008
49 #define SC_COMPILER_C_CHAR_STRING 0x00000010
50 #define SC_COMPILER_C_CHAR_DONTCARE 0x00000020
51 #define SC_COMPILER_C_BOOL 0x00000040
52 #define SC_COMPILER_C_WORD 0x00000080
53 #define SC_COMPILER_C_WORD_SEP 0x00000100
54 #define SC_COMPILER_C_VALUE 0x00000200
55 #define SC_COMPILER_C_VALUE_SEP 0x00000400
56 #define SC_COMPILER_C_VALUE_EXP 0x00000800
57 #define SC_COMPILER_C_VALUE_SIGN 0x00001000
58 #define SC_COMPILER_C_VALUE_VALUE 0x00002000
59 #define SC_COMPILER_C_STRING_SEP 0x00004000
60 #define SC_COMPILER_C_NAME_SEP 0x00008000 // there can be only one! '\''
61 #define SC_COMPILER_C_CHAR_IDENT 0x00010000 // identifier (built-in function) or reference start
62 #define SC_COMPILER_C_IDENT 0x00020000 // identifier or reference continuation
63 #define SC_COMPILER_C_ODF_LBRACKET 0x00040000 // ODF '[' reference bracket
64 #define SC_COMPILER_C_ODF_RBRACKET 0x00080000 // ODF ']' reference bracket
65 #define SC_COMPILER_C_ODF_LABEL_OP 0x00100000 // ODF '!!' automatic intersection of labels
66 #define SC_COMPILER_C_ODF_NAME_MARKER 0x00200000 // ODF '$$' marker that starts a defined (range) name
67 #define SC_COMPILER_C_CHAR_NAME 0x00400000 // start character of a defined name
68 #define SC_COMPILER_C_NAME 0x00800000 // continuation character of a defined name
69 #define SC_COMPILER_C_CHAR_ERRCONST 0x01000000 // start character of an error constant ('#')
71 #define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab
76 class ScExternalRefManager
;
81 class CompileFormulaContext
;
85 // constants and data types internal to compiler
89 formula::StackVar eType; // type of data
96 formula::StackVar eType
;
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 therefore need
117 // the private dtor) and know what they're doing..
118 friend class ScTokenArray
;
126 ScComplexRefData aRef
;
129 sal_Unicode cTabName
[MAXSTRLEN
+1];
130 ScComplexRefData aRef
;
134 sal_Unicode cName
[MAXSTRLEN
+1];
142 ScTableRefToken::Item eItem
;
146 rtl_uString
* mpDataIgnoreCase
;
150 sal_Unicode cStr
[ MAXSTRLEN
+1 ]; // string (up to 255 characters + 0)
151 short nJump
[ FORMULA_MAXJUMPCOUNT
+ 1 ]; // If/Chose token
154 //! members not initialized
157 ~ScRawToken() {} //! only delete via Delete()
159 DECL_FIXEDMEMPOOL_NEWDEL( ScRawToken
);
160 formula::StackVar
GetType() const { return eType
; }
161 OpCode
GetOpCode() const { return eOp
; }
162 void NewOpCode( OpCode e
) { eOp
= e
; }
164 // Use these methods only on tokens that are not part of a token array,
165 // since the reference count is cleared!
166 void SetOpCode( OpCode eCode
);
167 void SetString( rtl_uString
* pData
, rtl_uString
* pDataIgoreCase
);
168 void SetSingleReference( const ScSingleRefData
& rRef
);
169 void SetDoubleReference( const ScComplexRefData
& rRef
);
170 void SetDouble( double fVal
);
171 void SetErrorConstant( sal_uInt16 nErr
);
173 // These methods are ok to use, reference count not cleared.
174 void SetName(bool bGlobal
, sal_uInt16 nIndex
);
175 void SetExternalSingleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScSingleRefData
& rRef
);
176 void SetExternalDoubleRef( sal_uInt16 nFileId
, const OUString
& rTabName
, const ScComplexRefData
& rRef
);
177 void SetExternalName( sal_uInt16 nFileId
, const OUString
& rName
);
178 void SetMatrix( ScMatrix
* p
);
179 void SetExternal(const sal_Unicode
* pStr
);
181 /** If the token is a non-external reference, determine if the reference is
182 valid. If the token is an external reference, return true. Else return
183 false. Used only in ScCompiler::NextNewToken() to preserve non-existing
184 sheet names in otherwise valid references.
186 bool IsValidReference() const;
188 formula::FormulaToken
* CreateToken() const; // create typified token
189 void Load( SvStream
&, sal_uInt16 nVer
);
191 static sal_Int32
GetStrLen( const sal_Unicode
* pStr
); // as long as a "string" is an array
192 static size_t GetStrLenBytes( sal_Int32 nLen
)
193 { return nLen
* sizeof(sal_Unicode
); }
194 static size_t GetStrLenBytes( const sal_Unicode
* pStr
)
195 { return GetStrLenBytes( GetStrLen( pStr
) ); }
198 class SC_DLLPUBLIC ScCompiler
: public formula::FormulaCompiler
202 enum ExtendedErrorDetection
204 EXTENDED_ERROR_DETECTION_NONE
= 0, // no error on unknown symbols, default (interpreter handles it)
205 EXTENDED_ERROR_DETECTION_NAME_BREAK
, // name error on unknown symbols and break, pCode incomplete
206 EXTENDED_ERROR_DETECTION_NAME_NO_BREAK
// name error on unknown symbols, don't break, continue
211 const formula::FormulaGrammar::AddressConvention meConv
;
213 Convention( formula::FormulaGrammar::AddressConvention eConvP
);
214 virtual ~Convention();
216 virtual void makeRefStr(
217 OUStringBuffer
& rBuffer
,
218 formula::FormulaGrammar::Grammar eGram
,
219 const ScAddress
& rPos
,
220 const OUString
& rErrRef
, const std::vector
<OUString
>& rTabNames
,
221 const ScComplexRefData
& rRef
, bool bSingleRef
, bool bFromRangeName
) const = 0;
223 virtual ::com::sun::star::i18n::ParseResult
224 parseAnyToken( const OUString
& rFormula
,
226 const CharClass
* pCharClass
) const = 0;
229 * Parse the symbol string and pick up the file name and the external
232 * @return true on successful parse, or false otherwise.
234 virtual bool parseExternalName( const OUString
& rSymbol
, OUString
& rFile
, OUString
& rName
,
235 const ScDocument
* pDoc
,
236 const ::com::sun::star::uno::Sequence
<
237 com::sun::star::sheet::ExternalLinkInfo
>* pExternalLinks
) const = 0;
239 virtual OUString
makeExternalNameStr( sal_uInt16 nFileId
, const OUString
& rFile
,
240 const OUString
& rName
) const = 0;
242 virtual void makeExternalRefStr(
243 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
, sal_uInt16 nFileId
, const OUString
& rFileName
,
244 const OUString
& rTabName
, const ScSingleRefData
& rRef
) const = 0;
246 virtual void makeExternalRefStr(
247 OUStringBuffer
& rBuffer
, const ScAddress
& rPos
,
248 sal_uInt16 nFileId
, const OUString
& rFileName
, const std::vector
<OUString
>& rTabNames
,
249 const OUString
& rTabName
, const ScComplexRefData
& rRef
) const = 0;
251 enum SpecialSymbolType
254 * Character between sheet name and address. In OOO A1 this is
255 * '.', while XL A1 and XL R1C1 this is '!'.
260 * In OOO A1, a sheet name may be prefixed with '$' to indicate an
261 * absolute sheet position.
265 virtual sal_Unicode
getSpecialSymbol( SpecialSymbolType eSymType
) const = 0;
267 virtual sal_uLong
getCharTableFlags( sal_Unicode c
, sal_Unicode cLast
) const = 0;
270 const sal_uLong
* mpCharTable
;
272 friend struct Convention
;
276 static CharClass
*pCharClassEnglish
; // character classification for en_US locale
277 static const Convention
*pConventions
[ formula::FormulaGrammar::CONV_LAST
];
279 static struct AddInMap
282 const char* pEnglish
;
283 const char* pOriginal
; // programmatical name
284 const char* pUpper
; // upper case programmatical name
286 static const AddInMap
* GetAddInMap();
287 static size_t GetAddInMapCount();
292 SvNumberFormatter
* mpFormatter
;
294 // For CONV_XL_OOX, may be set via API by MOOXML filter.
295 com::sun::star::uno::Sequence
<com::sun::star::sheet::ExternalLinkInfo
> maExternalLinks
;
297 sal_Unicode cSymbol
[MAXSTRLEN
]; // current Symbol
298 OUString aFormula
; // formula source code
299 sal_Int32 nSrcPos
; // tokenizer position (source code)
300 mutable ScRawToken maRawToken
;
302 const CharClass
* pCharClass
; // which character classification is used for parseAnyToken
303 sal_uInt16 mnPredetectedReference
; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
304 SCsTAB nMaxTab
; // last sheet in document
305 sal_Int32 mnRangeOpPosInSymbol
; // if and where a range operator is in symbol
306 const Convention
*pConv
;
307 ExtendedErrorDetection meExtendedErrorDetection
;
308 bool mbCloseBrackets
; // whether to close open brackets automatically, default TRUE
309 bool mbRewind
; // whether symbol is to be rewound to some step during lexical analysis
310 std::vector
<sal_uInt16
> maExternalFiles
;
312 std::vector
<OUString
> maTabNames
; /// sheet names mangled for the current grammar for output
313 std::vector
<OUString
> &GetSetupTabNames() const; /// get or setup tab names for the current grammar
319 TableRefEntry( formula::FormulaToken
* p
) : mxToken(p
), mnLevel(0) {}
321 std::vector
<TableRefEntry
> maTableRefs
; /// "stack" of currently active ocTableRef tokens
323 bool NextNewToken(bool bInArray
= false);
325 virtual void SetError(sal_uInt16 nError
) SAL_OVERRIDE
;
326 sal_Int32
NextSymbol(bool bInArray
);
327 bool IsValue( const OUString
& );
328 bool IsOpCode( const OUString
&, bool bInArray
);
329 bool IsOpCode2( const OUString
& );
331 bool IsReference( const OUString
& );
332 bool IsSingleReference( const OUString
& );
333 bool IsPredetectedReference(const OUString
&);
334 bool IsDoubleReference( const OUString
& );
335 bool IsMacro( const OUString
& );
336 bool IsNamedRange( const OUString
& );
337 bool IsExternalNamedRange( const OUString
& rSymbol
, bool& rbInvalidExternalNameRange
);
338 bool IsDBRange( const OUString
& );
339 bool IsColRowName( const OUString
& );
340 bool IsBoolean( const OUString
& );
341 void AutoCorrectParsedSymbol();
343 void SetRelNameReference();
345 /** Obtain range data for ocName token, global or sheet local.
347 Prerequisite: rToken is a FormulaIndexToken so IsGlobal() and
348 GetIndex() can be called on it. We don't check with RTTI.
350 ScRangeData
* GetRangeData( const formula::FormulaToken
& pToken
) const;
352 static void InitCharClassEnglish();
355 ScCompiler( sc::CompileFormulaContext
& rCxt
, const ScAddress
& rPos
);
357 ScCompiler( ScDocument
* pDocument
, const ScAddress
&);
359 ScCompiler( sc::CompileFormulaContext
& rCxt
, const ScAddress
& rPos
, ScTokenArray
& rArr
);
361 ScCompiler( ScDocument
* pDocument
, const ScAddress
&,ScTokenArray
& rArr
);
363 virtual ~ScCompiler();
366 static void DeInit(); /// all
368 // for ScAddress::Format()
369 static void CheckTabQuotes( OUString
& aTabName
,
370 const formula::FormulaGrammar::AddressConvention eConv
= formula::FormulaGrammar::CONV_OOO
);
372 /** Analyzes a string for a 'Doc'#Tab construct, or 'Do''c'#Tab etc..
374 @returns the position of the unquoted # hash mark in 'Doc'#Tab, or
376 static sal_Int32
GetDocTabPos( const OUString
& rString
);
378 static bool EnQuote( OUString
& rStr
);
379 sal_Unicode
GetNativeAddressSymbol( Convention::SpecialSymbolType eType
) const;
381 // Check if it is a valid english function name
382 bool IsEnglishSymbol( const OUString
& rName
);
384 bool IsErrorConstant( const OUString
& ) const;
385 bool IsTableRefItem( const OUString
& ) const;
386 bool IsTableRefColumn( const OUString
& ) const;
388 /** Calls GetToken() if PeekNextNoSpaces() is of given OpCode. */
389 bool GetTokenIfOpCode( OpCode eOp
);
392 * When auto correction is set, the jump command reorder must be enabled.
394 void SetAutoCorrection( bool 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 void SetExternalLinks(
425 const ::com::sun::star::uno::Sequence
<
426 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
, sal_Int32 nPos
, sal_uLong nFlags
, bool bTestLetterNumeric
= true );
464 virtual OUString
FindAddInFunction( const OUString
& rUpperName
, bool bLocalFirst
) const SAL_OVERRIDE
;
465 virtual void fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr xMap
) const SAL_OVERRIDE
;
466 virtual void fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr xMap
) const SAL_OVERRIDE
;
467 virtual void fillFromAddInMap( NonConstOpCodeMapPtr xMap
, formula::FormulaGrammar::Grammar _eGrammar
) const SAL_OVERRIDE
;
468 virtual void fillAddInToken(::std::vector
< ::com::sun::star::sheet::FormulaOpCodeMapEntry
>& _rVec
,bool _bIsEnglish
) const SAL_OVERRIDE
;
470 virtual bool HandleExternalReference(const formula::FormulaToken
& _aToken
) SAL_OVERRIDE
;
471 virtual bool HandleRange() SAL_OVERRIDE
;
472 virtual bool HandleColRowName() SAL_OVERRIDE
;
473 virtual bool HandleDbData() SAL_OVERRIDE
;
474 virtual bool HandleTableRef() SAL_OVERRIDE
;
476 virtual formula::FormulaTokenRef
ExtendRangeReference( formula::FormulaToken
& rTok1
, formula::FormulaToken
& rTok2
, bool bReuseDoubleRef
) SAL_OVERRIDE
;
477 virtual void CreateStringFromExternal( OUStringBuffer
& rBuffer
, const formula::FormulaToken
* pToken
) const SAL_OVERRIDE
;
478 virtual void CreateStringFromSingleRef( OUStringBuffer
& rBuffer
, const formula::FormulaToken
* pToken
) const SAL_OVERRIDE
;
479 virtual void CreateStringFromDoubleRef( OUStringBuffer
& rBuffer
, const formula::FormulaToken
* pToken
) const SAL_OVERRIDE
;
480 virtual void CreateStringFromMatrix( OUStringBuffer
& rBuffer
, const formula::FormulaToken
* pToken
) const SAL_OVERRIDE
;
481 virtual void CreateStringFromIndex( OUStringBuffer
& rBuffer
, const formula::FormulaToken
* pToken
) const SAL_OVERRIDE
;
482 virtual void LocalizeString( OUString
& rName
) const SAL_OVERRIDE
; // modify rName - input: exact name
484 virtual bool IsForceArrayParameter( const formula::FormulaToken
* pToken
, sal_uInt16 nParam
) const SAL_OVERRIDE
;
486 /// Access the CharTable flags
487 inline sal_uLong
GetCharTableFlags( sal_Unicode c
, sal_Unicode cLast
)
488 { return c
< 128 ? pConv
->getCharTableFlags(c
, cLast
) : 0; }
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */