1758 lines
42 KiB
JavaScript
1758 lines
42 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* This program is a free software product. You can redistribute it and/or
|
||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||
* version 3 as published by the Free Software Foundation. In accordance with
|
||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||
* of any third-party rights.
|
||
*
|
||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||
*
|
||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||
* street, Riga, Latvia, EU, LV-1050.
|
||
*
|
||
* The interactive user interfaces in modified source and object code versions
|
||
* of the Program must display Appropriate Legal Notices, as required under
|
||
* Section 5 of the GNU AGPL version 3.
|
||
*
|
||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||
* grant you any rights under trademark law for use of our trademarks.
|
||
*
|
||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||
* well as technical writing content are licensed under the terms of the
|
||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||
*
|
||
*/
|
||
|
||
"use strict";
|
||
(function (window) {
|
||
const Literals = AscMath.MathLiterals;
|
||
const Struc = AscMath.MathStructures;
|
||
const ConvertTokens = AscMath.ConvertTokens;
|
||
const Tokenizer = AscMath.Tokenizer;
|
||
const GetTypeFont = AscMath.GetTypeFont;
|
||
const GetMathFontChar = AscMath.GetMathFontChar;
|
||
|
||
function CLaTeXParser()
|
||
{
|
||
this.oTokenizer = new Tokenizer(true);
|
||
this.intMathFontType = -1;
|
||
this.isReceiveOneTokenAtTime = false;
|
||
this.isNowMatrix = false;
|
||
this.EscapeSymbol = "";
|
||
this.isOneSymbol = false;
|
||
}
|
||
CLaTeXParser.prototype.IsNotEscapeSymbol = function ()
|
||
{
|
||
return this.oLookahead.data !== this.EscapeSymbol;
|
||
};
|
||
CLaTeXParser.prototype.ReadTokensWhileEnd = function (arrTypeOfLiteral, type)
|
||
{
|
||
let arrLiterals = [];
|
||
let strLiteral = "";
|
||
let styles = [];
|
||
|
||
let isOne = this.isReceiveOneTokenAtTime;
|
||
let isSymbol;
|
||
|
||
if ((isOne || this.isOneSymbol) && this.oLookahead.class === arrTypeOfLiteral.id)
|
||
{
|
||
let oItem = this.oLookahead;
|
||
let strValue = this.EatToken(arrTypeOfLiteral.id).data;
|
||
let oStyle = oItem.style;
|
||
type = Struc.char;
|
||
|
||
strLiteral = this.intMathFontType === -1
|
||
? strValue
|
||
: GetMathFontChar[strValue][this.intMathFontType];
|
||
|
||
styles.push(oStyle);
|
||
|
||
if (this.isOneSymbol)
|
||
this.isOneSymbol = false;
|
||
}
|
||
else
|
||
{
|
||
while (this.oLookahead.class === arrTypeOfLiteral.id
|
||
&& this.EscapeSymbol !== this.oLookahead.data
|
||
&& (styles.length === 0 || styles[styles.length - 1].IsStyleEqual(this.oLookahead.style)))
|
||
{
|
||
let oCurrentItem = this.oLookahead;
|
||
let strCurrent = oCurrentItem.data;
|
||
let oStyle = oCurrentItem.style.Copy();
|
||
this.EatToken(arrTypeOfLiteral.id);
|
||
|
||
if (GetMathFontChar[strCurrent] && GetMathFontChar[strCurrent][this.intMathFontType])
|
||
{
|
||
strLiteral += GetMathFontChar[strCurrent][this.intMathFontType];
|
||
isSymbol = true;
|
||
}
|
||
else
|
||
{
|
||
strLiteral += strCurrent;
|
||
if (this.isMathRm)
|
||
{
|
||
let metaData = oStyle.GetMathMetaData();
|
||
metaData.setIsMathRm(true);
|
||
}
|
||
}
|
||
|
||
styles.push(oStyle);
|
||
}
|
||
}
|
||
|
||
if (styles.length === 1)
|
||
styles = styles[0];
|
||
|
||
arrLiterals.push({type: isSymbol ? Struc.other : type, value: strLiteral, style: styles});
|
||
|
||
if (arrLiterals.length === 1)
|
||
return arrLiterals[0];
|
||
|
||
return arrLiterals
|
||
};
|
||
CLaTeXParser.prototype.SaveState = function (oLookahead)
|
||
{
|
||
this.oTokenizer.SaveState(oLookahead);
|
||
};
|
||
CLaTeXParser.prototype.RestoreState = function ()
|
||
{
|
||
let oRestore = this.oTokenizer.RestoreState();
|
||
if (oRestore)
|
||
this.oLookahead = oRestore;
|
||
};
|
||
CLaTeXParser.prototype.Parse = function (string)
|
||
{
|
||
this.oTokenizer.Init(string);
|
||
this.oLookahead = this.oTokenizer.GetNextToken();
|
||
return this.GetASTTree();
|
||
};
|
||
CLaTeXParser.prototype.GetASTTree2 = function(isEndFunc)
|
||
{
|
||
let arrExp = [];
|
||
while (this.oLookahead.data)
|
||
{
|
||
if (isEndFunc && isEndFunc())
|
||
return arrExp;
|
||
|
||
if (this.IsElementLiteral())
|
||
{
|
||
arrExp.push(this.GetExpressionLiteral(undefined, isEndFunc))
|
||
}
|
||
else
|
||
{
|
||
let oData = this.oLookahead;
|
||
this.EatToken(this.oLookahead.class);
|
||
let strValue = oData.data;
|
||
let oStyle = oData.style;
|
||
|
||
if ("\\bmod" === strValue) // todo в новой версии конвертора добавить отдельный модуль для такого типа токенов
|
||
{
|
||
strValue = " mod "; // в обратную сторону (линейную) такие токены вряд ли получится конвертнуть,
|
||
// а ворде такого токена просто нет
|
||
// todo продумать как будет происходить преобразование в линейную форму
|
||
}
|
||
|
||
arrExp.push({
|
||
type: Struc.char,
|
||
value: strValue,
|
||
style: oStyle,
|
||
})
|
||
}
|
||
}
|
||
|
||
return arrExp;
|
||
}
|
||
CLaTeXParser.prototype.GetASTTree = function ()
|
||
{
|
||
return {
|
||
type: "LaTeXEquation",
|
||
body: this.GetASTTree2()
|
||
};
|
||
};
|
||
CLaTeXParser.prototype.GetCharLiteral = function ()
|
||
{
|
||
return this.ReadTokensWhileEnd(Literals.char, Struc.char);
|
||
};
|
||
CLaTeXParser.prototype.GetOperandLiteral = function ()
|
||
{
|
||
let oPr = this.oLookahead.style;
|
||
const strToken = this.EatToken(Literals.operand.id);
|
||
return {
|
||
type: Struc.char,
|
||
value: strToken.data,
|
||
style: oPr
|
||
};
|
||
}
|
||
CLaTeXParser.prototype.GetOtherLiteral = function ()
|
||
{
|
||
return this.ReadTokensWhileEnd(Literals.other, Struc.other);
|
||
};
|
||
CLaTeXParser.prototype.GetSpaceLiteral = function ()
|
||
{
|
||
// LaTex skip all normal spaces
|
||
while (this.oLookahead.data === " ")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
}
|
||
|
||
let oStyle = this.oLookahead.style;
|
||
|
||
if (this.oLookahead.data === "\\ "
|
||
|| this.oLookahead.data === "\\quad"
|
||
// || this.oLookahead.data === "\\:"
|
||
// || this.oLookahead.data === "\\;"
|
||
)
|
||
{
|
||
let strSpace = "";
|
||
|
||
if (this.oLookahead.data === "\\ ")
|
||
strSpace = " ";
|
||
else if (this.oLookahead.data === "\\quad")
|
||
strSpace = " ";
|
||
// else if (this.oLookahead.data === "\\:")
|
||
// strSpace = " ";
|
||
// else if (this.oLookahead.data === "\\;")
|
||
// strSpace = " ";
|
||
|
||
this.EatToken(this.oLookahead.class)
|
||
|
||
return {
|
||
type: Struc.char,
|
||
value: strSpace,
|
||
style: oStyle
|
||
}
|
||
}
|
||
|
||
//this.ReadTokensWhileEnd(Literals.space, Struc.space);
|
||
};
|
||
CLaTeXParser.prototype.GetNumberLiteral = function ()
|
||
{
|
||
return this.ReadTokensWhileEnd(Literals.number, Struc.number);
|
||
};
|
||
CLaTeXParser.prototype.GetOperatorLiteral = function ()
|
||
{
|
||
let oPr = this.oLookahead.style;
|
||
const strToken = this.EatToken(Literals.operator.id);
|
||
return {
|
||
type: Struc.char,
|
||
value: strToken.data,
|
||
style: oPr
|
||
};
|
||
};
|
||
CLaTeXParser.prototype.IsAccentLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.accent.id;
|
||
};
|
||
CLaTeXParser.prototype.GetAccentLiteral = function (oBase)
|
||
{
|
||
let strAccent,
|
||
oResultAccent,
|
||
oPr;
|
||
|
||
if (this.oLookahead.data === "'" || this.oLookahead.data === "''")
|
||
{
|
||
return this.GetSubSupLiteral(oBase);
|
||
}
|
||
else
|
||
{
|
||
oPr = this.oLookahead.style;
|
||
strAccent = this.oLookahead;
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
strAccent.value = AscMath.MathLiterals.accent.LaTeX[strAccent.data];
|
||
|
||
oBase = this.GetArguments(1);
|
||
oBase = this.GetContentOfLiteral(oBase);
|
||
|
||
oResultAccent = {
|
||
type: Struc.accent,
|
||
base: oBase,
|
||
value: strAccent,
|
||
style: oPr,
|
||
};
|
||
}
|
||
|
||
return oResultAccent;
|
||
};
|
||
CLaTeXParser.prototype.IsFractionLiteral = function ()
|
||
{
|
||
return this.oLookahead.data === "\\frac"
|
||
|| this.oLookahead.data === "\\binom"
|
||
|| this.oLookahead.data === "\\cfrac"
|
||
|| this.oLookahead.data === "\\sfrac";
|
||
};
|
||
CLaTeXParser.prototype.GetFractionType = function (str)
|
||
{
|
||
switch (str)
|
||
{
|
||
case "\\frac" : return BAR_FRACTION; break;
|
||
case "\\over" : return BAR_FRACTION; break;
|
||
case "\\binom" : return NO_BAR_FRACTION; break;
|
||
case "\\atop" : return NO_BAR_FRACTION; break;
|
||
default : return SKEWED_FRACTION; break;
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.GetFractionLiteral = function ()
|
||
{
|
||
let strName = this.oLookahead.data;
|
||
let oFracStyle = this.oLookahead.style;
|
||
let type = this.GetFractionType(this.oLookahead.data);
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
let oResult = this.GetArguments(2);
|
||
|
||
let oFrac = {
|
||
type: Struc.frac,
|
||
up: oResult[0] || {},
|
||
down: oResult[1] || {},
|
||
fracType: type,
|
||
style: oFracStyle,
|
||
};
|
||
|
||
if (strName === '\\binom')
|
||
{
|
||
return {
|
||
type: Struc.bracket_block,
|
||
left: "(",
|
||
right: ")",
|
||
value: [oFrac],
|
||
style: {
|
||
startStyle : oFracStyle,
|
||
endStyle : oFracStyle,
|
||
middle: oFracStyle,
|
||
},
|
||
};
|
||
}
|
||
|
||
return oFrac
|
||
};
|
||
CLaTeXParser.prototype.IsOverLikeLiteral = function ()
|
||
{
|
||
return this.oLookahead.data === "\\over"
|
||
|| this.oLookahead.data === "\\atop"
|
||
}
|
||
CLaTeXParser.prototype.GetOverLikeLiteral = function (oNum)
|
||
{
|
||
if (!oNum)
|
||
oNum = this.GetArguments(1);
|
||
|
||
let oFracStyle = this.oLookahead.style;
|
||
let type = this.GetFractionType(this.oLookahead.data);
|
||
this.EatToken(this.oLookahead.class);
|
||
let oDen = this.GetArguments(1);
|
||
|
||
return {
|
||
type: Struc.frac,
|
||
up: oNum || {},
|
||
down: oDen || {},
|
||
fracType: type,
|
||
style: oFracStyle,
|
||
};
|
||
}
|
||
CLaTeXParser.prototype.IsExpBracket = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.lrBrackets.id
|
||
|| this.oLookahead.class === Literals.lBrackets.id
|
||
|| this.oLookahead.data === "\\left";
|
||
};
|
||
CLaTeXParser.prototype.GetBracketLiteral = function ()
|
||
{
|
||
let arrBracketContent,
|
||
strLeftSymbol,
|
||
strRightSymbol,
|
||
startStyle,
|
||
middle_styles = [],
|
||
endStyle;
|
||
|
||
let isRightAndLeft = false;
|
||
this.SaveState(this.oLookahead);
|
||
|
||
if (this.oLookahead.data === "\\left")
|
||
{
|
||
if (this.oLookahead.data === "\\left")
|
||
isRightAndLeft = true;
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
if (this.oLookahead.data !== "\\left"
|
||
&& this.oLookahead.class === Literals.lBrackets.id
|
||
|| this.oLookahead.data === "."
|
||
|| this.oLookahead.class === Literals.lrBrackets.id
|
||
|| this.oLookahead.class === Literals.rBrackets.id)
|
||
{
|
||
startStyle = this.oLookahead.style;
|
||
strLeftSymbol = this.EatToken(this.oLookahead.class).data;
|
||
}
|
||
else
|
||
{
|
||
this.RestoreState();
|
||
let oData = this.oLookahead;
|
||
this.EatToken(this.oLookahead.class);
|
||
return {
|
||
type: Struc.char,
|
||
value: oData.data,
|
||
style: oData.style,
|
||
}
|
||
}
|
||
|
||
arrBracketContent = this.GetContentOfBracket("\\right", middle_styles);
|
||
|
||
if (this.oLookahead.data === "\\right")
|
||
{
|
||
if (this.oLookahead.data === "\\right" && isRightAndLeft)
|
||
isRightAndLeft = true;
|
||
else
|
||
isRightAndLeft = false;
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
if (this.oLookahead.data !== "\\right"
|
||
&& this.oLookahead.class === Literals.rBrackets.id
|
||
|| this.oLookahead.data === "."
|
||
|| this.oLookahead.class === Literals.lrBrackets.id
|
||
|| this.oLookahead.class === Literals.lBrackets.id)
|
||
{
|
||
endStyle = this.oLookahead.style;
|
||
strRightSymbol = this.EatToken(this.oLookahead.class).data;
|
||
}
|
||
}
|
||
}
|
||
else if (this.oLookahead.class === Literals.lBrackets.id || this.oLookahead.class === Literals.lrBrackets.id)
|
||
{
|
||
startStyle = this.oLookahead.style;
|
||
strLeftSymbol = this.EatToken(this.oLookahead.class).data;
|
||
|
||
if (this.oLookahead.data === "_" || this.oLookahead.data === "^")
|
||
return this.GetPreScriptLiteral();
|
||
|
||
if (this.oLookahead.class === undefined) {
|
||
return {
|
||
type: Struc.char,
|
||
value: strLeftSymbol,
|
||
style: startStyle,
|
||
}
|
||
}
|
||
|
||
if (strLeftSymbol === "|" || strLeftSymbol === "‖" || strLeftSymbol === "\\|")
|
||
{
|
||
arrBracketContent = this.GetContentOfBracket(strLeftSymbol, middle_styles);
|
||
}
|
||
else
|
||
{
|
||
arrBracketContent = this.GetContentOfBracket(undefined, middle_styles);
|
||
}
|
||
|
||
if (this.oLookahead.class === Literals.rBrackets.id || this.oLookahead.class === Literals.lrBrackets.id)
|
||
{
|
||
endStyle = this.oLookahead.style;
|
||
strRightSymbol = this.EatToken(this.oLookahead.class).data;
|
||
}
|
||
}
|
||
|
||
if (strLeftSymbol === "{" && strRightSymbol === "}" && !isRightAndLeft)
|
||
return arrBracketContent;
|
||
|
||
return {
|
||
type: Struc.bracket_block,
|
||
left: strLeftSymbol,
|
||
right: strRightSymbol,
|
||
value: arrBracketContent,
|
||
style: {
|
||
startStyle : startStyle,
|
||
endStyle : endStyle,
|
||
middle: middle_styles,
|
||
},
|
||
};
|
||
};
|
||
CLaTeXParser.prototype.GetContentOfBracket = function (strLeftSymbol, arrMiddleStyles)
|
||
{
|
||
let arrContent = [];
|
||
let intCountOfBracketBlock = 1;
|
||
|
||
while (this.IsElementLiteral()
|
||
|| this.oLookahead.data === "∣"
|
||
|| this.oLookahead.data === "\\mid"
|
||
|| this.oLookahead.data === "ⓜ")
|
||
{
|
||
if (strLeftSymbol && this.oLookahead.data === strLeftSymbol)
|
||
break;
|
||
|
||
if (this.oLookahead.data === "\\right")
|
||
break;
|
||
|
||
if (this.IsElementLiteral())
|
||
{
|
||
// normal space always skip in LaTeX brackets
|
||
this.SkipFreeSpace();
|
||
|
||
let oToken = [this.GetExpressionLiteral([strLeftSymbol])];
|
||
if ((oToken && !Array.isArray(oToken)) || Array.isArray(oToken) && oToken.length > 0)
|
||
{
|
||
arrContent.push(oToken)
|
||
}
|
||
|
||
// normal space always skip in LaTeX brackets
|
||
this.SkipFreeSpace();
|
||
}
|
||
else
|
||
{
|
||
arrMiddleStyles.push(this.oLookahead.style)
|
||
this.EatToken(this.oLookahead.class);
|
||
intCountOfBracketBlock++;
|
||
// normal space always skip in LaTeX brackets
|
||
this.SkipFreeSpace();
|
||
}
|
||
}
|
||
|
||
while (arrContent.length < intCountOfBracketBlock)
|
||
{
|
||
arrContent.push([]);
|
||
}
|
||
|
||
return arrContent;
|
||
};
|
||
CLaTeXParser.prototype.IsElementLiteral = function ()
|
||
{
|
||
return this.oLookahead.class !== null && this.IsNotEscapeSymbol() && (
|
||
this.IsFractionLiteral() ||
|
||
this.oLookahead.class === Literals.number.id ||
|
||
this.oLookahead.class === Literals.char.id ||
|
||
this.oLookahead.class === Literals.space.id ||
|
||
this.IsSqrtLiteral() ||
|
||
this.IsExpBracket() ||
|
||
this.IsFuncLiteral() ||
|
||
this.oLookahead.class === "\\middle" ||
|
||
this.IsAccentLiteral() ||
|
||
this.IsPreScript() ||
|
||
this.IsMathFontLiteral() ||
|
||
this.oLookahead.class === "{" ||
|
||
this.oLookahead.class === Literals.operator.id ||
|
||
this.IsReactLiteral() ||
|
||
this.IsBoxLiteral() ||
|
||
// this.oLookahead.class === oLiteralNames.opDecimal[0] ||
|
||
this.IsArrayLiteral() ||
|
||
this.IsMatrixLiteral() ||
|
||
this.IsHBracket() ||
|
||
this.oLookahead.data === "\\below" ||
|
||
this.oLookahead.data === "\\above" ||
|
||
this.IsOverUnderBarLiteral() ||
|
||
this.IsTextLiteral() ||
|
||
this.IsSpecialSymbol() ||
|
||
this.oLookahead.class === Literals.other.id ||
|
||
this.oLookahead.class === Literals.operand.id ||
|
||
this.IsHorizontalArrowLiteral() ||
|
||
this.oLookahead.class === Literals.punct.id ||
|
||
this.IsUnderOverSet() ||
|
||
this.IsOperatorName()
|
||
);
|
||
};
|
||
CLaTeXParser.prototype.IsSpecialSymbol = function ()
|
||
{
|
||
return this.oLookahead.data === "/" ||
|
||
this.oLookahead.data === "&" ||
|
||
this.oLookahead.data === "@";
|
||
}
|
||
CLaTeXParser.prototype.GetSpecialSymbol = function ()
|
||
{
|
||
let oData = this.oLookahead;
|
||
this.EatToken(this.oLookahead.class)
|
||
return {
|
||
type: Struc.char,
|
||
value: oData.data,
|
||
style: oData.style,
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.GetElementLiteral = function ()
|
||
{
|
||
if (this.IsSpecialSymbol())
|
||
{
|
||
return this.GetSpecialSymbol()
|
||
}
|
||
else if (this.IsFractionLiteral())
|
||
{
|
||
return this.GetFractionLiteral();
|
||
}
|
||
else if (this.oLookahead.class === Literals.number.id)
|
||
{
|
||
return this.GetNumberLiteral();
|
||
}
|
||
else if (this.oLookahead.class === Literals.operand.id)
|
||
{
|
||
return this.GetOperandLiteral();
|
||
}
|
||
else if (this.oLookahead.class === Literals.char.id)
|
||
{
|
||
return this.GetCharLiteral();
|
||
}
|
||
else if (this.oLookahead.class === Literals.punct.id)
|
||
{
|
||
return this.ReadTokensWhileEnd(Literals.punct, Struc.char);
|
||
}
|
||
else if (this.IsHorizontalArrowLiteral())
|
||
{
|
||
return this.GetHorizontalArrowLiteral();
|
||
}
|
||
else if (this.oLookahead.class === Literals.char.id)
|
||
{
|
||
return this.GetOtherLiteral();
|
||
}
|
||
// else if (this.oLookahead.class === oLiteralNames.opDecimal[0])
|
||
// {
|
||
// let strDecimalLiteral = this.EatToken(this.oLookahead.class).data;
|
||
// return {
|
||
// type: oLiteralNames.opDecimal[num],
|
||
// value: strDecimalLiteral
|
||
// }
|
||
// }
|
||
else if (this.oLookahead.class === Literals.space.id)
|
||
{
|
||
return this.GetSpaceLiteral();
|
||
}
|
||
else if (this.IsSqrtLiteral())
|
||
{
|
||
return this.GetSqrtLiteral();
|
||
}
|
||
else if (this.IsExpBracket())
|
||
{
|
||
return this.GetBracketLiteral();
|
||
}
|
||
else if (this.IsFuncLiteral())
|
||
{
|
||
return this.GetFuncLiteral();
|
||
}
|
||
else if (this.oLookahead.class === "\\middle")
|
||
{
|
||
this.EatToken("\\middle");
|
||
return {
|
||
type: "MiddleLiteral",
|
||
value: this.EatToken(this.oLookahead.class).data,
|
||
};
|
||
}
|
||
else if (this.IsAccentLiteral())
|
||
{
|
||
return this.GetAccentLiteral();
|
||
}
|
||
else if (this.IsPreScript())
|
||
{
|
||
return this.GetPreScriptLiteral();
|
||
}
|
||
else if (this.IsMathFontLiteral())
|
||
{
|
||
return this.GetMathFontLiteral();
|
||
}
|
||
else if (this.oLookahead.data === "{")
|
||
{
|
||
return this.GetArguments(1)[0];
|
||
}
|
||
else if (this.oLookahead.class ===Literals.operator.id)
|
||
{
|
||
return this.GetOperatorLiteral()
|
||
}
|
||
else if (this.IsReactLiteral())
|
||
{
|
||
return this.GetRectLiteral()
|
||
}
|
||
else if (this.IsBoxLiteral())
|
||
{
|
||
return this.GetBoxLiteral()
|
||
}
|
||
else if (this.IsMatrixLiteral())
|
||
{
|
||
return this.GetMatrixLiteral();
|
||
}
|
||
else if (this.IsArrayLiteral())
|
||
{
|
||
return this.GetArrayLiteral();
|
||
}
|
||
else if (this.IsOverUnderBarLiteral())
|
||
{
|
||
return this.GetUnderOverBarLiteral();
|
||
}
|
||
else if (this.IsHBracket())
|
||
{
|
||
return this.GetHBracketLiteral()
|
||
}
|
||
else if (this.IsTextLiteral())
|
||
{
|
||
return this.GetTextLiteral();
|
||
}
|
||
else if (this.IsUnderOverSet())
|
||
{
|
||
return this.GetUnderOverSetLiteral();
|
||
}
|
||
else if (this.IsOperatorName())
|
||
{
|
||
return this.GetOperatorName();
|
||
}
|
||
else if (this.oLookahead.data === "/")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
return {
|
||
type: Struc.char,
|
||
value: "/",
|
||
}
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsOperatorName = function ()
|
||
{
|
||
return this.oLookahead.data === "\\operatorname"
|
||
};
|
||
CLaTeXParser.prototype.GetOperatorName = function ()
|
||
{
|
||
let style = this.oLookahead.style;
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
let arg = this.GetArguments(1);
|
||
|
||
return {
|
||
type: Struc.func_lim,
|
||
value: arg.value,
|
||
style: style,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsUnderOverSet = function ()
|
||
{
|
||
return this.oLookahead.data === "\\underset"
|
||
|| this.oLookahead.data === "\\overset";
|
||
};
|
||
CLaTeXParser.prototype.GetUnderOverSetLiteral = function()
|
||
{
|
||
let style = this.oLookahead.style;
|
||
let isUnder = this.oLookahead.data === "\\underset";
|
||
this.EatToken(this.oLookahead.class); // skip name of function;
|
||
|
||
let args = this.GetArguments(2);
|
||
|
||
return {
|
||
type: Struc.limit,
|
||
base: args[1],
|
||
value: args[0],
|
||
isBelow: (isUnder === true) ? VJUST_TOP : VJUST_BOT,
|
||
style: style,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsHorizontalArrowLiteral = function()
|
||
{
|
||
return this.oLookahead.class === Literals.horizontal.id;
|
||
}
|
||
CLaTeXParser.prototype.GetHorizontalArrowLiteral = function ()
|
||
{
|
||
let oStyle = this.oLookahead.style;
|
||
let oData = this.EatToken(this.oLookahead.class);
|
||
oData.data = Literals.horizontal.LaTeX[oData.data];
|
||
|
||
if (this.IsGetBelowAboveLiteral())
|
||
{
|
||
let isBelow = this.oLookahead.data === "\\below" ? VJUST_TOP : VJUST_BOT;
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetArguments(1);
|
||
|
||
return {
|
||
type: Struc.group_character,
|
||
value: oContent,
|
||
hBrack: oData,
|
||
down: undefined,
|
||
up: undefined,
|
||
style: oStyle,
|
||
isBelow: isBelow,
|
||
}
|
||
}
|
||
|
||
return {
|
||
type: Struc.char,
|
||
value: oData.data,
|
||
style: oStyle,
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.IsGetBelowAboveLiteral = function()
|
||
{
|
||
return this.oLookahead.data === "\\below" || this.oLookahead.data === "\\above";
|
||
}
|
||
CLaTeXParser.prototype.GetBelowAboveLiteral = function(base)
|
||
{
|
||
let oStyle = this.oLookahead.style;
|
||
let isBelow = false;
|
||
if (this.oLookahead.data === "\\above")
|
||
isBelow = true;
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetArguments(1);
|
||
|
||
if(base && base.type === Struc.func || base.type === Struc.func_lim)
|
||
{
|
||
this.SkipFreeSpace();
|
||
let third = this.GetArguments(1);
|
||
return {
|
||
type: Struc.func_lim,
|
||
value: {
|
||
type: Struc.char,
|
||
value: base.type === Struc.func_lim ? base.value.value : base.value,
|
||
style: base.style
|
||
},
|
||
up: isBelow ? oContent : undefined,
|
||
down: !isBelow ? oContent : undefined,
|
||
third: third,
|
||
style: base.style,
|
||
}
|
||
}
|
||
|
||
let strNewBaseValue = AscMath.ConvertWord(base.value, true);
|
||
if (strNewBaseValue)
|
||
base.value = strNewBaseValue;
|
||
|
||
return {
|
||
type: Struc.limit,
|
||
base: base,
|
||
value: oContent,
|
||
isBelow: (isBelow === false) ? VJUST_TOP : VJUST_BOT,
|
||
style: oStyle,
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.IsTextLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.text.id;
|
||
}
|
||
CLaTeXParser.prototype.GetTextLiteral = function ()
|
||
{
|
||
let style = this.oLookahead.style.Copy();
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetTextArgument();
|
||
|
||
let metaData = style.GetMathMetaData();
|
||
metaData.setIsText(true);
|
||
|
||
return {
|
||
type: Struc.char,
|
||
value: oContent,
|
||
style: style
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.GetTextArgument = function ()
|
||
{
|
||
let strText = "";
|
||
this.SkipFreeSpace();
|
||
|
||
this.EatToken(this.oLookahead.class); // {
|
||
|
||
while (this.oLookahead.data !== "}" && this.oLookahead.data !== undefined)
|
||
{
|
||
strText += this.EatToken(this.oLookahead.class).data;
|
||
}
|
||
|
||
this.EatToken(this.oLookahead.class); // }
|
||
|
||
return strText;
|
||
}
|
||
CLaTeXParser.prototype.IsFuncLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.func.id || this.oLookahead.class === Literals.nary.id
|
||
};
|
||
CLaTeXParser.prototype.GetFuncLiteral = function (oFunc)
|
||
{
|
||
let oFuncContent = oFunc ? oFunc : this.EatToken(this.oLookahead.class);
|
||
let oPr = oFuncContent.style;
|
||
let oThirdStyle;
|
||
let isNoLimits = false;
|
||
let SetStyleAndGetArgument = function (oThis)
|
||
{
|
||
oThirdStyle = oThis.oLookahead.style;
|
||
return oThis.GetArguments(1);
|
||
}
|
||
|
||
if (this.oLookahead.class === "\\limits")
|
||
this.EatToken("\\limits");
|
||
|
||
if (this.oLookahead.class === "\\nolimits")
|
||
{
|
||
isNoLimits = true;
|
||
this.EatToken("\\nolimits")
|
||
}
|
||
|
||
if (this.oLookahead.data === " ")
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
let oThirdContent = !this.IsSubSup() && !this.IsGetBelowAboveLiteral()
|
||
? SetStyleAndGetArgument(this)
|
||
: undefined;
|
||
|
||
let name = oFuncContent.data ? oFuncContent.data : oFuncContent.value;
|
||
|
||
this.SkipOneSpace();
|
||
|
||
if (oFuncContent.class === Literals.nary.id)
|
||
{
|
||
if(AscMath.MathLiterals.func.IsLaTeXIncludeLimit(name) && !isNoLimits)
|
||
{
|
||
let metaData = oPr.GetMathMetaData();
|
||
metaData.setIsLimitNary(true);
|
||
}
|
||
|
||
return {
|
||
type: Struc.nary,
|
||
value: Literals.nary.LaTeX[name],
|
||
style: oPr,
|
||
third: oThirdContent,
|
||
thirdStyle: oThirdStyle
|
||
}
|
||
}
|
||
else if (AscMath.MathLiterals.func.IsLaTeXIncludeLimit(name) && (this.IsSubSup() || this.IsGetBelowAboveLiteral() || this.oLookahead.data === '\\limits'))
|
||
{
|
||
return {
|
||
type: Struc.func_lim,
|
||
value: {
|
||
type: Struc.char,
|
||
value: name.slice(1),
|
||
style: oPr
|
||
},
|
||
style: oPr,
|
||
third: oThirdContent
|
||
}
|
||
}
|
||
else if (AscMath.MathLiterals.func.IsLaTeXIncludeNormal(name))
|
||
{
|
||
return {
|
||
type: Struc.func,
|
||
value: {
|
||
type: Struc.char,
|
||
value: name.slice(1),
|
||
style: oPr
|
||
},
|
||
style: oPr,
|
||
third: oThirdContent
|
||
}
|
||
}
|
||
else if (!oThirdContent)
|
||
{
|
||
return {
|
||
type: Struc.func,
|
||
value: name.slice(1),
|
||
style: oPr
|
||
}
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsReactLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.rect.id;
|
||
};
|
||
CLaTeXParser.prototype.GetRectLiteral = function ()
|
||
{
|
||
let oCtrPr = this.oLookahead.style;
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetArguments(1);
|
||
return {
|
||
type: Struc.rect,
|
||
value: oContent,
|
||
style: oCtrPr,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsOverUnderBarLiteral = function ()
|
||
{
|
||
return this.oLookahead.data === "\\underline" || this.oLookahead.data === "\\overline"
|
||
};
|
||
CLaTeXParser.prototype.GetUnderOverBarLiteral = function ()
|
||
{
|
||
let oStyle = this.oLookahead.style;
|
||
let strUnderOverLine = this.EatToken(this.oLookahead.class);
|
||
let oOperand = this.GetArguments(1);
|
||
|
||
strUnderOverLine.data = (strUnderOverLine.data === "\\underline")
|
||
? "▁"
|
||
: "¯";
|
||
|
||
return {
|
||
type: Struc.bar,
|
||
bar: strUnderOverLine,
|
||
value: oOperand,
|
||
style: oStyle,
|
||
};
|
||
};
|
||
CLaTeXParser.prototype.IsBoxLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.box.id;
|
||
}
|
||
CLaTeXParser.prototype.GetBoxLiteral = function ()
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetArguments(1);
|
||
return {
|
||
type: Struc.box,
|
||
value: oContent,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.GetBorderBoxLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.rect.id;
|
||
}
|
||
CLaTeXParser.prototype.IsGetBorderBoxLiteral = function ()
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
let oContent = this.GetArguments(1);
|
||
return {
|
||
type: Struc.rect,
|
||
value: oContent,
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.IsHBracket = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.hbrack.id;
|
||
};
|
||
CLaTeXParser.prototype.GetHBracketLiteral = function ()
|
||
{
|
||
let oHBracket = this.oLookahead,
|
||
oPr = this.oLookahead.style,
|
||
oDown,
|
||
oUp;
|
||
oHBracket.data = Literals.hbrack.LaTeX[oHBracket.data];
|
||
|
||
let isBelow = Literals.hbrack.GetPos(oHBracket.data);
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
let oContent = this.GetArguments(1);
|
||
this.SkipFreeSpace();
|
||
|
||
if (this.IsSubSup())
|
||
{
|
||
if (this.oLookahead.data === "_")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
oDown = this.GetArguments(1);
|
||
}
|
||
else
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
oUp = this.GetArguments(1);
|
||
}
|
||
}
|
||
|
||
return {
|
||
type: Struc.group_character,
|
||
value: oContent,
|
||
hBrack: oHBracket,
|
||
down: oDown,
|
||
up: oUp,
|
||
style: oPr,
|
||
isBelow: isBelow,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.GetWrapperElementLiteral = function ()
|
||
{
|
||
if (!this.IsSubSup() && this.oLookahead.class !== "\\over")
|
||
{
|
||
let oWrapperContent = this.GetElementLiteral();
|
||
|
||
if (oWrapperContent)
|
||
{
|
||
if (this.IsSubSup() || this.oLookahead.class === "\\limits")
|
||
{
|
||
while (this.IsSubSup())
|
||
{
|
||
oWrapperContent = this.GetSubSupLiteral(oWrapperContent);
|
||
}
|
||
return oWrapperContent;
|
||
}
|
||
//else if (this.oLookahead.class === Literals.accent.id)
|
||
//{
|
||
// return this.GetAccentLiteral(oWrapperContent);
|
||
//}
|
||
else if (this.IsGetBelowAboveLiteral())
|
||
{
|
||
return this.GetBelowAboveLiteral(oWrapperContent)
|
||
}
|
||
else if (this.IsOverLikeLiteral())
|
||
{
|
||
return this.GetOverLikeLiteral(oWrapperContent);
|
||
}
|
||
}
|
||
|
||
return oWrapperContent;
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.GetWrapperElement2 = function ()
|
||
{
|
||
this.isOneSymbol = true;
|
||
let oWrapperContent = this.GetElementLiteral();
|
||
|
||
if (this.oLookahead.class === Literals.accent.id)
|
||
{
|
||
return this.GetAccentLiteral(oWrapperContent);
|
||
}
|
||
else if (this.IsGetBelowAboveLiteral())
|
||
{
|
||
return this.GetBelowAboveLiteral(oWrapperContent)
|
||
}
|
||
|
||
return oWrapperContent;
|
||
};
|
||
CLaTeXParser.prototype.IsSubSup = function ()
|
||
{
|
||
return this.oLookahead.data === "^" || this.oLookahead.data === "_";
|
||
};
|
||
CLaTeXParser.prototype.GetSubSupLiteral = function (oBaseContent, isSingle)
|
||
{
|
||
let isLimits,
|
||
oDownContent,
|
||
oUpContent,
|
||
oThirdContent,
|
||
oSubStyle,
|
||
oSupStyle;
|
||
|
||
if (undefined === oBaseContent)
|
||
{
|
||
oBaseContent = this.GetElementLiteral();
|
||
}
|
||
|
||
if (this.oLookahead.class === "\\limits")
|
||
{
|
||
this.EatToken("\\limits");
|
||
isLimits = true;
|
||
}
|
||
else if (oBaseContent.type === Struc.func_lim || oBaseContent.isLimits)
|
||
{
|
||
isLimits = true;
|
||
}
|
||
|
||
if (oBaseContent && oBaseContent.type === Struc.bracket_block && oBaseContent.left === "{" && oBaseContent.right === "}")
|
||
{
|
||
oBaseContent = oBaseContent.value;
|
||
}
|
||
|
||
if (this.oLookahead.data === "'" || this.oLookahead.data === "''")
|
||
{
|
||
oUpContent = {
|
||
type: Struc.char,
|
||
value: this.EatToken(this.oLookahead.class).data
|
||
}
|
||
}
|
||
|
||
if (this.oLookahead.data === "_")
|
||
{
|
||
oSubStyle = this.oLookahead.style;
|
||
oDownContent = this.GetPartOfSupSup();
|
||
this.SkipFreeSpace();
|
||
if (this.oLookahead.data === "^" && isSingle !== true)
|
||
{
|
||
oSupStyle = this.oLookahead.style;
|
||
oUpContent = this.GetPartOfSupSup();
|
||
}
|
||
else if (oDownContent && oDownContent.down === undefined && oDownContent.base)
|
||
{
|
||
oDownContent = oDownContent.base;
|
||
}
|
||
}
|
||
else if (this.oLookahead.data === "^")
|
||
{
|
||
oSupStyle = this.oLookahead.style;
|
||
oUpContent = this.GetPartOfSupSup();
|
||
this.SkipFreeSpace();
|
||
if (this.oLookahead.data === "_" && isSingle !== true)
|
||
{
|
||
oSubStyle = this.oLookahead.style;
|
||
oDownContent = this.GetPartOfSupSup();
|
||
}
|
||
else if (oUpContent && oUpContent.up === undefined && oUpContent.base && oUpContent.type !== "BelowAboveLiteral")
|
||
{
|
||
oUpContent = oUpContent.base;
|
||
}
|
||
}
|
||
|
||
if (oBaseContent && (oBaseContent.type === Struc.func || oBaseContent.type == Struc.func_lim || oBaseContent.type === Struc.nary))
|
||
{
|
||
this.SkipOneSpace();
|
||
oThirdContent = this.GetArguments(1);
|
||
}
|
||
|
||
if (oBaseContent.type === Struc.func_lim && oUpContent && oDownContent)
|
||
{
|
||
oBaseContent.type = Struc.func;
|
||
isLimits = false;
|
||
}
|
||
|
||
|
||
return {
|
||
type: Struc.sub_sub,
|
||
value: oBaseContent,
|
||
up: oUpContent,
|
||
down: oDownContent,
|
||
third: oThirdContent,
|
||
isLimits: isLimits,
|
||
style: {supStyle: oSupStyle, subStyle: oSubStyle},
|
||
};
|
||
};
|
||
CLaTeXParser.prototype.GetPartOfSupSup = function ()
|
||
{
|
||
let oElement;
|
||
let strSymbol = this.oLookahead.class;
|
||
this.EatToken(strSymbol);
|
||
|
||
if (this.oLookahead.data === "'" || this.oLookahead.data === "''")
|
||
{
|
||
oElement = {
|
||
type: Struc.char,
|
||
value: this.EatToken(this.oLookahead.class).data
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (this.oLookahead.data === "{")
|
||
{
|
||
oElement = this.GetArguments(1);
|
||
|
||
}
|
||
else
|
||
{
|
||
oElement = this.GetWrapperElement2();
|
||
}
|
||
}
|
||
|
||
if (this.oLookahead.data === strSymbol) {
|
||
oElement = this.GetSubSupLiteral(oElement, true);
|
||
}
|
||
return oElement;
|
||
};
|
||
CLaTeXParser.prototype.IsPreScript = function ()
|
||
{
|
||
return (this.oLookahead.class === "^" || this.oLookahead.class === "_");
|
||
};
|
||
CLaTeXParser.prototype.GetPreScriptLiteral = function ()
|
||
{
|
||
let oUpContent;
|
||
let oDownContent;
|
||
let oBaseContent;
|
||
let oOutput;
|
||
|
||
if (this.oLookahead.data === "_") {
|
||
oDownContent = this.GetPartOfSupSup();
|
||
if (this.oLookahead.data === "^") {
|
||
oUpContent = this.GetPartOfSupSup();
|
||
}
|
||
}
|
||
else if (this.oLookahead.data === "^") {
|
||
oUpContent = this.GetPartOfSupSup();
|
||
if (this.oLookahead.data === "_") {
|
||
oDownContent = this.GetPartOfSupSup();
|
||
}
|
||
}
|
||
|
||
if (this.oLookahead.data === "}") {
|
||
this.EatToken(this.oLookahead.class)
|
||
}
|
||
|
||
this.SkipFreeSpace();
|
||
oBaseContent = this.GetElementLiteral();
|
||
|
||
oOutput = { type: Struc.pre_script };
|
||
|
||
if (oUpContent)
|
||
oOutput.up = oUpContent;
|
||
|
||
if (oDownContent)
|
||
oOutput.down = oDownContent;
|
||
|
||
if (oBaseContent)
|
||
oOutput.value = oBaseContent;
|
||
|
||
return oOutput;
|
||
};
|
||
CLaTeXParser.prototype.IsSqrtLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.radical.id;
|
||
};
|
||
CLaTeXParser.prototype.GetSqrtLiteral = function ()
|
||
{
|
||
let oBaseContent,
|
||
oIndexContent,
|
||
oOutput,
|
||
oStyle = this.oLookahead.style;
|
||
|
||
this.EatToken(Literals.radical.id);
|
||
if (this.oLookahead.data === "[")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
oIndexContent = this.GetExpressionLiteral(["]"]);
|
||
if (this.oLookahead.data === "]")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
}
|
||
}
|
||
oBaseContent = this.GetArguments(1);
|
||
oOutput = {
|
||
type: Struc.radical,
|
||
value: oBaseContent,
|
||
style: oStyle,
|
||
};
|
||
|
||
if (oIndexContent)
|
||
oOutput.index = oIndexContent;
|
||
return oOutput;
|
||
};
|
||
CLaTeXParser.prototype.IsMathFontLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.font.id;
|
||
}
|
||
CLaTeXParser.prototype.GetMathFontLiteral = function ()
|
||
{
|
||
let intPrevType = this.intMathFontType;
|
||
this.isMathRm = this.oLookahead.data === "\\mathrm";
|
||
this.intMathFontType = GetTypeFont[this.oLookahead.data];
|
||
|
||
this.EatToken(this.oLookahead.class);
|
||
let oOutput = this.GetArguments(1);
|
||
this.isMathRm = null;
|
||
|
||
this.intMathFontType = intPrevType;
|
||
return oOutput;
|
||
};
|
||
CLaTeXParser.prototype.IsMatrixLiteral = function ()
|
||
{
|
||
return (this.oLookahead.class === Literals.matrix.id
|
||
|| this.oLookahead.data === "\\substack")
|
||
&& !this.IsEndMatrixLiteral()
|
||
};
|
||
CLaTeXParser.prototype.IsEndMatrixLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.matrix.id
|
||
&& Literals.matrix.LaTeX[this.oLookahead.data] === 2
|
||
|| this.oLookahead.data === "}";
|
||
};
|
||
CLaTeXParser.prototype.IsAlignBlockForArray = function ()
|
||
{
|
||
if (this.oLookahead.data !== "{")
|
||
return false;
|
||
|
||
this.SaveState(this.oLookahead);
|
||
|
||
let oAlignBlock = this.GetArguments(1);
|
||
|
||
const IsAlignContent = function (str)
|
||
{
|
||
let arr = [];
|
||
for (let i = 0; i < str.length; i++)
|
||
{
|
||
if (str[i] === "l" || str[i] === "c" || str[i] === "r")
|
||
arr.push(true);
|
||
}
|
||
|
||
if (arr.length === str.length)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
if (oAlignBlock.type === Struc.char)
|
||
{
|
||
let strAlignBlock = oAlignBlock.value.trim();
|
||
|
||
if (IsAlignContent(strAlignBlock))
|
||
return strAlignBlock;
|
||
}
|
||
else
|
||
{
|
||
this.RestoreState();
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.IsArrayLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.array.id && Literals.array.LaTeX[this.oLookahead.data] === 1
|
||
}
|
||
CLaTeXParser.prototype.IsEndArrayLiteral = function ()
|
||
{
|
||
return this.oLookahead.class === Literals.array.id && Literals.array.LaTeX[this.oLookahead.data] === 2
|
||
}
|
||
CLaTeXParser.prototype.GetArrayLiteral = function ()
|
||
{
|
||
let name = this.EatToken(this.oLookahead.class).data,
|
||
data;
|
||
|
||
if (name !== "\\array{")
|
||
{
|
||
// set align in NamesOfLiterals
|
||
let align = this.IsAlignBlockForArray();
|
||
data = this.GetContentOfMatrixOrArray(function (oThis) {return oThis.IsEndArrayLiteral()});
|
||
}
|
||
else
|
||
{
|
||
data = this.GetContentOfMatrixOrArray(function (oThis) {return oThis.oLookahead.data === "}"});
|
||
}
|
||
|
||
return {
|
||
type: Struc.matrix,
|
||
value: data.value,
|
||
style: data.style,
|
||
strMatrixType: ""
|
||
}
|
||
}
|
||
|
||
CLaTeXParser.prototype.GetMatrixLiteral = function ()
|
||
{
|
||
let strMatrixType;
|
||
|
||
switch (this.oLookahead.data)
|
||
{
|
||
case "\\begin{cases}":
|
||
strMatrixType = "{";
|
||
break
|
||
case "\\begin{pmatrix}":
|
||
case "\\pmatrix":
|
||
case "⒨":
|
||
strMatrixType = "()";
|
||
break;
|
||
case "\\begin{bmatrix}":
|
||
case "\\bmatrix":
|
||
strMatrixType = "[]";
|
||
break;
|
||
case "\\begin{Bmatrix}":
|
||
case "\\Bmatrix":
|
||
strMatrixType = "{}";
|
||
break;
|
||
case "\\begin{vmatrix}":
|
||
case "\\vmatrix":
|
||
strMatrixType = "|";
|
||
break;
|
||
case "\\begin{Vmatrix}":
|
||
case "⒩":
|
||
case "\\Vmatrix":
|
||
strMatrixType = "‖";
|
||
break;
|
||
case "\\begin{array}":
|
||
case "\\begin{matrix}":
|
||
case "\\begin{equation}":
|
||
case "\\substack":
|
||
case "■":
|
||
//case "█":
|
||
default:
|
||
strMatrixType = "";
|
||
}
|
||
|
||
this.isNowMatrix = true;
|
||
|
||
let name = this.EatToken(this.oLookahead.class).data;
|
||
if (name === "\\substack")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
}
|
||
|
||
while (this.oLookahead.data === "[")
|
||
{
|
||
this.GetArguments(1);
|
||
}
|
||
|
||
this.SkipFreeSpace();
|
||
|
||
let data = this.GetContentOfMatrixOrArray(function (oThis) {return oThis.IsEndMatrixLiteral()});
|
||
|
||
this.isNowMatrix = false;
|
||
|
||
return {
|
||
type: Struc.matrix,
|
||
value: data.value,
|
||
style: data.style,
|
||
strMatrixType: strMatrixType,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.GetContentOfMatrixOrArray = function (oFunc)
|
||
{
|
||
let oLookahead;
|
||
let arrMatrixContent = [];
|
||
let styles = {};
|
||
let nRow = 0;
|
||
|
||
styles.head = this.oLookahead.style;
|
||
styles.cols = {};
|
||
styles.rows = {};
|
||
|
||
while (this.oLookahead.class !== undefined && !oFunc(this))
|
||
{
|
||
oLookahead = this.oLookahead;
|
||
let oContent = this.GetRayLiteral(styles.cols, styles.rows, nRow, oFunc);
|
||
|
||
if (oLookahead === this.oLookahead)
|
||
break;
|
||
|
||
if (oContent)
|
||
arrMatrixContent.push(oContent);
|
||
else if (oContent === false)
|
||
arrMatrixContent.push({}, {});
|
||
else if (oContent === undefined)
|
||
arrMatrixContent.push({});
|
||
else if (this.IsEndMatrixLiteral())
|
||
arrMatrixContent.push({}, {});
|
||
|
||
nRow++;
|
||
}
|
||
|
||
let intMaxLengthOfMatrixRow = -Infinity;
|
||
let intIndexOfMaxMatrixRow = -1;
|
||
|
||
for (let i = 0; i < arrMatrixContent.length; i++)
|
||
{
|
||
let arrContent = arrMatrixContent[i];
|
||
intMaxLengthOfMatrixRow = arrContent.length;
|
||
intIndexOfMaxMatrixRow = i;
|
||
}
|
||
|
||
for (let i = 0; i < arrMatrixContent.length; i++)
|
||
{
|
||
if (i !== intIndexOfMaxMatrixRow)
|
||
{
|
||
let arrMatrix = arrMatrixContent[i];
|
||
for (let j = arrMatrix.length; j < intMaxLengthOfMatrixRow; j++)
|
||
{
|
||
arrMatrix.push({});
|
||
}
|
||
}
|
||
}
|
||
|
||
if (oFunc(this))
|
||
{
|
||
this.EatToken(this.oLookahead.class)
|
||
}
|
||
|
||
return {
|
||
value: arrMatrixContent,
|
||
style: styles,
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.GetRayLiteral = function (cols, rows, nRow, oFunc)
|
||
{
|
||
let arrRayContent;
|
||
let oLookahead;
|
||
|
||
while (this.oLookahead.class !== Literals.arrayMatrix.id && !oFunc(this))
|
||
{
|
||
if (oLookahead === this.oLookahead)
|
||
return arrRayContent;
|
||
else
|
||
oLookahead = this.oLookahead;
|
||
|
||
rows[nRow] = {}
|
||
arrRayContent = this.GetElementOfMatrix(rows[nRow]);
|
||
nRow++;
|
||
}
|
||
|
||
if (this.oLookahead.class === Literals.arrayMatrix.id)
|
||
{
|
||
cols[nRow] = this.oLookahead.style;
|
||
this.EatToken(this.oLookahead.class)
|
||
|
||
if (!arrRayContent && this.IsEndMatrixLiteral())
|
||
return false;
|
||
}
|
||
|
||
this.SkipFreeSpace();
|
||
return arrRayContent
|
||
};
|
||
CLaTeXParser.prototype.GetElementOfMatrix = function (oStyle)
|
||
{
|
||
let arrRow = [];
|
||
let intLength = 0;
|
||
let intCount = 0;
|
||
let isAlreadyGetContent = false;
|
||
|
||
while (this.IsElementLiteral() || this.oLookahead.data === "&" )
|
||
{
|
||
let intCopyOfLength = intLength;
|
||
|
||
if (this.oLookahead.data === "\\\\" || this.IsEndMatrixLiteral())
|
||
break;
|
||
|
||
if (this.oLookahead.data !== "&")
|
||
{
|
||
const checkIsEndFunc = function()
|
||
{
|
||
return this.IsEndMatrixLiteral() || this.IsEndArrayLiteral() || this.oLookahead.data === '&' || this.oLookahead.data === '\\\\'
|
||
}.bind(this);
|
||
|
||
arrRow.push(this.GetASTTree2(checkIsEndFunc));
|
||
intLength++;
|
||
isAlreadyGetContent = true;
|
||
this.SkipFreeSpace();
|
||
}
|
||
else
|
||
{
|
||
oStyle[intCount] = this.oLookahead.style;
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
if (isAlreadyGetContent === false)
|
||
{
|
||
arrRow.push({});
|
||
intCount++;
|
||
intLength++;
|
||
}
|
||
else if (intCopyOfLength === intLength)
|
||
{
|
||
intCount++;
|
||
}
|
||
|
||
this.SkipFreeSpace();
|
||
}
|
||
|
||
}
|
||
|
||
if (intLength !== intCount + 1)
|
||
{
|
||
for (let j = intLength; j <= intCount; j++)
|
||
{
|
||
arrRow.push({});
|
||
}
|
||
}
|
||
else if (arrRow.length === 1 && arrRow[0].length === 0)
|
||
{
|
||
arrRow.push([]);
|
||
}
|
||
|
||
return arrRow;
|
||
};
|
||
CLaTeXParser.prototype.IsExpressionLiteral = function(arrBreak)
|
||
{
|
||
const arrEndOfExpression = ["}", "\\endgroup", "\\end", "┤"];
|
||
let isEndOfExp = !arrEndOfExpression.includes(this.oLookahead.data);
|
||
|
||
let isEnd = false;
|
||
|
||
if (Array.isArray(arrBreak))
|
||
isEnd = !arrBreak.includes(this.oLookahead.data);
|
||
else
|
||
isEnd = this.oLookahead.data !== arrBreak;
|
||
|
||
let isEscape = this.oLookahead.data !== this.EscapeSymbol
|
||
|
||
return isEnd
|
||
&& isEscape
|
||
&& isEndOfExp
|
||
&& this.IsElementLiteral();
|
||
};
|
||
CLaTeXParser.prototype.GetExpressionLiteral = function (arrBreakSymbol, fBreak)
|
||
{
|
||
this.EscapeSymbol = arrBreakSymbol;
|
||
const arrExpList = [];
|
||
|
||
while (this.IsExpressionLiteral(arrBreakSymbol) && (!fBreak || !fBreak()))
|
||
{
|
||
if (this.IsPreScript())
|
||
{
|
||
let el = this.GetPreScriptLiteral();
|
||
if (el)
|
||
arrExpList.push(el);
|
||
}
|
||
else
|
||
{
|
||
let el = this.GetWrapperElementLiteral();
|
||
if (el)
|
||
arrExpList.push(el);
|
||
}
|
||
}
|
||
|
||
this.EscapeSymbol = undefined;
|
||
return this.GetContentOfLiteral(arrExpList)
|
||
};
|
||
CLaTeXParser.prototype.EatToken = function (tokenType)
|
||
{
|
||
if (tokenType !== undefined && this.oLookahead.class === tokenType) {
|
||
const oToken = this.oLookahead;
|
||
// if (oToken === null) {
|
||
// console.log('Unexpected end of input, expected: ' + tokenType);
|
||
// }
|
||
// if (oToken.class !== tokenType) {
|
||
// console.log('Unexpected token: ' + oToken.class + ', expected: ' + tokenType);
|
||
// }
|
||
this.oLookahead = this.oTokenizer.GetNextToken();
|
||
return oToken;
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.SkipFreeSpace = function ()
|
||
{
|
||
while (this.oLookahead.data === " ") {
|
||
this.oLookahead = this.oTokenizer.GetNextToken();
|
||
}
|
||
};
|
||
CLaTeXParser.prototype.SkipOneSpace = function ()
|
||
{
|
||
if (this.oLookahead.data === " ") {
|
||
this.oLookahead = this.oTokenizer.GetNextToken();
|
||
}
|
||
}
|
||
CLaTeXParser.prototype.GetArguments = function (intCountOfArguments)
|
||
{
|
||
let oArgument = [];
|
||
while (intCountOfArguments > 0) {
|
||
this.SkipFreeSpace();
|
||
if (this.oLookahead.data === "{") {
|
||
this.SkipFreeSpace();
|
||
this.EatToken(this.oLookahead.class);
|
||
|
||
if (this.oLookahead.data === '\\prime')
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
oArgument.push({
|
||
type: Struc.char,
|
||
value: "′"
|
||
});
|
||
this.EatToken(this.oLookahead.class);
|
||
return oArgument;
|
||
}
|
||
else if (this.oLookahead.data === "\\pprime")
|
||
{
|
||
this.EatToken(this.oLookahead.class);
|
||
oArgument.push({
|
||
type: Struc.char,
|
||
value: "″"
|
||
});
|
||
this.EatToken(this.oLookahead.class);
|
||
return oArgument;
|
||
}
|
||
|
||
oArgument.push(this.GetExpressionLiteral());
|
||
this.EatToken(this.oLookahead.class);
|
||
}
|
||
else {
|
||
this.SkipFreeSpace();
|
||
oArgument.push(this.GetWrapperElementLiteral());
|
||
}
|
||
intCountOfArguments--;
|
||
}
|
||
if (oArgument.length === 1 && Array.isArray(oArgument)) {
|
||
return oArgument[0];
|
||
}
|
||
return oArgument;
|
||
};
|
||
CLaTeXParser.prototype.GetContentOfLiteral = function (oContent)
|
||
{
|
||
if (Array.isArray(oContent))
|
||
{
|
||
if (oContent.length === 1)
|
||
return oContent[0];
|
||
|
||
return oContent;
|
||
}
|
||
|
||
return oContent;
|
||
};
|
||
function ConvertLaTeXToTokensList(str, oContext, isGetOnlyTokens)
|
||
{
|
||
if (undefined === str || null === str)
|
||
return;
|
||
|
||
const oConverter = new CLaTeXParser(true);
|
||
const oTokens = oConverter.Parse(str);
|
||
|
||
if (!isGetOnlyTokens)
|
||
ConvertTokens(oTokens, oContext);
|
||
else
|
||
return oTokens;
|
||
|
||
return true;
|
||
};
|
||
|
||
//---------------------------------------export----------------------------------------------------
|
||
window["AscMath"] = window["AscMath"] || {};
|
||
window["AscMath"].ConvertLaTeXToTokensList = ConvertLaTeXToTokensList;
|
||
})(window);
|