sc/inc/compiler.hxx | 4 + sc/source/core/tool/compiler.cxx | 150 ++++++++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 48 deletions(-)
New commits: commit d6398719abecfca60db37637490e602222992dc2 Author: Eike Rathke <er...@redhat.com> Date: Thu Apr 9 18:03:09 2015 +0200 TableRef: correct GetToken() logic Ensure that only desired tokens are obtained and the resulting new token is actually the current one upon return. Change-Id: I624c324b861d8658accf3285cad2cfc5a598b450 diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index 3154d57..03baa29 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -386,6 +386,9 @@ public: bool IsTableRefItem( const OUString& ) const; bool IsTableRefColumn( const OUString& ) const; + /** Calls GetToken() if PeekNextNoSpaces() is of given OpCode. */ + bool GetTokenIfOpCode( OpCode eOp ); + /** * When auto correction is set, the jump command reorder must be enabled. */ diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 4cf6f24..a988209 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -4820,6 +4820,14 @@ bool ScCompiler::HandleDbData() return true; } +bool ScCompiler::GetTokenIfOpCode( OpCode eOp ) +{ + const formula::FormulaToken* p = pArr->PeekNextNoSpaces(); + if (p && p->GetOpCode() == eOp) + return GetToken(); + return false; +} + /* Documentation on MS-Excel Table structured references: * https://support.office.com/en-us/article/Use-structured-references-in-Excel-table-formulas-75fb07d3-826a-449c-b76f-363057e3d16f @@ -4847,7 +4855,6 @@ bool ScCompiler::HandleTableRef() aDBRange.aEnd.SetTab(aDBRange.aStart.Tab()); ScRange aRange( aDBRange); ScTokenArray* pNew = new ScTokenArray(); - bool bGotToken = false; bool bAddRange = true; bool bForwardToClose = false; ScTableRefToken::Item eItem = pTR->GetItem(); @@ -4927,22 +4934,27 @@ bool ScCompiler::HandleTableRef() break; } bool bColumnRange = false; - if (bForwardToClose && (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen) + int nLevel = 0; + if (bForwardToClose && GetTokenIfOpCode( ocTableRefOpen)) { - int nLevel = 1; + ++nLevel; enum { sOpen, sItem, sClose, sSep, + sLast, sStop } eState = sOpen; do { - if ((bGotToken = GetToken())) + const formula::FormulaToken* p = pArr->PeekNextNoSpaces(); + if (!p) + eState = sStop; + else { - switch (mpToken->GetOpCode()) + switch (p->GetOpCode()) { case ocTableRefOpen: eState = ((eState == sOpen || eState == sSep) ? sOpen : sStop); @@ -4961,35 +4973,37 @@ bool ScCompiler::HandleTableRef() break; case ocTableRefClose: eState = ((eState == sItem || eState == sClose) ? sClose : sStop); - if (--nLevel <= 0) - { - if (nLevel < 0) - SetError( errPair); - eState = sStop; - } + if (eState != sStop && --nLevel == 0) + eState = sLast; break; case ocSep: eState = ((eState == sClose) ? sSep : sStop); break; case ocPush: - if (eState == sOpen && - (mpToken->GetType() == svSingleRef || mpToken->GetType() == svDoubleRef)) + if (eState == sOpen && (p->GetType() == svSingleRef || p->GetType() == svDoubleRef)) + { bColumnRange = true; - eState = sStop; + eState = sLast; + } + else + { + eState = sStop; + } break; default: eState = sStop; } + if (eState != sStop) + GetToken(); + if (eState == sLast) + eState = sStop; } - } while (bGotToken && eState != sStop); - if (bGotToken && mpToken->GetOpCode() == ocTableRefClose) - bGotToken = false; // get next token below in return + } while (eState != sStop); } if (bAddRange) { if (bColumnRange) { - bGotToken = false; // obtain at least a close hereafter // Limit range to specified columns. ScRange aColRange( ScAddress::INITIALIZE_INVALID ); switch (mpToken->GetType()) @@ -4997,16 +5011,15 @@ bool ScCompiler::HandleTableRef() case svSingleRef: { aColRange.aStart = aColRange.aEnd = mpToken->GetSingleRef()->toAbs( aPos); - if ( (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose && - (bGotToken = GetToken()) && mpToken->GetOpCode() == ocRange && - (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen && - (bGotToken = GetToken()) && mpToken->GetOpCode() == ocPush) + if ( GetTokenIfOpCode( ocTableRefClose) && (nLevel--) && + GetTokenIfOpCode( ocRange) && + GetTokenIfOpCode( ocTableRefOpen) && (++nLevel) && + GetTokenIfOpCode( ocPush)) { if (mpToken->GetType() != svSingleRef) aColRange = ScRange( ScAddress::INITIALIZE_INVALID); else { - bGotToken = false; // obtain at least a close hereafter aColRange.aEnd = mpToken->GetSingleRef()->toAbs( aPos); aColRange.Justify(); } @@ -5040,27 +5053,19 @@ bool ScCompiler::HandleTableRef() { SetError( errNoRef); } - if (bColumnRange && !bGotToken) - { - if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose) - { - if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose) - bGotToken = false; // get next token below in return - } - else - { - SetError( errPair); - bGotToken = false; // get next token below in return - } - } } else { SetError( errNoRef); } + while (nLevel-- > 0) + { + if (!GetTokenIfOpCode( ocTableRefClose)) + SetError( errPair); + } PushTokenArray( pNew, true ); pNew->Reset(); - return bGotToken ? true : GetToken(); + return GetToken(); } return true; } commit 3335b46d123053b1228b94207a32bab08cf9d4e3 Author: Eike Rathke <er...@redhat.com> Date: Thu Apr 9 14:39:52 2015 +0200 TableRef: allow column specifier without item Change-Id: I1263f190d769254949701b3a257b2af5d6ea61a2 diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index c2ebe55..4cf6f24 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -4863,16 +4863,7 @@ bool ScCompiler::HandleTableRef() aRange.aEnd.IncRow(-1); if (aRange.aEnd.Row() < aRange.aStart.Row()) bAddRange = false; - - // Optional [] may follow. - if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen) - { - if ((bGotToken = GetToken())) - { - if (mpToken->GetOpCode() == ocTableRefClose) - bGotToken = false; // get next token below - } - } + bForwardToClose = true; } break; case ScTableRefToken::ALL: commit d5e1b41330fdd7341415e6c34f61ec826d20e51b Author: Eike Rathke <er...@redhat.com> Date: Thu Apr 9 14:11:46 2015 +0200 TableRef: lookup column specifier Change-Id: I73109e5a862b2f4bc456dff512bddf5d23586a6d diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index b4b1945..3154d57 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -384,6 +384,7 @@ public: bool IsErrorConstant( const OUString& ) const; bool IsTableRefItem( const OUString& ) const; + bool IsTableRefColumn( const OUString& ) const; /** * When auto correction is set, the jump command reorder must be enabled. diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index d580bb9..c2ebe55 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -3349,6 +3349,56 @@ bool ScCompiler::IsTableRefItem( const OUString& rName ) const return bItem; } +bool ScCompiler::IsTableRefColumn( const OUString& rName ) const +{ + // Only called when there actually is a current TableRef, hence + // accessing maTableRefs.back() is safe. + ScTableRefToken* p = dynamic_cast<ScTableRefToken*>(maTableRefs.back().mxToken.get()); + assert(p); // not a ScTableRefToken can't be + + ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex( p->GetIndex()); + if (!pDBData) + return false; + + // '#', '[', ']' and '\'' are escaped with '\'' + OUString aName( rName.replaceAll( OUString("'"), OUString())); + + ScRange aRange; + pDBData->GetArea( aRange); + aRange.aEnd.SetTab( aRange.aStart.Tab()); + aRange.aEnd.SetRow( aRange.aStart.Row()); + + // Quite similar to IsColRowName() but limited to one row of headers. + ScCellIterator aIter( pDoc, aRange); + for (bool bHas = aIter.first(); bHas; bHas = aIter.next()) + { + CellType eType = aIter.getType(); + bool bOk = false; + if (eType == CELLTYPE_FORMULA) + { + ScFormulaCell* pFC = aIter.getFormulaCell(); + bOk = (pFC->GetCode()->GetCodeLen() > 0) && (pFC->aPos != aPos); + } + else + bOk = true; + + if (bOk && aIter.hasString()) + { + OUString aStr = aIter.getString(); + if (ScGlobal::GetpTransliteration()->isEqual( aStr, aName)) + { + ScSingleRefData aRef; + aRef.InitFlags(); + aRef.SetColRel( true ); + aRef.SetAddress( aIter.GetPos(), aPos); + maRawToken.SetSingleReference( aRef ); + return true; + } + } + } + return false; +} + void ScCompiler::SetAutoCorrection( bool bVal ) { assert(mbJumpCommandReorder); @@ -3653,8 +3703,16 @@ bool ScCompiler::NextNewToken( bool bInArray ) do { - mbRewind = false; const OUString aOrg( cSymbol ); + + // Check for TableRef column specifier first, it may be anything. + if (cSymbol[0] != '#' && !maTableRefs.empty() && maTableRefs.back().mnLevel) + { + if (IsTableRefColumn( aOrg )) + return true; + } + + mbRewind = false; aUpper.clear(); bool bAsciiUpper = false; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits