public static MathList MathListForCharacters(string chars) { var r = new MathList(); foreach (char c in chars) { r.Add(ForCharacter(c)); } return(r); }
public static MathList WithAtoms(List <IMathAtom> atoms) { var r = new MathList(); foreach (var atom in atoms) { r.Add(atom); } return(r); }
internal MathList StopCommand(string command, MathList list, char stopChar) { if (command == "right") { if (_currentInnerAtom == null) { SetError("Missing \\left"); return(null); } _currentInnerAtom.RightBoundary = _BoundaryAtomForDelimiterType("right"); if (_currentInnerAtom.RightBoundary == null) { return(null); } return(list); } if (fractionCommands.ContainsKey(command)) { bool rule = (command == "over"); var fraction = new Fraction(rule); var delimiters = fractionCommands[command]; if (delimiters != null) { fraction.LeftDelimiter = delimiters.Value.First; fraction.RightDelimiter = delimiters.Value.Second; } fraction.Numerator = list; fraction.Denominator = BuildInternal(false, stopChar); if (_error != null) { return(null); } return(MathLists.WithAtoms(fraction)); } else if (command == "\\" || command == "cr") { if (_currentEnvironment == null) { var table = BuildTable(null, list, true, stopChar); if (table == null) { return(null); } return(MathLists.WithAtoms(table)); } else { // stop the current list and increment the row count _currentEnvironment.NRows++; return(list); } } else if (command == "end") { if (_currentEnvironment == null) { SetError(@"Missing \begin"); return(null); } var env = ReadEnvironment(); if (env == null) { return(null); } if (env != _currentEnvironment.Name) { SetError($"Begin environment name {_currentEnvironment.Name} does not match end environment name {env}"); return(null); } _currentEnvironment.Ended = true; return(list); } return(null); }
internal IMathList BuildInternal(bool oneCharOnly, char stopChar) { if (oneCharOnly && stopChar > 0) { throw new InvalidOperationException("Cannot set both oneCharOnly and stopChar"); } var r = new MathList(); IMathAtom prevAtom = null; while (HasCharacters) { if (_error != null) { return(null); } IMathAtom atom; var ch = GetNextCharacter(); if (oneCharOnly) { if (ch == '^' || ch == '}' || ch == '_' || ch == '&') { // this is not the character we are looking for. They are for the caller to look at. UnlookCharacter(); return(r); } } if (stopChar > 0 && ch == stopChar) { return(r); } switch (ch) { case '^': if (prevAtom == null || prevAtom.Superscript != null || !prevAtom.ScriptsAllowed) { prevAtom = MathAtoms.Create(MathAtomType.Ordinary, string.Empty); r.Add(prevAtom); } // this is a superscript for the previous atom. // note, if the next char is StopChar, it will be consumed and doesn't count as stop. prevAtom.Superscript = this.BuildInternal(true); continue; case '_': if (prevAtom == null || prevAtom.Subscript != null || !prevAtom.ScriptsAllowed) { prevAtom = MathAtoms.Create(MathAtomType.Ordinary, string.Empty); r.Add(prevAtom); } // this is a subscript for the previous atom. // note, if the next char is StopChar, it will be consumed and doesn't count as stop. prevAtom.Subscript = this.BuildInternal(true); continue; case '{': IMathList sublist; if (_currentEnvironment != null && _currentEnvironment.Name == null) { // \\ or \cr which do not have a corrosponding \end var oldEnv = _currentEnvironment; _currentEnvironment = null; sublist = BuildInternal(false, '}'); _currentEnvironment = oldEnv; } else { sublist = BuildInternal(false, '}'); } if (sublist == null) { return(null); } prevAtom = sublist.Atoms.LastOrDefault(); if (oneCharOnly) { r.Append(sublist); return(r); } #warning TODO Example //https://phabricator.wikimedia.org/T99369 //https://phab.wmfusercontent.org/file/data/xsimlcnvo42siudvwuzk/PHID-FILE-bdcqexocj5b57tj2oezn/math_rendering.png //dt, \text{d}t, \partial t, \nabla\psi \\ \underline\overline{dy/dx, \text{d}y/\text{d}x, \frac{dy}{dx}, \frac{\text{d}y}{\text{d}x}, \frac{\partial^2}{\partial x_1\partial x_2}y} \\ \prime, atom = new Group { InnerList = sublist }; break; case '}': if (oneCharOnly || stopChar != 0) { throw new InvalidCodePathException("This should have been handled before."); } SetError("Missing opening brace"); return(null); case '\\': var command = ReadCommand(); var done = StopCommand(command, r, stopChar); if (done != null) { return(done); } if (_error != null) { return(null); } if (ApplyModifier(command, prevAtom)) { continue; } var fontStyleQ = MathAtoms.FontStyle(command); if (fontStyleQ.HasValue) { var fontStyle = fontStyleQ.Value; var oldSpacesAllowed = _textMode; var oldFontStyle = _currentFontStyle; _textMode = (command == "text"); _currentFontStyle = fontStyle; var childList = BuildInternal(true); if (childList == null) { return(null); } _currentFontStyle = oldFontStyle; _textMode = oldSpacesAllowed; prevAtom = childList.Atoms.LastOrDefault(); r.Append(childList); if (oneCharOnly) { return(r); } continue; } atom = AtomForCommand(command, stopChar); if (atom == null) { SetError(_error ?? "Internal error"); return(null); } break; case '&': { // column separation in tables if (_currentEnvironment != null) { return(r); } var table = BuildTable(null, r, false, stopChar); if (table == null) { return(null); } return(MathLists.WithAtoms(table)); } case '\'': // this case is NOT in iosMath int i = 1; while (ExpectCharacter('\'')) { i++; } atom = new Prime(i); break; default: if (_textMode && ch == ' ') { atom = MathAtoms.ForLatexSymbolName(" "); } else { atom = MathAtoms.ForCharacter(ch); if (atom == null) { // not a recognized character continue; } } break; } if (atom == null) { throw new InvalidCodePathException("Atom shouldn't be null"); } atom.FontStyle = _currentFontStyle; r.Add(atom); prevAtom = atom; if (oneCharOnly) { return(r); // we consumed our character. } } if (stopChar > 0) { if (stopChar == '}') { SetError("Missing closing brace"); } else { // we never found our stop character. SetError("Expected character not found: " + stopChar.ToString()); } } return(r); }