private TexFormula Parse(string value, ref int position, bool allowClosingDelimiter, string textStyle) { var formula = new TexFormula() { TextStyle = textStyle }; var closedDelimiter = false; while (position < value.Length && !(allowClosingDelimiter && closedDelimiter)) { char ch = value[position]; if (IsWhiteSpace(ch)) { position++; } else if (ch == escapeChar) { ProcessEscapeSequence(formula, value, ref position, allowClosingDelimiter, ref closedDelimiter); } else if (ch == leftGroupChar) { var groupValue = ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar); var parsedGroup = Parse(groupValue, textStyle); var innerGroupAtom = parsedGroup.RootAtom ?? new RowAtom(); var groupAtom = new TypedAtom(innerGroupAtom, TexAtomType.Ordinary, TexAtomType.Ordinary); formula.Add(AttachScripts(formula, value, ref position, groupAtom)); } else if (ch == rightGroupChar) { throw new TexParseException("Found a closing '" + rightGroupChar + "' without an opening '" + leftGroupChar + "'!"); } else if (ch == superScriptChar || ch == subScriptChar || ch == primeChar) { if (position == 0) { throw new TexParseException("Every script needs a base: \"" + superScriptChar + "\", \"" + subScriptChar + "\" and \"" + primeChar + "\" can't be the first character!"); } else { throw new TexParseException("Double scripts found! Try using more braces."); } } else { var scriptsAtom = AttachScripts(formula, value, ref position, ConvertCharacter(formula, value, ref position, ch)); formula.Add(scriptsAtom); } } return(formula); }
//public TexFormula Convert(System.Linq.Expressions.Expression value) //{ // return new TexExpressionVisitor(value, this).Formula; //} public TexFormula Parse(string value) { var formula = new TexFormula(); var position = 0; while (position < value.Length) { char ch = value[position]; if (IsWhiteSpace(ch)) { position++; } else if (ch == escapeChar) { ProcessEscapeSequence(formula, value, ref position); } else if (ch == leftGroupChar) { formula.Add(AttachScripts(formula, value, ref position, Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar)).RootAtom)); } else if (ch == rightGroupChar) { throw new TexParseException("Found a closing '" + rightGroupChar + "' without an opening '" + leftGroupChar + "'!"); } else if (ch == superScriptChar || ch == subScriptChar || ch == primeChar) { if (position == 0) { throw new TexParseException("Every script needs a base: \"" + superScriptChar + "\", \"" + subScriptChar + "\" and \"" + primeChar + "\" can't be the first character!"); } else { throw new TexParseException("Double scripts found! Try using more braces."); } } else { var scriptsAtom = AttachScripts(formula, value, ref position, ConvertCharacter(formula, value, ref position, ch)); formula.Add(scriptsAtom); } } return(formula); }
private static TexFormula ConvertRawText(SourceSpan value, string textStyle) { var formula = new TexFormula { Source = value, TextStyle = textStyle }; var position = 0; var initialPosition = position; while (position < value.Length) { var ch = value[position]; var source = value.Segment(position, 1); var atom = IsWhiteSpace(ch) ? (Atom) new SpaceAtom(source) : new CharAtom(source, ch, textStyle); position++; formula.Add(atom, value.Segment(initialPosition, position - initialPosition)); } return(formula); }
private TexFormula Parse( SourceSpan value, ref int position, bool allowClosingDelimiter, string textStyle, ICommandEnvironment environment) { var formula = new TexFormula { Source = value, TextStyle = textStyle }; var closedDelimiter = false; var skipWhiteSpace = ShouldSkipWhiteSpace(textStyle); var initialPosition = position; while (position < value.Length && !(allowClosingDelimiter && closedDelimiter)) { char ch = value[position]; var source = value.Segment(position, 1); if (IsWhiteSpace(ch)) { if (!skipWhiteSpace) { formula.Add(new SpaceAtom(source), source); } position++; } else if (ch == escapeChar) { ProcessEscapeSequence( formula, value, ref position, allowClosingDelimiter, ref closedDelimiter, environment); } else if (ch == leftGroupChar) { var groupValue = ReadElement(value, ref position); var parsedGroup = Parse(groupValue, textStyle, environment.CreateChildEnvironment()); var innerGroupAtom = parsedGroup.RootAtom ?? new RowAtom(groupValue); var groupAtom = new TypedAtom( innerGroupAtom.Source, innerGroupAtom, TexAtomType.Ordinary, TexAtomType.Ordinary); var scriptsAtom = this.AttachScripts(formula, value, ref position, groupAtom, true, environment); formula.Add(scriptsAtom, value.Segment(initialPosition, position - initialPosition)); } else if (ch == rightGroupChar) { throw new TexParseException("Found a closing '" + rightGroupChar + "' without an opening '" + leftGroupChar + "'!"); } else if (ch == superScriptChar || ch == subScriptChar || ch == primeChar) { if (position == 0) { throw new TexParseException("Every script needs a base: \"" + superScriptChar + "\", \"" + subScriptChar + "\" and \"" + primeChar + "\" can't be the first character!"); } else { throw new TexParseException("Double scripts found! Try using more braces."); } } else { var character = ConvertCharacter(formula, ref position, source, environment); if (character != null) { var scriptsAtom = AttachScripts( formula, value, ref position, character, skipWhiteSpace, environment); formula.Add(scriptsAtom, value.Segment(initialPosition, position)); } } } return(formula); }
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()); var source = value.Segment(start, position - start); var atom = styledFormula.RootAtom ?? new NullAtom(source); var commandAtom = AttachScripts(formula, value, ref position, atom, true, environment); formula.Add(commandAtom, 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 void ProcessEscapeSequence( TexFormula formula, string value, ref int position, bool allowClosingDelimiter, ref bool closedDelimiter) { var result = new StringBuilder(); 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)) || result.Length == 0) { result.Append(ch); position++; } break; } result.Append(ch); position++; } var command = result.ToString(); SymbolAtom symbolAtom = null; TexFormula predefinedFormula = null; if (SymbolAtom.TryGetAtom(command, out symbolAtom)) { // Symbol was found. if (symbolAtom.Type == TexAtomType.Accent) { TexFormulaHelper helper = new TexFormulaHelper(formula); TexFormula accentFormula = ReadScript(formula, value, ref position); helper.AddAccent(accentFormula, symbolAtom.Name); } else if (symbolAtom.Type == TexAtomType.BigOperator) { var opAtom = new BigOperatorAtom(symbolAtom, null, null); formula.Add(AttachScripts(formula, value, ref position, opAtom)); } else { formula.Add(AttachScripts(formula, value, ref position, symbolAtom)); } } else if (predefinedFormulas.TryGetValue(command, out predefinedFormula)) { // Predefined formula was found. formula.Add(AttachScripts(formula, value, ref position, predefinedFormula.RootAtom)); } else if (command.Equals("nbsp")) { // Space was found. formula.Add(AttachScripts(formula, value, ref position, new SpaceAtom())); } else if (textStyles.Contains(command)) { // Text style was found. SkipWhiteSpace(value, ref position); var styledFormula = Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar), command); if (styledFormula.RootAtom == null) { throw new TexParseException("Styled text can't be empty!"); } formula.Add(AttachScripts(formula, value, ref position, styledFormula.RootAtom)); } else if (commands.Contains(command)) { // Command was found. var commandAtom = ProcessCommand( formula, value, ref position, command, allowClosingDelimiter, ref closedDelimiter); commandAtom = allowClosingDelimiter ? commandAtom : AttachScripts( formula, value, ref position, commandAtom); formula.Add(commandAtom); } else { // Escape sequence is invalid. throw new TexParseException("Unknown symbol or command or predefined TeXFormula: '" + command + "'"); } }
private void ProcessEscapeSequence(TexFormula formula, string value, ref int position) { var result = new StringBuilder(); position++; while (position < value.Length) { var ch = value[position]; var isEnd = position == value.Length - 1; if (!char.IsLetter(ch) || isEnd) { // Escape sequence has ended. if (isEnd) { result.Append(ch); position++; } break; } result.Append(ch); position++; } var command = result.ToString(); SymbolAtom symbolAtom = null; TexFormula predefinedFormula = null; try { symbolAtom = SymbolAtom.GetAtom(command); } catch (SymbolNotFoundException) { } try { predefinedFormula = GetFormula(command); } catch (FormulaNotFoundException) { } if (symbolAtom != null) { // Symbol was found. formula.Add(AttachScripts(formula, value, ref position, symbolAtom)); } else if (predefinedFormula != null) { // Predefined formula was found. formula.Add(AttachScripts(formula, value, ref position, predefinedFormula.RootAtom)); } else if (command.Equals("nbsp")) { // Space was found. formula.Add(AttachScripts(formula, value, ref position, new SpaceAtom())); } else if (textStyles.Contains(command)) { // Text style was found. SkipWhiteSpace(value, ref position); var styledFormula = Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar)); styledFormula.TextStyle = command; formula.Add(AttachScripts(formula, value, ref position, styledFormula.RootAtom)); } else if (commands.Contains(command)) { // Command was found. formula.Add(AttachScripts(formula, value, ref position, ProcessCommand(formula, value, ref position, command))); } else { // Escape sequence is invalid. throw new TexParseException("Unknown symbol or command or predefined TeXFormula: '" + command + "'"); } }
//public TexFormula Convert(System.Linq.Expressions.Expression value) //{ // return new TexExpressionVisitor(value, this).Formula; //} public TexFormula Parse(string value) { var formula = new TexFormula(); var position = 0; while (position < value.Length) { char ch = value[position]; if (IsWhiteSpace(ch)) { position++; } else if (ch == escapeChar) { ProcessEscapeSequence(formula, value, ref position); } else if (ch == leftGroupChar) { formula.Add(AttachScripts(formula, value, ref position, Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar)).RootAtom)); } else if (ch == rightGroupChar) { throw new TexParseException("Found a closing '" + rightGroupChar + "' without an opening '" + leftGroupChar + "'!"); } else if (ch == superScriptChar || ch == subScriptChar || ch == primeChar) { if (position == 0) throw new TexParseException("Every script needs a base: \"" + superScriptChar + "\", \"" + subScriptChar + "\" and \"" + primeChar + "\" can't be the first character!"); else throw new TexParseException("Double scripts found! Try using more braces."); } else { var scriptsAtom = AttachScripts(formula, value, ref position, ConvertCharacter(formula, value, ref position, ch)); formula.Add(scriptsAtom); } } return formula; }
private void ProcessEscapeSequence( TexFormula formula, SourceSpan value, ref int position, bool allowClosingDelimiter, ref bool closedDelimiter) { 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); helper.AddAccent(accentFormula, symbolAtom.Name); } else if (symbolAtom.Type == TexAtomType.BigOperator) { var opAtom = new BigOperatorAtom(formulaSource, symbolAtom, null, null); formula.Add(this.AttachScripts(formula, value, ref position, opAtom), formulaSource); } else { formula.Add(this.AttachScripts(formula, value, ref position, symbolAtom), formulaSource); } } else if (predefinedFormulas.TryGetValue(command, out var factory)) { // Predefined formula was found. var predefinedFormula = factory(formulaSource); var atom = this.AttachScripts(formula, value, ref position, predefinedFormula.RootAtom); formula.Add(atom, formulaSource); } else if (command.Equals("nbsp")) { // Space was found. var atom = this.AttachScripts(formula, value, ref position, new SpaceAtom(formulaSource)); formula.Add(atom, formulaSource); } else if (textStyles.Contains(command)) { // Text style was found. this.SkipWhiteSpace(value, ref position); var styledFormula = Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar), command); if (styledFormula.RootAtom == null) { throw new TexParseException("Styled text can't be empty!"); } var atom = this.AttachScripts(formula, value, ref position, styledFormula.RootAtom); var source = new SourceSpan(formulaSource.Source, formulaSource.Start, position); formula.Add(atom, source); } else if (commands.Contains(command)) { // Command was found. var commandAtom = this.ProcessCommand( formula, value, ref position, command, allowClosingDelimiter, ref closedDelimiter); commandAtom = allowClosingDelimiter ? commandAtom : AttachScripts( formula, value, ref position, commandAtom); var source = new SourceSpan(formulaSource.Source, formulaSource.Start, commandAtom.Source.End); formula.Add(commandAtom, source); } else { // this.AttachScripts(formula, value, ref position, ); position = initialSrcPosition; var fallbackSpan = new SourceSpan(value.Source, start, commandSpan.End); var escapeAtom = this.AttachScripts( formula, value, ref position, new CharAtom(new SourceSpan(value.Source, position, 1), '\\'), true); // this.ConvertCharacter(formula, ref position, new SourceSpan(value.Source,position,1)); var scriptsAtom = this.AttachScripts( formula, value, ref position, this.ConvertCharacter(formula, ref position, fallbackSpan), true); // formula.Add(scriptsAtom, formulaSource ); // Escape sequence is invalid. //throw new TexParseException("Unknown symbol or command or predefined TeXFormula: '" + command + "'"); } }
private void ProcessEscapeSequence(TexFormula formula, string value, ref int position) { var result = new StringBuilder(); 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 || result.Length == 0) { result.Append(ch); position++; } break; } result.Append(ch); position++; } var command = result.ToString(); SymbolAtom symbolAtom = null; TexFormula predefinedFormula = null; try { symbolAtom = SymbolAtom.GetAtom(command); } catch (SymbolNotFoundException) { } try { predefinedFormula = GetFormula(command); } catch (FormulaNotFoundException) { } if (symbolAtom != null) { // Symbol was found. if (symbolAtom.Type == TexAtomType.Accent) { TexFormulaHelper helper = new TexFormulaHelper(formula); TexFormula accentFormula = ReadScript(formula, value, ref position); helper.AddAccent(accentFormula, symbolAtom.Name); } else { formula.Add(AttachScripts(formula, value, ref position, symbolAtom)); } } else if (predefinedFormula != null) { // Predefined formula was found. formula.Add(AttachScripts(formula, value, ref position, predefinedFormula.RootAtom)); } else if (command.Equals("nbsp")) { // Space was found. formula.Add(AttachScripts(formula, value, ref position, new SpaceAtom())); } else if (textStyles.Contains(command)) { // Text style was found. SkipWhiteSpace(value, ref position); var styledFormula = Parse(ReadGroup(formula, value, ref position, leftGroupChar, rightGroupChar)); styledFormula.TextStyle = command; formula.Add(AttachScripts(formula, value, ref position, styledFormula.RootAtom)); } else if (commands.Contains(command)) { // Command was found. formula.Add(AttachScripts(formula, value, ref position, ProcessCommand(formula, value, ref position, command))); } else { // Escape sequence is invalid. throw new TexParseException("Unknown symbol or command or predefined TeXFormula: '" + command + "'"); } }