diff options
author | dante <dante19031999@gmail.com> | 2020-11-03 18:51:19 +0100 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2020-11-10 07:59:14 +0100 |
commit | 7e2c35324c54646f53f0fa14b7bce07e1da73c0b (patch) | |
tree | 55232517950926bdb04bec619288b81347abf160 /starmath/source/parse.cxx | |
parent | 0f2bddacae89a50c1349e2511c3b60c7c7120aad (diff) |
Evaluate command: tdf#109338
Adds evaluate command.
It's visible from UI as a bracket.
Example: evaluate { {1} over {%sigma sqrt{2%pi} }func e^-{{(x-%mu)^2} over {2%sigma^2}} } from { -infinity } to { +infinity } = 0
In order to make the mathml part, several changes had to be mad:
- Allow mathml to correctly identify the math token for opperators
- Allow mathml to correctly identify the math token for fences
- Since improvements where made on token recognision, visitors to string can now be lighter ( removing long long switch )
- Improving the import / export to mathm
- LO says it mathml 2, but actually is something between 2 and 3
- Allowing mfenced ( mathml 2.0 ) to stayl 3 adding the missing data ( prefix and postfix )
- Be able to know if we are opening or closing brackets
- lrline and lrdline commands hidden on UI.
- They are they own open close
- If prefix and postfix are missing meaning of the expression may change, however that's the user problem.
- The problem resides in the fact that MS_VERTLINE is uses for lline and rline.
- The problem resides in the fact that MS_DVERTLINE is uses for ldline and rdline.
- Changing frac priority from 0 to 5, if not { frac 1 2 frac 1 2 } fails ( found while testing )
- The mathml testing was made with highter standars than qa tests, however there are no guarantees.
- Added xml tokens needed for math
- Added starmathdatabase. Will grow in the future.
The point is avoiding long lists and swtches inside code.
Added it command for hidden or implicit product ( like ⁢ in mathml ). Oppens path for tdf#66200. Note that about this issue there is only one line on the parser. The mathml implementation will be made later when LO will allow chars with &charname;.
Change-Id: If24b40c2420d39498693944f13a02985f997dd23
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105267
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
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); |