// First character may be any alphabetic const sal_Int32 coStartFlags = KParseTokens::ANY_LETTER | KParseTokens::IGNORE_LEADING_WS;
// Continuing characters may be any alphabetic const sal_Int32 coContFlags = (coStartFlags & ~KParseTokens::IGNORE_LEADING_WS)
| KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; // First character for numbers, may be any numeric or dot const sal_Int32 coNumStartFlags
= KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT | KParseTokens::IGNORE_LEADING_WS; // Continuing characters for numbers, may be any numeric or dot or comma. // tdf#127873: additionally accept ',' comma group separator as too many // existing documents unwittingly may have used that as decimal separator // in such locales (though it never was as this is always the en-US locale // and the group separator is only parsed away). const sal_Int32 coNumContFlags = (coNumStartFlags & ~KParseTokens::IGNORE_LEADING_WS)
| KParseTokens::GROUP_SEPARATOR_IN_NUMBER; // First character for numbers hexadecimal const sal_Int32 coNum16StartFlags
= KParseTokens::ASC_DIGIT | KParseTokens::ASC_UPALPHA | KParseTokens::IGNORE_LEADING_WS;
// Continuing characters for numbers hexadecimal const sal_Int32 coNum16ContFlags = (coNum16StartFlags & ~KParseTokens::IGNORE_LEADING_WS); // user-defined char continuing characters may be any alphanumeric or dot. const sal_Int32 coUserDefinedCharContFlags = KParseTokens::ANY_LETTER_OR_NUMBER
| KParseTokens::ASC_DOT
| KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
//Checks if keyword is in the list. staticinlinebool findCompare(const SmTokenTableEntry& lhs, const OUString& s)
{ return s.compareToIgnoreAsciiCase(lhs.aIdent) > 0;
}
//Returns the SmTokenTableEntry for a keyword const SmTokenTableEntry* GetTokenTableEntry(const OUString& rName)
{ if (rName.isEmpty()) return nullptr; //avoid null pointer exceptions //Looks for the first keyword after or equal to rName in alphabetical order. auto findIter
= std::lower_bound(std::begin(aTokenTable), std::end(aTokenTable), rName, findCompare); if (findIter != std::end(aTokenTable) && rName.equalsIgnoreAsciiCase(findIter->aIdent)) return &*findIter; //check is equal return nullptr; //not found
}
OUString encloseOrEscapeLiteral(const OUString& string, bool force)
{ if (force) return"\"" + string + "\"";
OUStringBuffer result; const std::unordered_set<sal_Unicode> DelimiterTable1{ //keeping " as first entry is important to not get into recursive replacement ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '^', '_', '#', '%', '>', '<', '&', '|', '~', '`'
}; const std::unordered_set<sal_Unicode> DelimiterTable2{ //keeping " as first entry is important to not get into recursive replacement '{', '}', '(', ')', '[', ']',
}; for (sal_Int32 i = 0; i < string.getLength(); i++)
{ if (string[i] == '"')
result.append("\"\\\"\""); elseif (DelimiterTable1.find(string[i]) != DelimiterTable1.end())
result.append("\"" + OUStringChar(string[i]) + "\""); elseif (DelimiterTable2.find(string[i]) != DelimiterTable2.end())
result.append("\\" + OUStringChar(string[i])); else
result.append(string[i]);
}
OUString resultString = result.makeStringAndClear(); const SmTokenTableEntry* tkn = GetTokenTableEntry(resultString); // excluding function and operator as they take arguments and can't treat them as literal or else arguments are not displayed correctly if (tkn && tkn->nGroup != TG::Function && tkn->nGroup != TG::Oper)
{
resultString = "\"" + resultString + "\"";
} return resultString;
}
staticbool IsDelimiter(const OUString& rTxt, sal_Int32 nPos)
{ // returns 'true' iff cChar is '\0' or a delimiter
assert(nPos <= rTxt.getLength()); //index out of range if (nPos == rTxt.getLength()) returntrue; //This is EOF
sal_Unicode cChar = rTxt[nPos];
// check if 'cChar' is in the delimiter table static constexpr sal_Unicode aDelimiterTable[] = { ' ', '{', '}', '(', ')', '\t', '\n', '\r', '+', '-', '*', '/', '=', '[', ']', '^', '_', '#', '%', '>', '<', '&', '|', '\\', '"', '~', '`'
}; //reordered by usage (by eye) for nanoseconds saving.
//checks the array for (autoconst& cDelimiter : aDelimiterTable)
{ if (cDelimiter == cChar) returntrue;
}
// checks number used as arguments in Math formulas (e.g. 'size' command) // Format: no negative numbers, must start with a digit, no exponent notation, ... staticbool lcl_IsNumber(const OUString& rText)
{ bool bPoint = false; const sal_Unicode* pBuffer = rText.getStr(); for (sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++)
{ const sal_Unicode cChar = *pBuffer; if (cChar == '.')
{ if (bPoint) returnfalse; else
bPoint = true;
} elseif (!rtl::isAsciiDigit(cChar)) returnfalse;
} returntrue;
} // checks number used as arguments in Math formulas (e.g. 'size' command) // Format: no negative numbers, must start with a digit, no exponent notation, ... staticbool lcl_IsNotWholeNumber(const OUString& rText)
{ const sal_Unicode* pBuffer = rText.getStr(); for (sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) if (!rtl::isAsciiDigit(*pBuffer)) returntrue; returnfalse;
} // checks hex number used as arguments in Math formulas (e.g. 'hex' command) // Format: no negative numbers, must start with a digit, no exponent notation, ... staticbool lcl_IsNotWholeNumber16(const OUString& rText)
{ const sal_Unicode* pBuffer = rText.getStr(); for (sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) if (!rtl::isAsciiCanonicHexDigit(*pBuffer)) returntrue; returnfalse;
}
void SmParser5::NextToken() //Central part of the parser
{
sal_Int32 nBufLen = m_aBufferString.getLength();
ParseResult aRes;
sal_Int32 nRealStart; bool bCont; do
{ // skip white spaces while (UnicodeType::SPACE_SEPARATOR == m_pSysCC->getType(m_aBufferString, m_nBufferIndex))
++m_nBufferIndex;
// Try to parse a number in a locale-independent manner using // '.' as decimal separator. // See https://bz.apache.org/ooo/show_bug.cgi?id=45779
aRes
= m_aNumCC.parsePredefinedToken(KParseType::ASC_NUMBER, m_aBufferString, m_nBufferIndex,
coNumStartFlags, u""_ustr, coNumContFlags, u""_ustr);
if (aRes.TokenType == 0)
{ // Try again with the default token parsing.
aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex, coStartFlags, u""_ustr,
coContFlags, u""_ustr);
}
// default setting for the case that no identifier // i.e. a valid symbol-name is following the '%' // character
m_aCurToken.eType = TTEXT;
m_aCurToken.cMathChar = u""_ustr;
m_aCurToken.nGroup = TG::NONE;
m_aCurToken.nLevel = 5;
m_aCurToken.aText = "%";
if (aTmpRes.TokenType & KParseType::IDENTNAME)
{
sal_Int32 n = aTmpRes.EndPos - nTmpStart;
m_aCurToken.eType = TSPECIAL;
m_aCurToken.aText = m_aBufferString.copy(nTmpStart - 1, n + 1);
rnEndPos = nRealStart + 2;
} else
{
m_aCurToken.eType = TMINUS;
m_aCurToken.setChar(MS_MINUS);
m_aCurToken.nGroup = TG::UnOper | TG::Sum;
m_aCurToken.nLevel = 5;
m_aCurToken.aText = "-";
}
} break; case'.':
{ // Only one character? Then it can't be a number. if (m_nBufferIndex < m_aBufferString.getLength() - 1)
{ // for compatibility with SO5.2 // texts like .34 ...56 ... h ...78..90 // will be treated as numbers
m_aCurToken.eType = TNUMBER;
m_aCurToken.cMathChar = u""_ustr;
m_aCurToken.nGroup = TG::NONE;
m_aCurToken.nLevel = 5;
sal_Int32 nTxtStart = m_nBufferIndex;
sal_Unicode cChar; // if the equation ends with dot(.) then increment m_nBufferIndex till end of string only do
{
cChar = m_aBufferString[++m_nBufferIndex];
} while ((cChar == '.' || rtl::isAsciiDigit(cChar))
&& (m_nBufferIndex < m_aBufferString.getLength() - 1));
// tdf#129372: we may have to deal with surrogate pairs // (see https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates) // in this case, we must read 2 sal_Unicode instead of 1 int nOffset(rtl::isSurrogate(m_aBufferString[nRealStart]) ? 2 : 1);
m_aCurToken.aText = m_aBufferString.copy(nRealStart, nOffset);
std::unique_ptr<SmNode> SmParser5::DoAlign(bool bUseExtraSpaces) // parse alignment info (if any), then go on with rest of expression
{
DepthProtect aDepthGuard(m_nParseDepth);
std::unique_ptr<SmStructureNode> xSNode;
if (TokenInGroup(TG::Align))
{
xSNode.reset(new SmAlignNode(m_aCurToken));
xSNode->SetSelection(m_aCurESelection);
NextToken();
// allow for just one align statement in 5.0 if (TokenInGroup(TG::Align)) return DoError(SmParseError::DoubleAlign);
}
// start with single expression that may have an alignment statement // (and go on with expressions that must not have alignment // statements in 'while' loop below. See also 'Expression()'.) if (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE)
ExpressionArray.push_back(DoAlign());
while (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE)
ExpressionArray.push_back(DoExpression());
//If there's no expression, add an empty one. //this is to avoid a formula tree without any caret //positions, in visual formula editor. if (ExpressionArray.empty())
{
SmToken aTok;
aTok.eType = TNEWLINE;
ExpressionArray.emplace_back(std::unique_ptr<SmNode>(new SmExpressionNode(aTok)));
}
auto xSNode = std::make_unique<SmLineNode>(m_aCurToken);
xSNode->SetSelection(m_aCurESelection);
xSNode->SetSubNodes(buildNodeArray(ExpressionArray)); return xSNode;
}
std::vector<std::unique_ptr<SmNode>> RelationArray;
RelationArray.push_back(DoRelation()); while (m_aCurToken.nLevel >= 4)
RelationArray.push_back(DoRelation());
if (RelationArray.size() > 1)
{
std::unique_ptr<SmExpressionNode> xSNode(new SmExpressionNode(m_aCurToken));
xSNode->SetSubNodes(buildNodeArray(RelationArray));
xSNode->SetUseExtraSpaces(bUseExtraSpaces); return xSNode;
} else
{ // This expression has only one node so just push this node. return std::move(RelationArray[0]);
}
}
while (TokenInGroup(TG::Product))
{ //this linear loop builds a recursive structure, if it gets //too deep then later processing, e.g. releasing the tree, //can exhaust stack if (m_nParseDepth + nDepthLimit > DEPTH_LIMIT) throw std::range_error("parser depth limit");
case TBOPER:
xSNode.reset(new SmBinHorNode(m_aCurToken));
NextToken();
//Let the glyph node know it's a binary operation
m_aCurToken.eType = TBOPER;
m_aCurToken.nGroup = TG::Product;
xOper = DoGlyphSpecial(); break;
case TOVERBRACE: case TUNDERBRACE:
xSNode.reset(new SmVerticalBraceNode(m_aCurToken));
xSNode->SetSelection(m_aCurESelection);
xOper.reset(new SmMathSymbolNode(m_aCurToken));
xOper->SetSelection(m_aCurESelection);
NextToken(); break;
case TWIDEBACKSLASH: case TWIDESLASH:
{
SmBinDiagonalNode* pSTmp = new SmBinDiagonalNode(m_aCurToken);
pSTmp->SetAscending(eType == TWIDESLASH);
xSNode.reset(pSTmp);
std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(m_aCurToken));
pNode->SetSelection(m_aCurESelection); //! Of course 'm_aCurToken' is just the first sub-/supscript token. //! It should be of no further interest. The positions of the //! sub-/supscripts will be identified by the corresponding subnodes //! index in the 'aSubNodes' array (enum value from 'SmSubSup').
// process all sub-/supscripts int nIndex = 0; while (TokenInGroup(nActiveGroup))
{
SmTokenType eType(m_aCurToken.eType);
switch (eType)
{ case TRSUB:
nIndex = static_cast<int>(RSUB); break; case TRSUP:
nIndex = static_cast<int>(RSUP); break; case TFROM: case TCSUB:
nIndex = static_cast<int>(CSUB); break; case TTO: case TCSUP:
nIndex = static_cast<int>(CSUP); break; case TLSUB:
nIndex = static_cast<int>(LSUB); break; case TLSUP:
nIndex = static_cast<int>(LSUP); 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
{ // skip sub-/supscript token
NextToken();
}
// get sub-/supscript node // (even when we saw a double-sub/supscript error in the above // in order to minimize mess and continue parsing.)
std::unique_ptr<SmNode> xSNode; if (eType == TFROM || eType == TTO)
{ // parse limits in old 4.0 and 5.0 style
xSNode = DoRelation();
} else
xSNode = DoTerm(true);
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);
// get operator symbol auto xNode = std::make_unique<SmMathSymbolNode>(m_aCurToken);
xNode->SetSelection(m_aCurESelection); // skip operator token
NextToken(); // get sub- supscripts if any if (m_aCurToken.nGroup == TG::Power) return DoSubSup(TG::Power, std::move(xNode)); return xNode;
}
switch (m_aCurToken.eType)
{ case TESCAPE: return DoEscape();
case TNOSPACE: case TLGROUP:
{ bool bNoSpace = m_aCurToken.eType == TNOSPACE; if (bNoSpace)
NextToken(); if (m_aCurToken.eType != TLGROUP) return DoTerm(false); // nospace is no longer concerned
NextToken();
// allow for empty group if (m_aCurToken.eType == TRGROUP)
{
std::unique_ptr<SmStructureNode> xSNode(new SmExpressionNode(m_aCurToken));
xSNode->SetSelection(m_aCurESelection);
xSNode->SetSubNodes(nullptr, nullptr);
auto pNode = DoAlign(!bNoSpace); if (m_aCurToken.eType == TRGROUP)
{
NextToken(); return pNode;
} auto xSNode = std::make_unique<SmExpressionNode>(m_aCurToken);
xSNode->SetSelection(m_aCurESelection);
std::unique_ptr<SmNode> xError(DoError(SmParseError::RgroupExpected));
xSNode->SetSubNodes(std::move(pNode), std::move(xError)); return std::unique_ptr<SmNode>(xSNode.release());
}
case TLEFT: return DoBrace(); case TEVALUATE: return DoEvaluate();
case TBLANK: case TSBLANK: return DoBlank();
case TTEXT:
{ auto pNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_TEXT);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
} case TCHARACTER:
{ auto pNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_VARIABLE);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
} case TIDENT: case TNUMBER:
{ auto pTextNode = std::make_unique<SmTextNode>(
m_aCurToken, m_aCurToken.eType == TNUMBER ? FNT_NUMBER : FNT_VARIABLE);
pTextNode->SetSelection(m_aCurESelection); if (!bGroupNumberIdent)
{
NextToken(); return std::unique_ptr<SmNode>(pTextNode.release());
}
std::vector<std::unique_ptr<SmNode>> aNodes; // Some people want to be able to write "x_2n" for "x_{2n}" // although e.g. LaTeX or AsciiMath interpret that as "x_2 n". // The tokenizer skips whitespaces so we need some additional // work to distinguish from "x_2 n". // See https://bz.apache.org/ooo/show_bug.cgi?id=11752 and // https://bugs.libreoffice.org/show_bug.cgi?id=55853
sal_Int32 nBufLen = m_aBufferString.getLength();
// We need to be careful to call NextToken() only after having // tested for a whitespace separator (otherwise it will be // skipped!) bool moveToNextToken = true; while (m_nBufferIndex < nBufLen
&& m_pSysCC->getType(m_aBufferString, m_nBufferIndex)
!= UnicodeType::SPACE_SEPARATOR)
{
NextToken(); if (m_aCurToken.eType != TNUMBER && m_aCurToken.eType != TIDENT)
{ // Neither a number nor an identifier. We just moved to // the next token, so no need to do that again.
moveToNextToken = false; break;
}
aNodes.emplace_back(std::unique_ptr<SmNode>(new SmTextNode(
m_aCurToken, m_aCurToken.eType == TNUMBER ? FNT_NUMBER : FNT_VARIABLE)));
} if (moveToNextToken)
NextToken(); if (aNodes.empty()) return std::unique_ptr<SmNode>(pTextNode.release()); // We have several concatenated identifiers and numbers. // Let's group them into one SmExpressionNode.
aNodes.insert(aNodes.begin(), std::move(pTextNode));
std::unique_ptr<SmExpressionNode> xNode(new SmExpressionNode(SmToken()));
xNode->SetSubNodes(buildNodeArray(aNodes)); return std::unique_ptr<SmNode>(xNode.release());
} case TLEFTARROW: case TRIGHTARROW: case TUPARROW: case TDOWNARROW: case TCIRC: case TDRARROW: case TDLARROW: case TDLRARROW: case TEXISTS: case TNOTEXISTS: case TFORALL: case TPARTIAL: case TNABLA: case TLAPLACE: case TFOURIER: case TTOWARD: case TDOTSAXIS: case TDOTSDIAG: case TDOTSDOWN: case TDOTSLOW: case TDOTSUP: case TDOTSVERT:
{ auto pNode = std::make_unique<SmMathSymbolNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
}
case TSETN: case TSETZ: case TSETQ: case TSETR: case TSETC: case THBAR: case TLAMBDABAR: case TBACKEPSILON: case TALEPH: case TIM: case TRE: case TWP: case TEMPTYSET: case TINFINITY:
{ auto pNode = std::make_unique<SmMathIdentifierNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
}
case TPLACE:
{ auto pNode = std::make_unique<SmPlaceNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
}
case TSPECIAL: return DoSpecial();
case TBINOM: return DoBinom();
case TFRAC: return DoFrac();
case TSTACK: return DoStack();
case TMATRIX: return DoMatrix();
case THEX:
NextTokenFontSize(); if (m_aCurToken.eType == THEX)
{ auto pTextNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_NUMBER);
pTextNode->SetSelection(m_aCurESelection);
NextToken(); return pTextNode;
} else return DoError(SmParseError::NumberExpected); default: if (TokenInGroup(TG::LBrace)) return DoBrace(); if (TokenInGroup(TG::Oper)) return DoOperator(); if (TokenInGroup(TG::UnOper)) return DoUnOper(); if (TokenInGroup(TG::Attribute) || TokenInGroup(TG::FontAttr))
{
std::stack<std::unique_ptr<SmStructureNode>,
std::vector<std::unique_ptr<SmStructureNode>>>
aStack; bool bIsAttr; for (;;)
{
bIsAttr = TokenInGroup(TG::Attribute); if (!bIsAttr && !TokenInGroup(TG::FontAttr)) break;
aStack.push(bIsAttr ? DoAttribute() : DoFontAttribute());
}
auto xFirstNode = DoPower(); while (!aStack.empty())
{
std::unique_ptr<SmStructureNode> xNode = std::move(aStack.top());
aStack.pop();
xNode->SetSubNodes(nullptr, std::move(xFirstNode));
xFirstNode = std::move(xNode);
} return xFirstNode;
} if (TokenInGroup(TG::Function)) return DoFunction(); return DoError(SmParseError::UnexpectedChar);
}
}
switch (m_aCurToken.eType)
{ case TLPARENT: case TRPARENT: case TLBRACKET: case TRBRACKET: case TLDBRACKET: case TRDBRACKET: case TLBRACE: case TLGROUP: case TRBRACE: case TRGROUP: case TLANGLE: case TRANGLE: case TLCEIL: case TRCEIL: case TLFLOOR: case TRFLOOR: case TLLINE: case TRLINE: case TLDLINE: case TRDLINE:
{ auto pNode = std::make_unique<SmMathSymbolNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return std::unique_ptr<SmNode>(pNode.release());
} default: return DoError(SmParseError::UnexpectedToken);
}
}
switch (eType)
{ case TSUM: case TPROD: case TCOPROD: case TINT: case TINTD: case TIINT: case TIIINT: case TLINT: case TLLINT: case TLLLINT:
pNode.reset(new SmMathSymbolNode(m_aCurToken));
pNode->SetSelection(m_aCurESelection); break;
case TLIM: case TLIMSUP: case TLIMINF: case THADD: case TNAHA: if (eType == TLIMSUP)
m_aCurToken.aText = u"lim sup"_ustr; elseif (eType == TLIMINF)
m_aCurToken.aText = u"lim inf"_ustr; elseif (eType == TNAHA)
m_aCurToken.aText = u"نها"_ustr; elseif (eType == THADD)
m_aCurToken.aText = OUString(&MS_HADD, 1); else
m_aCurToken.aText = u"lim"_ustr;
pNode.reset(new SmTextNode(m_aCurToken, FNT_TEXT));
pNode->SetSelection(m_aCurESelection); break;
switch (eType)
{ case TABS: case TSQRT:
NextToken(); break;
case TNROOT:
NextToken();
xExtra = DoPower(); break;
case TUOPER:
NextToken(); //Let the glyph know what it is...
m_aCurToken.eType = TUOPER;
m_aCurToken.nGroup = TG::UnOper;
xOper = DoGlyphSpecial(); break;
case TPLUS: case TMINUS: case TPLUSMINUS: case TMINUSPLUS: case TNEG: case TFACT:
xOper = DoOpSubSup(); break;
default:
assert(false);
}
// get argument
xArg = DoPower();
if (eType == TABS)
{
xSNode.reset(new SmBraceNode(aNodeToken));
xSNode->SetSelection(aESelection);
xSNode->SetScaleMode(SmScaleMode::Height);
// build nodes for left & right lines // (text, group, level of the used token are of no interest here) // we'll use row & column of the keyword for abs
aNodeToken.eType = TABS;
// get appropriate node for the attribute itself switch (m_aCurToken.eType)
{ case TUNDERLINE: case TOVERLINE: case TOVERSTRIKE:
xAttr.reset(new SmRectangleNode(m_aCurToken));
xAttr->SetSelection(m_aCurESelection);
eScaleMode = SmScaleMode::Width; break;
case TWIDEVEC: case TWIDEHARPOON: case TWIDEHAT: case TWIDETILDE:
xAttr.reset(new SmMathSymbolNode(m_aCurToken));
xAttr->SetSelection(m_aCurESelection);
eScaleMode = SmScaleMode::Width; break;
switch (m_aCurToken.eType)
{ case TITALIC: case TNITALIC: case TBOLD: case TNBOLD: case TPHANTOM:
{ auto pNode = std::make_unique<SmFontNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return pNode;
}
if (m_aCurToken.eType == TDVIPSNAMESCOL)
NextTokenColor(TDVIPSNAMESCOL); if (m_aCurToken.eType == TERROR) return DoError(SmParseError::ColorExpected); if (TokenInGroup(TG::Color))
{
aToken = m_aCurToken;
aESelection = m_aCurESelection; if (m_aCurToken.eType == TRGB) //loads r, g and b
{
sal_uInt32 nr, ng, nb, nc;
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
nr = m_aCurToken.aText.toUInt32(); if (nr > 255) return DoError(SmParseError::ColorExpected);
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
ng = m_aCurToken.aText.toUInt32(); if (ng > 255) return DoError(SmParseError::ColorExpected);
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
nb = m_aCurToken.aText.toUInt32(); if (nb > 255) return DoError(SmParseError::ColorExpected);
nc = nb | ng << 8 | nr << 16 | sal_uInt32(0) << 24;
aToken.cMathChar = OUString::number(nc, 16);
} elseif (m_aCurToken.eType == TRGBA) //loads r, g and b
{
sal_uInt32 nr, na, ng, nb, nc;
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
nr = m_aCurToken.aText.toUInt32(); if (nr > 255) return DoError(SmParseError::ColorExpected);
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
ng = m_aCurToken.aText.toUInt32(); if (ng > 255) return DoError(SmParseError::ColorExpected);
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
nb = m_aCurToken.aText.toUInt32(); if (nb > 255) return DoError(SmParseError::ColorExpected);
NextTokenFontSize(); if (lcl_IsNotWholeNumber(m_aCurToken.aText)) return DoError(SmParseError::ColorExpected);
na = m_aCurToken.aText.toUInt32(); if (na > 255) return DoError(SmParseError::ColorExpected);
nc = nb | ng << 8 | nr << 16 | na << 24;
aToken.cMathChar = OUString::number(nc, 16);
} elseif (m_aCurToken.eType == THEX) //loads hex code
{
sal_uInt32 nc;
NextTokenFontSize(); if (java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0 return DoError(SmParseError::ColorExpected);
nc = m_aCurToken.aText.toUInt32(16);
aToken.cMathChar = OUString::number(nc, 16);
}
aToken.aText = m_aBufferString.subView(nBufferIndex, m_nBufferIndex - nBufferIndex);
NextToken
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 else
java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 52
SmToken ;
ESelection = ()java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 do
{
NextToken void caif_ctrl_cb(structcflayer *,
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 0 return xNode;
}
java.lang.StringIndexOutOfBoundsException: Range [66, 56) out of bounds for length 56
{
m_nParseDepthjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
(sk
NextTokenFontSize
Type;
switch sock_flag(k )
{ case THEX:
Type = FontSizeType::ABSOLUT; break; case TPLUS:
java.lang.StringIndexOutOfBoundsException: Range [38, 31) out of bounds for length 38 break;
java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 20
sjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 break; case TMULTIPLY:
java.lang.StringIndexOutOfBoundsException: Range [20, 16) out of bounds for length 42 break; casejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
Typeunlock break;
default:
}
if(Type :)
{
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 9 if return DoError(SmParseError::SizeExpected);
}
// get number argument
(tx_flow_is_oncf_sk)& if (lcl_IsNumber(m_aCurToken
{
aValue= ..toDouble); /!! Reduce values in order to avoid numerical errors if (java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 9
{
tools::Long nNum = aValue.GetNumerator();
tools::Long nDenom = aValue.GetDenominator();
hile> 1000
java.lang.StringIndexOutOfBoundsException: Range [19, 15) out of bounds for length 44
nDenom /= 10;
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 13 long ;
}
} else
java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 51
pFontNode->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
NextToken0) returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
std:: sent ;
{
java.lang.StringIndexOutOfBoundsException: Range [4, 10) out of bounds for length 0
std::java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 11
xSNode->SetSelection(m_aCurESelection);
std *ittries java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 52
SmScaleMode * (which can fail easily ifit grabthe
SmParseError eError =SmParseError;
[Alan]
tToken()java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
:java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
// check for left bracket if (struct socket *sock, int lvl, int opt, sockptr_t ov,
{
pLeft.reset( opt {
->m_aCurESelection;
NextToken(); = java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
-java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 23
/
// check for right bracket ifjava.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 48
{
pRight.reset(new SmMathSymbolNode(m_aCurToken));
pRight->SetSelection(m_aCurESelection);
NextToken();
} else
eError = SmParseError::RbraceExpected;
} else
eError = SmParseError::RightExpected;
} else
eError = SmParseError::LbraceExpected;
} else
{
assert(TokenInGroup java.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 72
SmTokenType eExpectedType = TUNKNOWN java.lang.StringIndexOutOfBoundsException: Range [7, 6) out of bounds for length 28
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 40
{ case TLPARENT:
eExpectedType = TRPARENT; break;
*
eExpectedType = TRBRACKET break;
= ;
java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 28
eExpectedType = TRDBRACKET; break; case TLLINE:
eExpectedType = TRLINEcaseSS_CONNECTEDjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19 break; caseout
eExpectedType = TRDLINE break; casejava.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 25
; /* Check priority value comming from socket */
java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 48
/*ifindex = id of the interf breakjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 case TLCEIL:
eExpectedType = TRCEIL; break;
TLRLINE:
eExpectedType = TLRLINE;cf_sk>headroom=LL_RESERVED_SPACE_EXTRA(dev,headroom; break; case TLRDLINE:
eExpectedType = TLRDLINE; break; default:
RN(java.lang.StringIndexOutOfBoundsException: Range [36, 34) out of bounds for length 53
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 47
{
=;
pRight->return;
()java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
} else
eError = SmParseError::ParentMismatch;
}
if (eError (sk;
{
(pLeftjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
assert)
xSNode->SetSubNodes()
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return xSNode;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
(sk>)
}
std/
{
DepthProtect aDepthGuard(m_nParseDepth);
auto
pBody->SetSelectionjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
bindjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 // get body if any if .hutdown java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 30
{ do
{ if (m_aCurToken.eType =.java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 28
{
SmMathSymbolNode* pTempNode
=(k structjava.lang.StringIndexOutOfBoundsException: Range [59, 58) out of bounds for length 64
aNodesalive java.lang.StringIndexOutOfBoundsException: Range [50, 48) out of bounds for length 61
NextToken();
}
struct caifsock=NULLjava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
{
aNodes.push_back(DoAlign()); static proto prot { P"
eType=
aNodes.emplace_back(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
} while (m_aCurToken.eType != TEND && m_aCurToken.eType != TRIGHT);
} else
{ do
{ if (m_aCurToken.eType == if (->=
SmMathSymbolNode* -java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 26
pTempNode->SetSelection(m_aCurESelection);
aNodes.emplace_back(std::unique_ptr<SmMathSymbolNode>(pTempNode));
NextToken();
} elseif (!TokenInGroup(TG::RBrace))
{
et PF_CAIF,GFP_KERNEL , kern);
aNodes/* Store the protocol */
s (protocol
} while (m_aCurTokenjava.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 20
}
pBody->SetSubNodes(buildNodeArray(aNodes));
pBody early return pBody;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
std<mNodeSmParser5(
{
aDepthGuard(java.lang.StringIndexOutOfBoundsException: Range [43, 42) out of bounds for length 44
// Create node
std _ java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 43
xSNode-java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
SmToken aToken(TRLINE, MS_VERTLINE, u"evaluate"_ustr, TG::RBrace, 5);
// add symbol name to list of used symbols const OUString aSymbolName(m_aCurToken.aText.copy(1)); if (!aSymbolName.isEmpty())
m_aUsedSymbols.insert(aSymbolName);
auto pNode = std::make_unique<SmSpecialNode>(m_aCurToken);
pNode->SetSelection(m_aCurESelection);
NextToken(); return pNode;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.