[Libreoffice-commits] core.git: 6 commits - formula/source include/formula sc/source
Eike Rathke
erack at redhat.com
Sat Apr 23 13:53:01 UTC 2016
formula/source/core/api/FormulaCompiler.cxx | 167 +++++++++++++++++++++----
formula/source/core/api/token.cxx | 5
formula/source/core/resource/core_resource.src | 2
include/formula/grammar.hxx | 15 ++
include/formula/tokenarray.hxx | 26 +--
sc/source/core/tool/compiler.cxx | 4
sc/source/core/tool/token.cxx | 4
7 files changed, 176 insertions(+), 47 deletions(-)
New commits:
commit 26adceb098134d918f6d57c8687ab057e24adc39
Author: Eike Rathke <erack at redhat.com>
Date: Sat Apr 23 15:44:13 2016 +0200
Resolves: tdf#96426 significant whitespace as intersection in Excel syntax
Also when reading/writing OOXML, so change SC_OPCODE_INTERSECT of
RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML accordingly to " ", where
previously "!" was expected and written, which was plain wrong.
Change-Id: Ic0cfd7afc657f07bfd8e37de61b3621cc68685ff
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index fdf21e0..303e00e 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1061,6 +1061,7 @@ bool FormulaCompiler::GetToken()
bStop = true;
else
{
+ FormulaTokenRef pSpacesToken;
short nWasColRowName;
if ( pArr->nIndex > 0 && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
nWasColRowName = 1;
@@ -1069,6 +1070,9 @@ bool FormulaCompiler::GetToken()
mpToken = pArr->Next();
while( mpToken && mpToken->GetOpCode() == ocSpaces )
{
+ // For significant whitespace remember last ocSpaces token. Usually
+ // there's only one even for multiple spaces.
+ pSpacesToken = mpToken;
if ( nWasColRowName )
nWasColRowName++;
if ( bAutoCorrect && !pStack )
@@ -1094,6 +1098,14 @@ bool FormulaCompiler::GetToken()
mpToken = new FormulaByteToken( ocIntersect );
pArr->nIndex--; // we advanced to the second ocColRowName, step back
}
+ else if (pSpacesToken && FormulaGrammar::isExcelSyntax( meGrammar))
+ {
+ // Let IntersectionLine() <- Factor() decide how to treat this,
+ // once the actual arguments are determined in RPN.
+ mpToken = pSpacesToken;
+ pArr->nIndex--; // step back from next non-spaces token
+ return true;
+ }
}
}
if( bStop )
@@ -1562,15 +1574,98 @@ void FormulaCompiler::RangeLine()
}
}
+namespace {
+
+bool isRangeResultFunction( OpCode eOp )
+{
+ switch (eOp)
+ {
+ case ocIndirect:
+ case ocOffset:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool isRangeResultOpCode( OpCode eOp )
+{
+ switch (eOp)
+ {
+ case ocRange:
+ case ocUnion:
+ case ocIntersect:
+ case ocIndirect:
+ case ocOffset:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool isPotentialRangeType( FormulaToken* pToken, bool bRPN )
+{
+ switch (pToken->GetType())
+ {
+ case svByte: // could be range result, but only a few
+ if (bRPN)
+ return isRangeResultOpCode( pToken->GetOpCode());
+ else
+ return isRangeResultFunction( pToken->GetOpCode());
+ case svSingleRef:
+ case svDoubleRef:
+ case svIndex: // could be range
+ //case svRefList: // um..what?
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ case svExternalName: // could be range
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool isIntersectable( FormulaToken** pCode1, FormulaToken** pCode2 )
+{
+ FormulaToken* pToken1 = *pCode1;
+ FormulaToken* pToken2 = *pCode2;
+ if (pToken1 && pToken2)
+ return isPotentialRangeType( pToken1, true) && isPotentialRangeType( pToken2, true);
+ return false;
+}
+
+}
+
void FormulaCompiler::IntersectionLine()
{
RangeLine();
- while (mpToken->GetOpCode() == ocIntersect)
+ while (mpToken->GetOpCode() == ocIntersect || mpToken->GetOpCode() == ocSpaces)
{
+ sal_uInt16 nCodeIndex = pArr->nIndex - 1;
+ FormulaToken** pCode1 = pCode - 1;
FormulaTokenRef p = mpToken;
NextToken();
RangeLine();
- PutCode(p);
+ FormulaToken** pCode2 = pCode - 1;
+ if (p->GetOpCode() == ocSpaces)
+ {
+ // Convert to intersection if both left and right are references or
+ // functions (potentially returning references, if not then a space
+ // or no space would be a syntax error anyway), not other operators
+ // or operands. Else discard.
+ if (isIntersectable( pCode1, pCode2))
+ {
+ FormulaTokenRef pIntersect( new FormulaByteToken( ocIntersect));
+ // Replace ocSpaces with ocIntersect so that when switching
+ // formula syntax the correct operator string is created.
+ pArr->ReplaceToken( nCodeIndex, pIntersect.get(), FormulaTokenArray::ReplaceMode::CODE_ONLY);
+ PutCode( pIntersect);
+ }
+ }
+ else
+ {
+ PutCode(p);
+ }
}
}
@@ -1920,6 +2015,14 @@ const FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuf
}
else if( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
rBuffer.appendAscii( pInternal[ eOp - ocInternalBegin ] );
+ else if (eOp == ocIntersect)
+ {
+ // Nasty, ugly, horrific, terrifying..
+ if (FormulaGrammar::isExcelSyntax( meGrammar))
+ rBuffer.append(' ');
+ else
+ rBuffer.append( mxSymbols->getSymbol( eOp));
+ }
else if( (sal_uInt16) eOp < mxSymbols->getSymbolCount()) // Keyword:
rBuffer.append( mxSymbols->getSymbol( eOp));
else
@@ -2208,7 +2311,24 @@ OpCode FormulaCompiler::NextToken()
}
}
}
- eLastOp = eOp;
+ // Nasty, ugly, horrific, terrifying.. significant whitespace..
+ if (eOp == ocSpaces && FormulaGrammar::isExcelSyntax( meGrammar))
+ {
+ // Fake an intersection op as last op for the next round, but at
+ // least roughly check if it could make sense at all.
+ if (eLastOp == ocPush || eLastOp == ocClose)
+ {
+ FormulaToken* pNext = pArr->PeekNextNoSpaces();
+ if (pNext && isPotentialRangeType( pNext, false))
+ eLastOp = ocIntersect;
+ else
+ eLastOp = eOp;
+ }
+ else
+ eLastOp = eOp;
+ }
+ else
+ eLastOp = eOp;
}
return eOp;
}
diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index 0fb5a63..bf49624 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -486,7 +486,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML
String SC_OPCODE_AND { Text = "AND" ; };
String SC_OPCODE_OR { Text = "OR" ; };
String SC_OPCODE_XOR { Text = "_xlfn.XOR" ; };
- String SC_OPCODE_INTERSECT { Text = "!" ; };
+ String SC_OPCODE_INTERSECT { Text = " " ; };
String SC_OPCODE_UNION { Text = "~" ; };
String SC_OPCODE_RANGE { Text = ":" ; };
String SC_OPCODE_NOT { Text = "NOT" ; };
diff --git a/include/formula/grammar.hxx b/include/formula/grammar.hxx
index 91ca7ae11..6500d68 100644
--- a/include/formula/grammar.hxx
+++ b/include/formula/grammar.hxx
@@ -203,6 +203,21 @@ public:
css::sheet::FormulaLanguage::OOXML;
}
+ /// If grammar has an Excel syntax, determined by address convention.
+ static inline bool isExcelSyntax( const Grammar eGrammar )
+ {
+ AddressConvention eConv = extractRefConvention( eGrammar );
+ switch (eConv)
+ {
+ case FormulaGrammar::AddressConvention::CONV_XL_A1:
+ case FormulaGrammar::AddressConvention::CONV_XL_R1C1:
+ case FormulaGrammar::AddressConvention::CONV_XL_OOX:
+ return true;
+ default:
+ return false;
+ }
+ }
+
};
} // formula
commit f41257dc9913cd6020a3a37bf425c20b51e18ece
Author: Eike Rathke <erack at redhat.com>
Date: Sat Apr 23 14:33:50 2016 +0200
simplify the ReplaceToken() offset logic to absolute offsets
Change-Id: I8d02fb63bc0c5cb48aabaf7a8800f5f9ac95cbf5
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 7009d94..ac5e339 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -867,16 +867,13 @@ FormulaToken* FormulaTokenArray::MergeArray( )
FormulaToken* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset, FormulaToken* t,
FormulaTokenArray::ReplaceMode eMode )
{
- if (eMode == BACKWARD_CODE_ONLY)
- nOffset = nLen - nOffset - 1;
-
if (nOffset < nLen)
{
CheckToken(*t);
t->IncRef();
FormulaToken* p = pCode[nOffset];
pCode[nOffset] = t;
- if (eMode == FORWARD_CODE_AND_RPN && p->GetRef() > 1)
+ if (eMode == CODE_AND_RPN && p->GetRef() > 1)
{
for (sal_uInt16 i=0; i < nRPN; ++i)
{
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index e890c3a..cd0f430 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -127,23 +127,19 @@ protected:
public:
enum ReplaceMode
{
- BACKWARD_CODE_ONLY, ///< offset goes backward, replacement only in pCode
- FORWARD_CODE_AND_RPN ///< offset goes forward, replacement in pCode and RPN
+ CODE_ONLY, ///< replacement only in pCode
+ CODE_AND_RPN ///< replacement in pCode and pRPN
};
protected:
/** Also used by the compiler. The token MUST had been allocated with new!
@param nOffset
- If eMode==BACKWARD_CODE_ONLY negative offset of token, 0==last,
- 1==previous, ...
- If eMode==FORWARD_CODE_AND_RPN positive offset of token, 0==first,
- 1==second, ...
+ Absolute offset in pCode of the token to be replaced.
@param eMode
- If BACKWARD_CODE_ONLY only the token in pCode at nLen-nOffset-1
- is replaced.
- If FORWARD_CODE_AND_RPN the token in pCode at nOffset is
- replaced; if the original token was also referenced in the RPN
- array then that reference is replaced with a reference to the new
+ If CODE_ONLY only the token in pCode at nOffset is replaced.
+ If CODE_AND_RPN the token in pCode at nOffset is replaced;
+ if the original token was also referenced in the pRPN array
+ then that reference is replaced with a reference to the new
token as well.
*/
FormulaToken* ReplaceToken( sal_uInt16 nOffset, FormulaToken*, ReplaceMode eMode );
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index e16446a..f647286 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -4325,8 +4325,8 @@ ScTokenArray* ScCompiler::CompileString( const OUString& rFormula )
FormulaToken* pTableRefToken = new ScTableRefToken( pPrev->GetIndex(), ScTableRefToken::TABLE);
maTableRefs.push_back( TableRefEntry( pTableRefToken));
// pPrev may be dead hereafter.
- static_cast<ScTokenArray*>(pArr)->ReplaceToken( 1, pTableRefToken,
- FormulaTokenArray::ReplaceMode::BACKWARD_CODE_ONLY);
+ static_cast<ScTokenArray*>(pArr)->ReplaceToken( nIdx, pTableRefToken,
+ FormulaTokenArray::ReplaceMode::CODE_ONLY);
}
}
switch (eOp)
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 154868e..00203e0 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2397,7 +2397,7 @@ void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, cons
OUString aTabName;
sal_uInt16 nFileId;
GetExternalTableData(pOldDoc, pNewDoc, rRef1.Tab(), aTabName, nFileId);
- ReplaceToken( j, new ScExternalDoubleRefToken(nFileId, aTabName, rRef), FORWARD_CODE_AND_RPN);
+ ReplaceToken( j, new ScExternalDoubleRefToken(nFileId, aTabName, rRef), CODE_AND_RPN);
// ATTENTION: rRef can't be used after this point
}
}
@@ -2414,7 +2414,7 @@ void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, cons
OUString aTabName;
sal_uInt16 nFileId;
GetExternalTableData(pOldDoc, pNewDoc, rRef.Tab(), aTabName, nFileId);
- ReplaceToken( j, new ScExternalSingleRefToken(nFileId, aTabName, rRef), FORWARD_CODE_AND_RPN);
+ ReplaceToken( j, new ScExternalSingleRefToken(nFileId, aTabName, rRef), CODE_AND_RPN);
// ATTENTION: rRef can't be used after this point
}
}
commit 9185f889ed9da48aad07d6a552224561f38e9b99
Author: Eike Rathke <erack at redhat.com>
Date: Fri Apr 22 21:12:23 2016 +0200
newline shortage
Change-Id: Id2487480270bb2be765495bb6d5982c85ae2117f
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 492abb0..fdf21e0 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -2212,6 +2212,7 @@ OpCode FormulaCompiler::NextToken()
}
return eOp;
}
+
void FormulaCompiler::PutCode( FormulaTokenRef& p )
{
if( pc >= FORMULA_MAXTOKENS - 1 )
commit 7756822206e84669f55cec1e75ede8c09d5693a7
Author: Eike Rathke <erack at redhat.com>
Date: Fri Apr 22 19:18:13 2016 +0200
alignment
Change-Id: If7dbdcd93a43d4e14f853b7d3436fa31c0091403
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index 7960591..e890c3a 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -109,10 +109,10 @@ class FORMULA_DLLPUBLIC FormulaTokenArray
protected:
FormulaToken** pCode; // Token code array
FormulaToken** pRPN; // RPN array
- sal_uInt16 nLen; // Length of token array
- sal_uInt16 nRPN; // Length of RPN array
- sal_uInt16 nIndex; // Current step index
- sal_uInt16 nError; // Error code
+ sal_uInt16 nLen; // Length of token array
+ sal_uInt16 nRPN; // Length of RPN array
+ sal_uInt16 nIndex; // Current step index
+ sal_uInt16 nError; // Error code
ScRecalcMode nMode; // Flags to indicate when to recalc this code
bool bHyperLink; // If HYPERLINK() occurs in the formula.
bool mbFromRangeName; // If this array originates from a named expression
commit 737040e5db1b74f49d3a075ac4c64e218b1134de
Author: Eike Rathke <erack at redhat.com>
Date: Fri Apr 22 18:42:05 2016 +0200
change multiple ifs to switch case
... obtaining mpToken->GetOpCode() only once.
Change-Id: I909fef97540998a7f09115738fb76a1e963480bf
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 31004d4..492abb0 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1101,27 +1101,29 @@ bool FormulaCompiler::GetToken()
mpToken = new FormulaByteToken( ocStop );
return false;
}
- if ( mpToken->GetOpCode() == ocSubTotal || mpToken->GetOpCode() == ocAggregate )
- glSubTotal = true;
- else if ( mpToken->IsExternalRef() )
+ if ( mpToken->IsExternalRef() )
{
return HandleExternalReference(*mpToken);
}
- else if( mpToken->GetOpCode() == ocName )
- {
- return HandleRange();
- }
- else if( mpToken->GetOpCode() == ocColRowName )
- {
- return HandleColRowName();
- }
- else if( mpToken->GetOpCode() == ocDBArea )
- {
- return HandleDbData();
- }
- else if( mpToken->GetOpCode() == ocTableRef )
+ else
{
- return HandleTableRef();
+ switch (mpToken->GetOpCode())
+ {
+ case ocSubTotal:
+ case ocAggregate:
+ glSubTotal = true;
+ break;
+ case ocName:
+ return HandleRange();
+ case ocColRowName:
+ return HandleColRowName();
+ case ocDBArea:
+ return HandleDbData();
+ case ocTableRef:
+ return HandleTableRef();
+ default:
+ ; // nothing
+ }
}
return true;
}
commit 4c5932cf06f0434a0df32203d567cab976402011
Author: Eike Rathke <erack at redhat.com>
Date: Fri Apr 22 18:30:29 2016 +0200
join two lines that cause an annoying debugger step over experience
Change-Id: I50bf6710f7319f5c2ea18d8a3aa02f5c613de063
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index baacb94..31004d4 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1062,8 +1062,7 @@ bool FormulaCompiler::GetToken()
else
{
short nWasColRowName;
- if ( pArr->nIndex
- && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
+ if ( pArr->nIndex > 0 && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
nWasColRowName = 1;
else
nWasColRowName = 0;
@@ -1102,8 +1101,7 @@ bool FormulaCompiler::GetToken()
mpToken = new FormulaByteToken( ocStop );
return false;
}
- if ( mpToken->GetOpCode() == ocSubTotal ||
- mpToken->GetOpCode() == ocAggregate )
+ if ( mpToken->GetOpCode() == ocSubTotal || mpToken->GetOpCode() == ocAggregate )
glSubTotal = true;
else if ( mpToken->IsExternalRef() )
{
More information about the Libreoffice-commits
mailing list