예제 #1
0
        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);
        }
예제 #2
0
        //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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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 + "'");
            }
        }
예제 #6
0
        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 + "'");
            }
        }
예제 #7
0
        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 + "'");
            }
        }
예제 #8
0
        //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;
        }
예제 #9
0
        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 + "'");
            }
        }
예제 #10
0
        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 + "'");
            }
        }