Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / inc / compiler.hxx
blob5f89b97044c79d90298ba7dc3fd14e8594c4ca67
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
23 #include <string.h>
25 #include <tools/mempool.hxx>
26 #include "scdllapi.h"
27 #include "global.hxx"
28 #include "refdata.hxx"
29 #include "token.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>
35 #include <vector>
37 #include <formula/FormulaCompiler.hxx>
38 #include <o3tl/typed_flags_set.hxx>
40 // constants and data types also for external modules (ScInterpreter et al)
42 #define MAXSTRLEN 1024 /* maximum length of input string of one symbol */
44 // flag values of CharTable
45 enum class ScCharFlags : sal_uInt32 {
46 NONE = 0x00000000,
47 Illegal = 0x00000000,
48 Char = 0x00000001,
49 CharBool = 0x00000002,
50 CharWord = 0x00000004,
51 CharValue = 0x00000008,
52 CharString = 0x00000010,
53 CharDontCare = 0x00000020,
54 Bool = 0x00000040,
55 Word = 0x00000080,
56 WordSep = 0x00000100,
57 Value = 0x00000200,
58 ValueSep = 0x00000400,
59 ValueExp = 0x00000800,
60 ValueSign = 0x00001000,
61 ValueValue = 0x00002000,
62 StringSep = 0x00004000,
63 NameSep = 0x00008000, // there can be only one! '\''
64 CharIdent = 0x00010000, // identifier (built-in function) or reference start
65 Ident = 0x00020000, // identifier or reference continuation
66 OdfLBracket = 0x00040000, // ODF '[' reference bracket
67 OdfRBracket = 0x00080000, // ODF ']' reference bracket
68 OdfLabelOp = 0x00100000, // ODF '!!' automatic intersection of labels
69 OdfNameMarker = 0x00200000, // ODF '$$' marker that starts a defined (range) name
70 CharName = 0x00400000, // start character of a defined name
71 Name = 0x00800000, // continuation character of a defined name
72 CharErrConst = 0x01000000, // start character of an error constant ('#')
74 namespace o3tl {
75 template<> struct typed_flags<ScCharFlags> : is_typed_flags<ScCharFlags, 0x01ffffff> {};
78 #define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab
80 class ScDocument;
81 class ScMatrix;
82 class ScRangeData;
83 class ScExternalRefManager;
84 class ScTokenArray;
86 namespace sc {
88 class CompileFormulaContext;
92 // constants and data types internal to compiler
95 OpCode eOp; // OpCode
96 formula::StackVar eType; // type of data
99 struct ScRawTokenBase
101 protected:
102 OpCode eOp;
103 formula::StackVar eType;
106 struct ScRawToken: private ScRawTokenBase
108 friend class ScCompiler;
109 // Friends that use a temporary ScRawToken on the stack (and therefore need
110 // the private dtor) and know what they're doing..
111 friend class ScTokenArray;
112 public:
113 union {
114 double nValue;
115 struct {
116 sal_uInt8 cByte;
117 bool bIsInForceArray;
118 } sbyte;
119 ScComplexRefData aRef;
120 struct {
121 sal_uInt16 nFileId;
122 sal_Unicode cTabName[MAXSTRLEN+1];
123 ScComplexRefData aRef;
124 } extref;
125 struct {
126 sal_uInt16 nFileId;
127 sal_Unicode cName[MAXSTRLEN+1];
128 } extname;
129 struct {
130 sal_Int16 nSheet;
131 sal_uInt16 nIndex;
132 } name;
133 struct {
134 sal_uInt16 nIndex;
135 ScTableRefToken::Item eItem;
136 } table;
137 struct {
138 rtl_uString* mpData;
139 rtl_uString* mpDataIgnoreCase;
140 } sharedstring;
141 ScMatrix* pMat;
142 sal_uInt16 nError;
143 sal_Unicode cStr[ MAXSTRLEN+1 ]; // string (up to 255 characters + 0)
144 short nJump[ FORMULA_MAXJUMPCOUNT + 1 ]; // If/Chose token
147 //! members not initialized
148 ScRawToken() {}
149 private:
150 ~ScRawToken() {} //! only delete via Delete()
151 public:
152 DECL_FIXEDMEMPOOL_NEWDEL( ScRawToken );
153 formula::StackVar GetType() const { return eType; }
154 OpCode GetOpCode() const { return eOp; }
155 void NewOpCode( OpCode e ) { eOp = e; }
157 // Use these methods only on tokens that are not part of a token array,
158 // since the reference count is cleared!
159 void SetOpCode( OpCode eCode );
160 void SetString( rtl_uString* pData, rtl_uString* pDataIgoreCase );
161 void SetSingleReference( const ScSingleRefData& rRef );
162 void SetDoubleReference( const ScComplexRefData& rRef );
163 void SetDouble( double fVal );
164 void SetErrorConstant( sal_uInt16 nErr );
166 // These methods are ok to use, reference count not cleared.
167 void SetName(sal_Int16 nSheet, sal_uInt16 nIndex);
168 void SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef );
169 void SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef );
170 void SetExternalName( sal_uInt16 nFileId, const OUString& rName );
171 void SetExternal(const sal_Unicode* pStr);
173 /** If the token is a non-external reference, determine if the reference is
174 valid. If the token is an external reference, return true. Else return
175 false. Used only in ScCompiler::NextNewToken() to preserve non-existing
176 sheet names in otherwise valid references.
178 bool IsValidReference() const;
180 formula::FormulaToken* CreateToken() const; // create typified token
182 static sal_Int32 GetStrLen( const sal_Unicode* pStr ); // as long as a "string" is an array
183 static size_t GetStrLenBytes( sal_Int32 nLen )
184 { return nLen * sizeof(sal_Unicode); }
187 class SC_DLLPUBLIC ScCompiler : public formula::FormulaCompiler
189 public:
191 enum ExtendedErrorDetection
193 EXTENDED_ERROR_DETECTION_NONE = 0, // no error on unknown symbols, default (interpreter handles it)
194 EXTENDED_ERROR_DETECTION_NAME_BREAK, // name error on unknown symbols and break, pCode incomplete
195 EXTENDED_ERROR_DETECTION_NAME_NO_BREAK // name error on unknown symbols, don't break, continue
198 struct Convention
200 const formula::FormulaGrammar::AddressConvention meConv;
202 Convention( formula::FormulaGrammar::AddressConvention eConvP );
203 virtual ~Convention();
205 virtual void makeRefStr(
206 OUStringBuffer& rBuffer,
207 formula::FormulaGrammar::Grammar eGram,
208 const ScAddress& rPos,
209 const OUString& rErrRef, const std::vector<OUString>& rTabNames,
210 const ScComplexRefData& rRef, bool bSingleRef, bool bFromRangeName ) const = 0;
212 virtual css::i18n::ParseResult
213 parseAnyToken( const OUString& rFormula,
214 sal_Int32 nSrcPos,
215 const CharClass* pCharClass) const = 0;
218 * Parse the symbol string and pick up the file name and the external
219 * range name.
221 * @return true on successful parse, or false otherwise.
223 virtual bool parseExternalName( const OUString& rSymbol, OUString& rFile, OUString& rName,
224 const ScDocument* pDoc,
225 const css::uno::Sequence< css::sheet::ExternalLinkInfo>* pExternalLinks ) const = 0;
227 virtual OUString makeExternalNameStr( sal_uInt16 nFileId, const OUString& rFile,
228 const OUString& rName ) const = 0;
230 virtual void makeExternalRefStr(
231 OUStringBuffer& rBuffer, const ScAddress& rPos, sal_uInt16 nFileId, const OUString& rFileName,
232 const OUString& rTabName, const ScSingleRefData& rRef ) const = 0;
234 virtual void makeExternalRefStr(
235 OUStringBuffer& rBuffer, const ScAddress& rPos,
236 sal_uInt16 nFileId, const OUString& rFileName, const std::vector<OUString>& rTabNames,
237 const OUString& rTabName, const ScComplexRefData& rRef ) const = 0;
239 enum SpecialSymbolType
242 * Character between sheet name and address. In OOO A1 this is
243 * '.', while XL A1 and XL R1C1 this is '!'.
245 SHEET_SEPARATOR,
248 * In OOO A1, a sheet name may be prefixed with '$' to indicate an
249 * absolute sheet position.
251 ABS_SHEET_PREFIX
253 virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const = 0;
255 virtual ScCharFlags getCharTableFlags( sal_Unicode c, sal_Unicode cLast ) const = 0;
257 protected:
258 const ScCharFlags* mpCharTable;
260 friend struct Convention;
262 private:
264 static CharClass *pCharClassEnglish; // character classification for en_US locale
265 static const Convention *pConventions[ formula::FormulaGrammar::CONV_LAST ];
267 static struct AddInMap
269 const char* pODFF;
270 const char* pEnglish;
271 const char* pOriginal; // programmatical name
272 const char* pUpper; // upper case programmatical name
273 } maAddInMap[];
274 static const AddInMap* GetAddInMap();
275 static size_t GetAddInMapCount();
277 ScDocument* pDoc;
278 ScAddress aPos;
280 SvNumberFormatter* mpFormatter;
282 SCTAB mnCurrentSheetTab; // indicates current sheet number parsed so far
283 sal_Int32 mnCurrentSheetEndPos; // position after current sheet name if parsed
285 // For CONV_XL_OOX, may be set via API by MOOXML filter.
286 css::uno::Sequence<css::sheet::ExternalLinkInfo> maExternalLinks;
288 sal_Unicode cSymbol[MAXSTRLEN]; // current Symbol
289 OUString aFormula; // formula source code
290 sal_Int32 nSrcPos; // tokenizer position (source code)
291 mutable ScRawToken maRawToken;
293 const CharClass* pCharClass; // which character classification is used for parseAnyToken
294 sal_uInt16 mnPredetectedReference; // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
295 SCsTAB nMaxTab; // last sheet in document
296 sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol
297 const Convention *pConv;
298 ExtendedErrorDetection meExtendedErrorDetection;
299 bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE
300 bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis
301 std::vector<sal_uInt16> maExternalFiles;
303 std::vector<OUString> maTabNames; /// sheet names mangled for the current grammar for output
304 std::vector<OUString> &GetSetupTabNames() const; /// get or setup tab names for the current grammar
306 struct TableRefEntry
308 ScTokenRef mxToken;
309 sal_uInt16 mnLevel;
310 TableRefEntry( formula::FormulaToken* p ) : mxToken(p), mnLevel(0) {}
312 std::vector<TableRefEntry> maTableRefs; /// "stack" of currently active ocTableRef tokens
314 bool NextNewToken(bool bInArray = false);
316 virtual void SetError(sal_uInt16 nError) override;
317 sal_Int32 NextSymbol(bool bInArray);
318 bool IsValue( const OUString& );
319 bool IsOpCode( const OUString&, bool bInArray );
320 bool IsOpCode2( const OUString& );
321 bool IsString();
322 bool IsReference( const OUString& rSymbol, const OUString* pErrRef = nullptr );
323 bool IsSingleReference( const OUString& rSymbol, const OUString* pErrRef = nullptr );
324 bool IsDoubleReference( const OUString& rSymbol, const OUString* pErrRef = nullptr );
325 bool IsPredetectedReference( const OUString& rSymbol );
326 bool IsPredetectedErrRefReference( const OUString& rName, const OUString* pErrRef );
327 bool IsMacro( const OUString& );
328 bool IsNamedRange( const OUString& );
329 bool IsExternalNamedRange( const OUString& rSymbol, bool& rbInvalidExternalNameRange );
330 bool IsDBRange( const OUString& );
331 bool IsColRowName( const OUString& );
332 bool IsBoolean( const OUString& );
333 void AutoCorrectParsedSymbol();
335 void AdjustSheetLocalNameRelReferences( SCTAB nDelta );
336 void SetRelNameReference();
338 /** Obtain range data for ocName token, global or sheet local.
340 Prerequisite: rToken is a FormulaIndexToken so IsGlobal() and
341 GetIndex() can be called on it. We don't check with RTTI.
343 ScRangeData* GetRangeData( const formula::FormulaToken& pToken ) const;
345 static void InitCharClassEnglish();
347 public:
348 ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos );
350 ScCompiler( ScDocument* pDocument, const ScAddress&);
352 ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, ScTokenArray& rArr );
354 ScCompiler( ScDocument* pDocument, const ScAddress&,ScTokenArray& rArr);
356 virtual ~ScCompiler();
358 public:
359 static void DeInit(); /// all
361 // for ScAddress::Format()
362 static void CheckTabQuotes( OUString& aTabName,
363 const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO );
365 /** Analyzes a string for a 'Doc'#Tab construct, or 'Do''c'#Tab etc..
367 @returns the position of the unquoted # hash mark in 'Doc'#Tab, or
368 -1 if none. */
369 static sal_Int32 GetDocTabPos( const OUString& rString );
371 static bool EnQuote( OUString& rStr );
372 sal_Unicode GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const;
374 // Check if it is a valid english function name
375 bool IsEnglishSymbol( const OUString& rName );
377 bool IsErrorConstant( const OUString& ) const;
378 bool IsTableRefItem( const OUString& ) const;
379 bool IsTableRefColumn( const OUString& ) const;
381 /** Calls GetToken() if PeekNextNoSpaces() is of given OpCode. */
382 bool GetTokenIfOpCode( OpCode eOp );
385 * When auto correction is set, the jump command reorder must be enabled.
387 void SetAutoCorrection( bool bVal );
388 void SetCloseBrackets( bool bVal ) { mbCloseBrackets = bVal; }
389 void SetRefConvention( const Convention *pConvP );
390 void SetRefConvention( const formula::FormulaGrammar::AddressConvention eConv );
392 static const Convention* GetRefConvention( formula::FormulaGrammar::AddressConvention eConv );
394 /// Set symbol map if not empty.
395 void SetFormulaLanguage( const OpCodeMapPtr & xMap );
397 void SetGrammar( const formula::FormulaGrammar::Grammar eGrammar );
399 void SetNumberFormatter( SvNumberFormatter* pFormatter );
401 private:
402 /** Set grammar and reference convention from within SetFormulaLanguage()
403 or SetGrammar().
405 @param eNewGrammar
406 The new grammar to be set and the associated reference convention.
408 @param eOldGrammar
409 The previous grammar that was active before SetFormulaLanguage().
411 void SetGrammarAndRefConvention(
412 const formula::FormulaGrammar::Grammar eNewGrammar,
413 const formula::FormulaGrammar::Grammar eOldGrammar );
414 public:
416 /// Set external link info for ScAddress::CONV_XL_OOX.
417 void SetExternalLinks(
418 const css::uno::Sequence<
419 css::sheet::ExternalLinkInfo>& rLinks )
421 maExternalLinks = rLinks;
424 void CreateStringFromXMLTokenArray( OUString& rFormula, OUString& rFormulaNmsp );
426 void SetExtendedErrorDetection( ExtendedErrorDetection eVal ) { meExtendedErrorDetection = eVal; }
428 bool IsCorrected() { return bCorrected; }
429 const OUString& GetCorrectedFormula() { return aCorrectedFormula; }
432 * Tokenize formula expression string into an array of tokens.
434 * @param rFormula formula expression to tokenize.
436 * @return heap allocated token array object. The caller <i>must</i>
437 * manage the life cycle of this object.
439 ScTokenArray* CompileString( const OUString& rFormula );
440 ScTokenArray* CompileString( const OUString& rFormula, const OUString& rFormulaNmsp );
441 const ScAddress& GetPos() const { return aPos; }
443 void MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow );
444 static void MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos,
445 SCCOL nMaxCol, SCROW nMaxRow );
447 /** If the character is allowed as tested by nFlags (SC_COMPILER_C_...
448 bits) for all known address conventions. If more than one bit is given
449 in nFlags, all bits must match. */
450 static bool IsCharFlagAllConventions(
451 OUString const & rStr, sal_Int32 nPos, ScCharFlags nFlags );
453 private:
454 // FormulaCompiler
455 virtual OUString FindAddInFunction( const OUString& rUpperName, bool bLocalFirst ) const override;
456 virtual void fillFromAddInCollectionUpperName( const NonConstOpCodeMapPtr& xMap ) const override;
457 virtual void fillFromAddInCollectionEnglishName( const NonConstOpCodeMapPtr& xMap ) const override;
458 virtual void fillFromAddInMap( const NonConstOpCodeMapPtr& xMap, formula::FormulaGrammar::Grammar _eGrammar ) const override;
459 virtual void fillAddInToken(::std::vector< css::sheet::FormulaOpCodeMapEntry >& _rVec,bool _bIsEnglish) const override;
461 virtual bool HandleExternalReference(const formula::FormulaToken& _aToken) override;
462 virtual bool HandleRange() override;
463 virtual bool HandleColRowName() override;
464 virtual bool HandleDbData() override;
465 virtual bool HandleTableRef() override;
467 virtual formula::FormulaTokenRef ExtendRangeReference( formula::FormulaToken & rTok1, formula::FormulaToken & rTok2 ) override;
468 virtual void CreateStringFromExternal( OUStringBuffer& rBuffer, const formula::FormulaToken* pToken ) const override;
469 virtual void CreateStringFromSingleRef( OUStringBuffer& rBuffer, const formula::FormulaToken* pToken ) const override;
470 virtual void CreateStringFromDoubleRef( OUStringBuffer& rBuffer, const formula::FormulaToken* pToken ) const override;
471 virtual void CreateStringFromMatrix( OUStringBuffer& rBuffer, const formula::FormulaToken* pToken ) const override;
472 virtual void CreateStringFromIndex( OUStringBuffer& rBuffer, const formula::FormulaToken* pToken ) const override;
473 virtual void LocalizeString( OUString& rName ) const override; // modify rName - input: exact name
475 virtual bool IsForceArrayParameter( const formula::FormulaToken* pToken, sal_uInt16 nParam ) const override;
477 /// Access the CharTable flags
478 inline ScCharFlags GetCharTableFlags( sal_Unicode c, sal_Unicode cLast )
479 { return c < 128 ? pConv->getCharTableFlags(c, cLast) : ScCharFlags::NONE; }
482 #endif
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */