diff options
Diffstat (limited to 'starmath/source/parse.cxx')
-rw-r--r-- | starmath/source/parse.cxx | 122 |
1 files changed, 95 insertions, 27 deletions
diff --git a/starmath/source/parse.cxx b/starmath/source/parse.cxx index 598ec121611b..803f97425a6d 100644 --- a/starmath/source/parse.cxx +++ b/starmath/source/parse.cxx @@ -38,32 +38,6 @@ using namespace ::com::sun::star::i18n; - -SmToken::SmToken() - : eType(TUNKNOWN) - , cMathChar('\0') - , nGroup(TG::NONE) - , nLevel(0) - , nRow(0) - , nCol(0) -{ -} - -SmToken::SmToken(SmTokenType eTokenType, - sal_Unicode cMath, - const char* pText, - TG nTokenGroup, - sal_uInt16 nTokenLevel) - : aText(OUString::createFromAscii(pText)) - , eType(eTokenType) - , cMathChar(cMath) - , nGroup(nTokenGroup) - , nLevel(nTokenLevel) - , nRow(0) - , nCol(0) -{ -} - //Definition of math keywords const SmTokenTableEntry aTokenTable[] = { @@ -123,6 +97,7 @@ const SmTokenTableEntry aTokenTable[] = { "drarrow" , TDRARROW, MS_DRARROW, TG::Standalone, 5}, { "emptyset" , TEMPTYSET, MS_EMPTYSET, TG::Standalone, 5}, { "equiv", TEQUIV, MS_EQUIV, TG::Relation, 0}, + { "evaluate", TEVALUATE, '\0', TG::NONE, 0}, { "exists", TEXISTS, MS_EXISTS, TG::Standalone, 5}, { "exp", TEXP, '\0', TG::Function, 5}, { "fact", TFACT, MS_FACT, TG::UnOper, 5}, @@ -130,7 +105,7 @@ const SmTokenTableEntry aTokenTable[] = { "font", TFONT, '\0', TG::FontAttr, 5}, { "forall", TFORALL, MS_FORALL, TG::Standalone, 5}, { "fourier", TFOURIER, MS_FOURIER, TG::Standalone, 5}, - { "frac", TFRAC, '\0', TG::NONE, 0}, + { "frac", TFRAC, '\0', TG::NONE, 5}, { "from", TFROM, '\0', TG::Limit, 0}, { "func", TFUNC, '\0', TG::Function, 5}, { "ge", TGE, MS_GE, TG::Relation, 0}, @@ -150,6 +125,7 @@ const SmTokenTableEntry aTokenTable[] = { "int", TINT, MS_INT, TG::Oper, 5}, { "intd", TINTD, MS_INT, TG::Oper, 5}, { "intersection", TINTERSECT, MS_INTERSECT, TG::Product, 0}, + { "it", TIT, '\0', TG::Product, 0}, { "ital", TITALIC, '\0', TG::FontAttr, 5}, { "italic", TITALIC, '\0', TG::FontAttr, 5}, { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TG::Standalone, 5}, @@ -174,6 +150,8 @@ const SmTokenTableEntry aTokenTable[] = { "lllint", TLLLINT, MS_LLLINT, TG::Oper, 5}, { "ln", TLN, '\0', TG::Function, 5}, { "log", TLOG, '\0', TG::Function, 5}, + { "lrline", TLRLINE, MS_VERTLINE, TG::LBrace | TG::RBrace, 5}, + { "lrdline", TLRDLINE, MS_VERTLINE, TG::LBrace | TG::RBrace, 5}, { "lsub", TLSUB, '\0', TG::Power, 0}, { "lsup", TLSUP, '\0', TG::Power, 0}, { "lt", TLT, MS_LT, TG::Relation, 0}, @@ -1513,6 +1491,55 @@ std::unique_ptr<SmNode> SmParser::DoSubSup(TG nActiveGroup, SmNode *pGivenNode) return pNode; } +std::unique_ptr<SmNode> SmParser::DoSubSupEvaluate(SmNode *pGivenNode) +{ + std::unique_ptr<SmNode> xGivenNode(pGivenNode); + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit"); + + std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(m_aCurToken)); + pNode->SetUseLimits(true); + + // initialize subnodes array + std::vector<std::unique_ptr<SmNode>> aSubNodes(1 + SUBSUP_NUM_ENTRIES); + aSubNodes[0] = std::move(xGivenNode); + + // process all sub-/supscripts + int nIndex = 0; + while (TokenInGroup(TG::Limit)) + { + SmTokenType eType (m_aCurToken.eType); + + switch (eType) + { + case TFROM : nIndex = static_cast<int>(RSUB); break; + case TTO : nIndex = static_cast<int>(RSUP); break; + default : + SAL_WARN( "starmath", "unknown case"); + } + nIndex++; + assert(1 <= nIndex && nIndex <= SUBSUP_NUM_ENTRIES); + + std::unique_ptr<SmNode> xENode; + if (aSubNodes[nIndex]) // if already occupied at earlier iteration + { + // forget the earlier one, remember an error instead + aSubNodes[nIndex].reset(); + xENode = DoError(SmParseError::DoubleSubsupscript); // this also skips current token. + } + else NextToken(); // skip sub-/supscript token + + // get sub-/supscript node + std::unique_ptr<SmNode> xSNode; + xSNode = DoTerm(true); + + aSubNodes[nIndex] = std::move(xENode ? xENode : xSNode); + } + + pNode->SetSubNodes(buildNodeArray(aSubNodes)); + return pNode; +} + std::unique_ptr<SmNode> SmParser::DoOpSubSup() { DepthProtect aDepthGuard(m_nParseDepth); @@ -1613,6 +1640,8 @@ std::unique_ptr<SmNode> SmParser::DoTerm(bool bGroupNumberIdent) case TLEFT : return DoBrace(); + case TEVALUATE: + return DoEvaluate(); case TBLANK : case TSBLANK : @@ -2302,6 +2331,8 @@ std::unique_ptr<SmStructureNode> SmParser::DoBrace() case TLANGLE : eExpectedType = TRANGLE; break; case TLFLOOR : eExpectedType = TRFLOOR; break; case TLCEIL : eExpectedType = TRCEIL; break; + case TLRLINE : eExpectedType = TLRLINE; break; + case TLRDLINE : eExpectedType = TLRDLINE; break; default : SAL_WARN("starmath", "unknown case"); } @@ -2376,6 +2407,43 @@ std::unique_ptr<SmBracebodyNode> SmParser::DoBracebody(bool bIsLeftRight) return pBody; } +std::unique_ptr<SmNode> SmParser::DoEvaluate() +{ + + // Checkout depth and create node + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit"); + std::unique_ptr<SmStructureNode> xSNode(new SmBraceNode(m_aCurToken)); + SmToken aToken( TRLINE, MS_VERTLINE, "evaluate", TG::RBrace, 5); + aToken.nRow = m_aCurToken.nRow; + aToken.nCol = m_aCurToken.nCol; + + // Parse body && left none + NextToken(); + std::unique_ptr<SmNode> pBody = DoPower(); + SmToken bToken( TNONE, '\0', "", TG::LBrace, 5); + std::unique_ptr<SmNode> pLeft; + pLeft.reset(new SmMathSymbolNode(bToken)); + + // Mount nodes + std::unique_ptr<SmNode> pRight; + pRight.reset(new SmMathSymbolNode(aToken)); + xSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight)); + xSNode->SetScaleMode(SmScaleMode::Height); // scalable line + + // Parse from to + if ( m_aCurToken.nGroup == TG::Limit ) + { + std::unique_ptr<SmNode> rSNode; + rSNode = DoSubSupEvaluate(xSNode.release()); + rSNode->GetToken().eType = TEVALUATE; + return rSNode; + } + + return xSNode; + +} + std::unique_ptr<SmTextNode> SmParser::DoFunction() { DepthProtect aDepthGuard(m_nParseDepth); |