private void ProcessEscapeSequence(TexFormula formula, SourceSpan value, ref int position, bool allowClosingDelimiter, ref bool closedDelimiter, ICommandEnvironment environment) { var initialSrcPosition = position; position++; var start = position; while (position < value.Length) { var ch = value[position]; var isEnd = position == value.Length - 1; if (!char.IsLetter(ch) || isEnd) { // Escape sequence has ended // Or it's a symbol. Assuming in this case it will only be a single char. if ((isEnd && char.IsLetter(ch)) || position - start == 0) { position++; } break; } position++; } var commandSpan = value.Segment(start, position - start); var command = commandSpan.ToString(); var formulaSource = new SourceSpan(value.Source, initialSrcPosition, commandSpan.End); SymbolAtom symbolAtom = null; if (SymbolAtom.TryGetAtom(commandSpan, out symbolAtom)) { // Symbol was found. if (symbolAtom.Type == TexAtomType.Accent) { var helper = new TexFormulaHelper(formula, formulaSource); TexFormula accentFormula = ReadScript(formula, value, ref position, environment); helper.AddAccent(accentFormula, symbolAtom.Name); } else if (symbolAtom.Type == TexAtomType.BigOperator) { var opAtom = new BigOperatorAtom(formulaSource, symbolAtom, null, null); formula.Add(AttachScripts(formula, value, ref position, opAtom, true, environment), formulaSource); } else { formula.Add( AttachScripts(formula, value, ref position, symbolAtom, true, environment), formulaSource); } } else if (predefinedFormulas.TryGetValue(command, out var factory)) { // Predefined formula was found. var predefinedFormula = factory(formulaSource); var atom = AttachScripts(formula, value, ref position, predefinedFormula.RootAtom, true, environment); formula.Add(atom, formulaSource); } else if (command.Equals("nbsp")) { // Space was found. var atom = AttachScripts(formula, value, ref position, new SpaceAtom(formulaSource), true, environment); formula.Add(atom, formulaSource); } else if (textStyles.Contains(command)) { // Text style was found. SkipWhiteSpace(value, ref position); var styledFormula = command == TexUtilities.TextStyleName ? ConvertRawText(ReadElement(value, ref position), command) : Parse(ReadElement(value, ref position), command, environment.CreateChildEnvironment()); if (styledFormula.RootAtom == null) { throw new TexParseException("Styled text can't be empty!"); } var atom = AttachScripts(formula, value, ref position, styledFormula.RootAtom, true, environment); var source = new SourceSpan(formulaSource.Source, formulaSource.Start, position); formula.Add(atom, source); } else if (embeddedCommands.Contains(command) || environment.AvailableCommands.ContainsKey(command) || _commandRegistry.ContainsKey(command)) { // Command was found. var commandAtom = ProcessCommand( formula, value, ref position, command, allowClosingDelimiter, ref closedDelimiter, environment); if (commandAtom != null) { commandAtom = allowClosingDelimiter ? commandAtom : AttachScripts( formula, value, ref position, commandAtom, true, environment); var source = new SourceSpan(formulaSource.Source, formulaSource.Start, commandAtom.Source.End); formula.Add(commandAtom, source); } } else { // Escape sequence is invalid. throw new TexParseException("Unknown symbol or command or predefined TeXFormula: '" + command + "'"); } }
private Atom AttachScripts(TexFormula formula, string value, ref int position, Atom atom) { if (position == value.Length) { return(atom); } if (value[position] == superScriptChar || value[position] == subScriptChar) { if (position == value.Length - 1) { position++; return(atom); } } else { return(atom); } TexFormula superscriptFormula = null; TexFormula subscriptFormula = null; //0: Undetermined; 1: Not Yet; 2: Yes, we are; 3: Yes, and make it smaller int markAsBig = 0; //0: In Beginning;1: We are in _;2: we are in ^ int lastIsSuper = 0; while (position < value.Length) { var ch = value[position]; if (ch == superScriptChar || ch == subScriptChar) { if (++position < value.Length && (value[position] == ch)) { markAsBig = 2; if (++position < value.Length && (value[position] == ch)) { markAsBig = 3; position++; } } bool v = ch == superScriptChar; if ((v ? superscriptFormula : subscriptFormula) == null) { lastIsSuper = v ? 2 : 1; } continue; } else if (ch == rightGroupChar || (value[position - 1] != '^' && value[position - 1] != '_')) { break; } if (lastIsSuper == 2) { if (superscriptFormula == null) { superscriptFormula = ReadScript(formula, value, ref position); } else { position--; superscriptFormula.RootAtom = AttachScripts(formula, value, ref position, superscriptFormula.RootAtom); } } else if (lastIsSuper == 1) { if (subscriptFormula == null) { subscriptFormula = ReadScript(formula, value, ref position); } else { position--; subscriptFormula.RootAtom = AttachScripts(formula, value, ref position, subscriptFormula.RootAtom); } } else { break; } } if (superscriptFormula == null && subscriptFormula == null) { return(atom); } // Check whether to return Big Operator or Scripts. if (atom != null && (atom.GetRightType() == CharType.BigOperator || markAsBig >= 2)) { return(BigOperatorAtom.Get(atom, subscriptFormula == null ? null : subscriptFormula.GetRoot, superscriptFormula == null ? null : superscriptFormula.GetRoot, markAsBig == 3)); } else { return(ScriptsAtom.Get(atom, subscriptFormula == null ? null : subscriptFormula.GetRoot, superscriptFormula == null ? null : superscriptFormula.GetRoot)); } }