Beispiel #1
0
 public ParseNode(TexToken token)
     : this()
 {
     this.Kind     = ParseNodeKind.Token;
     this.Token    = token;
     this.Children = new ParseNodeCollection(this);
 }
Beispiel #2
0
 private void WritePrefixOperatorNode(ComposedTokenStream tokenStream, TexExpressionNode node,
                                      ComposerState state)
 {
     if (node.Children.Count >= 1)
     {
         tokenStream.Write(TexToken.FromSymbol(node.Symbol));
         foreach (var argNode in node.Arguments)
         {
             if (argNode.Children.Count != 1)
             {
                 throw new TexComposerException(argNode, string.Format(
                                                    errorMessageUnexpectedNumberOfChildren, argNode.Symbol, argNode.Children.Count));
             }
             tokenStream.Write(TexToken.FromSymbol(argNode.Symbol));
             WriteNode(tokenStream, argNode.Children[0], state);
         }
         tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.Space));
         foreach (var childNode in node.Children)
         {
             WriteNode(tokenStream, childNode, state);
         }
     }
     else
     {
         throw new TexComposerException(node, string.Format(
                                            errorMessageUnexpectedNumberOfChildren, node.Symbol, node.Children.Count));
     }
 }
Beispiel #3
0
        public TokenStream Tokenise(TrackedTextReader reader)
        {
            char nextChar;

            while (reader.Peek() != -1)
            {
                nextChar = (char)reader.Peek();

                if (char.IsWhiteSpace(nextChar))
                {
                    reader.Read();
                }
                else if (char.IsDigit(nextChar))
                {
                    yield return(TexToken.FromNumber(ScanReal(reader), reader.Position, nextChar.ToString()));
                }
                else if (nextChar == '\\')
                {
                    object value;
                    var    token = TexToken.FromValue(ScanLongSymbol(reader, out value), value, reader.Position,
                                                      nextChar.ToString());
                    if (token.Symbol != TexSymbolKind.Unknown)
                    {
                        yield return(token);
                    }
                }
                else
                {
                    object value;
                    yield return(TexToken.FromValue(ScanShortSymbol(reader, out value), value, reader.Position,
                                                    nextChar.ToString()));
                }
            }
            yield return(TexToken.FromSymbol(TexSymbolKind.EndOfStream, reader.Position, null));
        }
Beispiel #4
0
        private ParseNode ParseTermOptional(TokenStream tokenStream, ref ParserState state, bool isSubTree)
        {
            var valueNode = ParseFactorialValueOptional(tokenStream, ref state);

            if (valueNode == null)
            {
                return(null);
            }
            var node = new ParseNode(ParseNodeKind.InfixOperator);

            node.Children.Add(valueNode);
            var opNode   = ParseTermOperatorOptional(tokenStream, ref state);
            var termNode = ParseTermOptional(tokenStream, ref state, true);

            if (termNode == null)
            {
                return(node);
            }
            if (opNode == null)
            {
                node.Children.Add(new ParseNode(TexToken.FromSymbol(TexSymbolKind.Dot,
                                                                    tokenStream.Current.SourcePosition, null)));
            }
            else
            {
                node.Children.Add(opNode);
            }
            node.Children.Add(termNode);
            node.IsSubExpression = isSubTree;
            return(node);
        }
Beispiel #5
0
        private ParseNode ParseTextOptional(TokenStream tokenStream, ref ParserState state)
        {
            if (tokenStream.Current.Symbol != TexSymbolKind.Text)
            {
                return(null);
            }
            tokenStream.ForceMoveNext();
            switch (tokenStream.Current.Symbol)
            {
            case TexSymbolKind.GroupOpen:
                tokenStream.ForceMoveNext();
                var sb = new StringBuilder();
                while (tokenStream.Current.Symbol != TexSymbolKind.GroupClose)
                {
                    sb.Append((char)tokenStream.Current.Value);
                    tokenStream.ForceMoveNext();
                }
                if (sb.Length == 0)
                {
                    throw new TexParserException(tokenStream.Current, errorMessageTextValueEmpty);
                }
                tokenStream.ForceMoveNext();
                return(new ParseNode(TexToken.FromValue(TexSymbolKind.Text, sb.ToString(),
                                                        tokenStream.Current.SourcePosition, null)));

            default:
                throw new TexParserException(tokenStream.Current, new[] {
                    TexSymbolKind.GroupOpen
                });
            }
        }
Beispiel #6
0
 private void WriteBracketedFunction(ComposedTokenStream tokenStream, TexExpressionNode node,
                                     ComposerState state)
 {
     if (node.Children.Count >= 1)
     {
         tokenStream.Write(TexToken.FromSymbol(node.Symbol));
         foreach (var argNode in node.Arguments)
         {
             tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.SquareBracketOpen));
             state.IsParentNodeGroupOpen = true;
             WriteNode(tokenStream, argNode, state);
             tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.SquareBracketClose));
         }
         foreach (var childNode in node.Children)
         {
             tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.GroupOpen));
             state.IsParentNodeGroupOpen = true;
             WriteNode(tokenStream, childNode, state);
             tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.GroupClose));
         }
     }
     else
     {
         throw new TexComposerException(node, string.Format(
                                            errorMessageUnexpectedNumberOfChildren, node.Symbol, node.Children.Count));
     }
 }
Beispiel #7
0
 public ParseNode(TexToken token, IEnumerable <ParseNode> children)
     : this(token)
 {
     foreach (var childNode in children)
     {
         this.Children.Add(childNode);
     }
 }
Beispiel #8
0
        private void Write(string value, TexToken prevToken)
        {
            var encloseWithGroup = this.StrictMode &&
                                   (prevToken.Symbol == TexSymbolKind.RaiseToIndex || prevToken.Symbol == TexSymbolKind.LowerToIndex) &&
                                   value.Length > 1;

            if (encloseWithGroup)
            {
                this.TextWriter.Write("{");
            }
            this.TextWriter.Write(value);
            if (encloseWithGroup)
            {
                this.TextWriter.Write("}");
            }
        }
Beispiel #9
0
 private void WritePostfixOperatorNode(ComposedTokenStream tokenStream, TexExpressionNode node,
                                       ComposerState state)
 {
     if (node.Children.Count >= 1)
     {
         foreach (var childNode in node.Children)
         {
             WriteNode(tokenStream, childNode, state);
         }
         tokenStream.Write(TexToken.FromSymbol(node.Symbol));
     }
     else
     {
         throw new TexComposerException(node, string.Format(
                                            errorMessageUnexpectedNumberOfChildren, node.Symbol, node.Children.Count));
     }
 }
Beispiel #10
0
        private char?GetShortSymbol(TexToken token)
        {
            switch (token.Symbol)
            {
                #region General
            case TexSymbolKind.Prime:
                return('\'');

            case TexSymbolKind.Colon:
                return(':');

            case TexSymbolKind.Comma:
                return(',');

            case TexSymbolKind.RaiseToIndex:
                return('^');

            case TexSymbolKind.LowerToIndex:
                return('_');

                #endregion

                #region Values
            case TexSymbolKind.Letter:
                return((char)token.Value);

                #endregion

                #region Brackets
            case TexSymbolKind.GroupOpen:
                return('{');

            case TexSymbolKind.GroupClose:
                return('}');

            case TexSymbolKind.RoundBracketOpen:
                return('(');

            case TexSymbolKind.RoundBracketClose:
                return(')');

            case TexSymbolKind.SquareBracketOpen:
                return('[');

            case TexSymbolKind.SquareBracketClose:
                return(']');

            case TexSymbolKind.ModulusBracket:
                return('|');

                #endregion

                #region Relation Operators
            case TexSymbolKind.Equals:
                return('=');

            case TexSymbolKind.LessThan:
                return('<');

            case TexSymbolKind.GreaterThan:
                return('>');

                #endregion

                #region Binary Operators
            case TexSymbolKind.Plus:
                return('+');

            case TexSymbolKind.Minus:
                return('-');

            case TexSymbolKind.Star:
                return('*');

            case TexSymbolKind.Divide:
                return('/');

                #endregion

                #region Postfix Operators
            case TexSymbolKind.Factorial:
                return('!');

                #endregion

                #region Formatting
            case TexSymbolKind.Space:
                return(' ');

                #endregion

            default:
                return(null);
            }
        }
Beispiel #11
0
        private string GetLongSymbol(TexToken token)
        {
            switch (token.Symbol)
            {
                #region Values
            case TexSymbolKind.Text:
                return(string.Format("text{{{0}}}", (string)token.Value));

            case TexSymbolKind.GreekLetter:
                return((string)token.Value);

                #endregion

                #region Brackets
            case TexSymbolKind.CurlyBracketOpen:
                return("{");

            case TexSymbolKind.CurlyBracketClose:
                return("}");

            case TexSymbolKind.AngleBracketOpen:
                return("langle");

            case TexSymbolKind.AngleBracketClose:
                return("rangle");

            case TexSymbolKind.FloorBracketOpen:
                return("lfloor");

            case TexSymbolKind.FloorBracketClose:
                return("rfloor");

            case TexSymbolKind.CeilingBracketOpen:
                return("lceil");

            case TexSymbolKind.CeilingBracketClose:
                return("rceil");

            case TexSymbolKind.NormBracket:
                return("|");

                #endregion

                #region Relation Operators
            case TexSymbolKind.NotEquals:
                return("neq");

            case TexSymbolKind.DotEquals:
                return("doteq");

            case TexSymbolKind.Approximates:
                return("approx");

            case TexSymbolKind.Equivalent:
                return("equiv");

            case TexSymbolKind.LessThanOrEqualTo:
                return("leq");

            case TexSymbolKind.GreaterThanOrEqualTo:
                return("geq");

            case TexSymbolKind.MuchLessThan:
                return("ll");

            case TexSymbolKind.MuchGreaterThan:
                return("gg");

            case TexSymbolKind.Proportional:
                return("propto");

            case TexSymbolKind.Asymptotic:
                return("asymp");

            case TexSymbolKind.Bowtie:
                return("bowtie");

            case TexSymbolKind.Models:
                return("models");

            case TexSymbolKind.Precedes:
                return("prec");

            case TexSymbolKind.PrecedesOrEquals:
                return("preceq");

            case TexSymbolKind.Succedes:
                return("succ");

            case TexSymbolKind.SuccedesOrEquals:
                return("succeq");

            case TexSymbolKind.Congruent:
                return("cong");

            case TexSymbolKind.Similar:
                return("sim");

            case TexSymbolKind.SimilarOrEquals:
                return("simeq");

            case TexSymbolKind.Perpendicular:
                return("perp");

            case TexSymbolKind.Middle:
                return("mid");

            case TexSymbolKind.Subset:
                return("subset");

            case TexSymbolKind.SubsetOrEqualTo:
                return("subseteq");

            case TexSymbolKind.Superset:
                return("supset");

            case TexSymbolKind.SupersetOrEqualTo:
                return("supseteq");

            case TexSymbolKind.SquareSubset:
                return("sqsubset");

            case TexSymbolKind.SquareSubsetOrEqualTo:
                return("sqsubseteq");

            case TexSymbolKind.SquareSuperset:
                return("sqsupset");

            case TexSymbolKind.SquareSupersetOrEqualTo:
                return("sqsupseteq");

            case TexSymbolKind.Member:
                return("in");

            case TexSymbolKind.NotMember:
                return("nin");

            case TexSymbolKind.Contains:
                return("ni");

            case TexSymbolKind.NotContains:
                return("nni");

            case TexSymbolKind.Smile:
                return("smile");

            case TexSymbolKind.Frown:
                return("frown");

            case TexSymbolKind.VLineDash:
                return("vdash");

            case TexSymbolKind.DashVLine:
                return("dashv");

                #endregion

                #region Binary Operators
            case TexSymbolKind.PlusMinus:
                return("pm");

            case TexSymbolKind.MinusPlus:
                return("mp");

            case TexSymbolKind.Cross:
                return("times");

            case TexSymbolKind.Dot:
                return("cdot");

            case TexSymbolKind.Divide:
                return("div");

            case TexSymbolKind.Over:
                return("over");

                #endregion

                #region Bracketed Functions
            case TexSymbolKind.Fraction:
                return("frac");

            case TexSymbolKind.Binomial:
                return("binom");

            case TexSymbolKind.Root:
                return("sqrt");

                #endregion

                #region Functions
            case TexSymbolKind.Minimum:
                return("min");

            case TexSymbolKind.Maximum:
                return("max");

            case TexSymbolKind.GreatestCommonDenominator:
                return("gcd");

            case TexSymbolKind.LowestCommonMultiple:
                return("lcm");

            case TexSymbolKind.Exponent:
                return("exp");

            case TexSymbolKind.Log:
                return("log");

            case TexSymbolKind.NaturalLog:
                return("ln");

            case TexSymbolKind.Argument:
                return("arg");

            case TexSymbolKind.Limit:
                return("lim");

            case TexSymbolKind.LimitInferior:
                return("liminf");

            case TexSymbolKind.LimitSuperior:
                return("limsup");

            case TexSymbolKind.Sine:
                return("sin");

            case TexSymbolKind.Cosine:
                return("cos");

            case TexSymbolKind.Tangent:
                return("tan");

            case TexSymbolKind.Secant:
                return("sec");

            case TexSymbolKind.Cosecant:
                return("csc");

            case TexSymbolKind.Cotangent:
                return("cot");

            case TexSymbolKind.ArcSine:
                return("arcsin");

            case TexSymbolKind.ArcCosine:
                return("arccos");

            case TexSymbolKind.ArcTangent:
                return("arctan");

            case TexSymbolKind.ArcSecant:
                return("arcsec");

            case TexSymbolKind.ArcCosecant:
                return("arccsc");

            case TexSymbolKind.ArcCotangent:
                return("arccot");

            case TexSymbolKind.HypSine:
                return("sinh");

            case TexSymbolKind.HypCosine:
                return("cosh");

            case TexSymbolKind.HypTangent:
                return("tanh");

            case TexSymbolKind.HypSecant:
                return("sech");

            case TexSymbolKind.HypCosecant:
                return("csch");

            case TexSymbolKind.HypCotangent:
                return("coth");

            case TexSymbolKind.ArHypSine:
                return("arcsinh");

            case TexSymbolKind.ArHypCosine:
                return("arccosh");

            case TexSymbolKind.ArHypTangent:
                return("arctanh");

            case TexSymbolKind.ArHypSecant:
                return("arcsech");

            case TexSymbolKind.ArHypCosecant:
                return("arccsch");

            case TexSymbolKind.ArHypCotangent:
                return("arccoth");

            case TexSymbolKind.InlineModulo:
                return("bmod");

            case TexSymbolKind.IdentityModulo:
                return("pmod");

                #endregion

                #region Big Operators
            case TexSymbolKind.Sum:
                return("sum");

            case TexSymbolKind.Product:
                return("prod");

            case TexSymbolKind.Coproduct:
                return("coprod");

            case TexSymbolKind.Integral:
                return("int");

            case TexSymbolKind.DoubleIntegral:
                return("iint");

            case TexSymbolKind.TripleIntegral:
                return("iiint");

            case TexSymbolKind.QuadrupleIntegral:
                return("iiiint");

            case TexSymbolKind.NtupleIntegral:
                return("idotsint");

            case TexSymbolKind.ClosedIntegral:
                return("oint");

            case TexSymbolKind.ClosedDoubleIntegral:
                return("oiint");

            case TexSymbolKind.ClosedTripleIntegral:
                return("oiiint");

            case TexSymbolKind.ClosedQuadrupleIntegral:
                return("oiiiint");

            case TexSymbolKind.ClosedNtupleIntegral:
                return("oidotsint");

            case TexSymbolKind.BigOPlus:
                return("bigoplus");

            case TexSymbolKind.BigOTimes:
                return("bigotimes");

            case TexSymbolKind.BigODot:
                return("bigodot");

            case TexSymbolKind.BigCup:
                return("bigcup");

            case TexSymbolKind.BigCap:
                return("bigcap");

            case TexSymbolKind.BigCupPlus:
                return("bigcupplus");

            case TexSymbolKind.BigSquareCup:
                return("bigsqcup");

            case TexSymbolKind.BigSquareCap:
                return("bigsqcap");

            case TexSymbolKind.BigVee:
                return("bigveee");

            case TexSymbolKind.BigWedge:
                return("bigwedge");

                #endregion

                #region Formatting
            case TexSymbolKind.Separator:
                return(",");

            case TexSymbolKind.Left:
                return("left");

            case TexSymbolKind.Right:
                return("right");

                #endregion

            default:
                return(null);
            }
        }
Beispiel #12
0
        private void WriteNode(ComposedTokenStream tokenStream, TexExpressionNode node, ComposerState state)
        {
            var openBracketSymbol  = TexSymbolKind.Null;
            var closeBracketSymbol = TexSymbolKind.Null;

            if ((node.Symbol.IsBinaryOperator() || node.Symbol.IsRelationOperator()) &&
                !node.Symbol.IsRaiseOrLowerOperator())
            {
                // Check if current operator needs brackets because it has lower precedence than parent operator.
                if (node.Parent != null && !node.Parent.Symbol.IsRaiseOrLowerOperator())
                {
                    var nodePrecedence       = GetOperatorPrecedence(node);
                    var parentNodePrecedence = GetOperatorPrecedence(node.Parent);
                    if (nodePrecedence != -1 && parentNodePrecedence != -1 &&
                        nodePrecedence < parentNodePrecedence ||
                        (nodePrecedence == parentNodePrecedence &&
                         (node.Parent.Children.IndexOf(node) == 0 ^ node.Parent.Symbol.IsLeftAssociativeOperator())))
                    {
                        openBracketSymbol  = TexSymbolKind.RoundBracketOpen;
                        closeBracketSymbol = TexSymbolKind.RoundBracketClose;
                    }
                }
            }
            else if (node.Symbol.IsFunctionOperator() || node.Symbol.IsBigOperator())
            {
                openBracketSymbol  = TexSymbolKind.GroupOpen;
                closeBracketSymbol = TexSymbolKind.GroupClose;
            }

            if (openBracketSymbol == TexSymbolKind.Null)
            {
                if (node.Parent != null)
                {
                    // If any descendant node has more than one child, then group is needed.
                    bool needGroup = false;
                    var  curNode   = node;
                    while (curNode.Children.Count >= 1)
                    {
                        if (curNode.Children.Count > 1)
                        {
                            needGroup = true;
                            break;
                        }
                        curNode = curNode.Children[0];
                    }

                    if (needGroup)
                    {
                        switch (node.Parent.Symbol)
                        {
                        case TexSymbolKind.LowerToIndex:
                        case TexSymbolKind.RaiseToIndex:
                            openBracketSymbol  = TexSymbolKind.GroupOpen;
                            closeBracketSymbol = TexSymbolKind.GroupClose;
                            break;

                        case TexSymbolKind.Factorial:
                            openBracketSymbol  = TexSymbolKind.GroupOpen;
                            closeBracketSymbol = TexSymbolKind.GroupClose;
                            break;
                        }
                    }
                }
            }

            if (IsRightMostNode(node))
            {
                // No need to write brackets, since current operator will be written last.
                state.IsParentNodeGroupOpen = false;
                openBracketSymbol           = TexSymbolKind.Null;
                closeBracketSymbol          = TexSymbolKind.Null;
            }
            else if (!state.IsParentNodeGroupOpen && openBracketSymbol == TexSymbolKind.GroupOpen)
            {
                // Do not directly nest group brackets.
                state.IsParentNodeGroupOpen = true;
            }

            if (openBracketSymbol != TexSymbolKind.Null)
            {
                tokenStream.Write(TexToken.FromSymbol(openBracketSymbol));
            }

            if (node.Symbol.IsBinaryOperator() || node.Symbol.IsRelationOperator())
            {
                WriteInfixOperatorNode(tokenStream, node, state);
            }
            else if (node.Symbol.IsBracketedFunction())
            {
                WriteBracketedFunction(tokenStream, node, state);
            }
            else if (node.Symbol.IsFunctionOperator() || node.Symbol.IsBigOperator())
            {
                WritePrefixOperatorNode(tokenStream, node, state);
            }
            else if (node.Symbol.IsPostfixOperator())
            {
                WritePostfixOperatorNode(tokenStream, node, state);
            }
            else if (node.Symbol.IsValue())
            {
                WriteValueNode(tokenStream, node, state);
            }
            else
            {
                throw new TexComposerException(node,
                                               "Unrecognised node symbol.");
            }

            if (closeBracketSymbol != TexSymbolKind.Null)
            {
                tokenStream.Write(TexToken.FromSymbol(closeBracketSymbol));
            }
        }
Beispiel #13
0
 public void Write(TexToken token)
 {
     this.tokenList.AddLast(token);
 }
Beispiel #14
0
 private void WriteValueNode(ComposedTokenStream tokenStream, TexExpressionNode node,
                             ComposerState state)
 {
     tokenStream.Write(TexToken.FromValue(node.Symbol, node.Value));
 }
Beispiel #15
0
        private void WriteInfixOperatorNode(ComposedTokenStream tokenStream, TexExpressionNode node,
                                            ComposerState state)
        {
            if (node.Children.Count == 1)
            {
                // Node is actually term prefix.
                tokenStream.Write(TexToken.FromSymbol(node.Symbol));
                WriteNode(tokenStream, node.Children[0], state);
            }
            else if (node.Children.Count == 2)
            {
                WriteNode(tokenStream, node.Children[0], state);

                bool writeOpSymbol = true;
                var  padSymbol     = (this.PadPlusAndMinusSigns && node.Symbol.IsPlusOrMinusOperator()) ||
                                     node.Symbol.IsLongOperator();
                if (node.Symbol == TexSymbolKind.Dot)
                {
                    var checkNode = node.Children[1];
                    while (checkNode.Symbol == TexSymbolKind.Dot || checkNode.Symbol == TexSymbolKind.RaiseToIndex ||
                           checkNode.Symbol == TexSymbolKind.LowerToIndex)
                    {
                        checkNode = checkNode.Children[0];
                    }

                    // If terms can be multipled implicitly, do not write operator token.
                    switch (checkNode.Symbol)
                    {
                    case TexSymbolKind.Number:
                    case TexSymbolKind.Text:
                        break;

                    default:
                        if (checkNode.Children.Count <= 1)
                        {
                            writeOpSymbol = false;
                            padSymbol     = false;
                        }
                        break;
                    }
                }

                if (padSymbol)
                {
                    tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.Space));
                }
                if (writeOpSymbol)
                {
                    tokenStream.Write(TexToken.FromSymbol(node.Symbol));
                }
                if (padSymbol)
                {
                    tokenStream.Write(TexToken.FromSymbol(TexSymbolKind.Space));
                }

                WriteNode(tokenStream, node.Children[1], state);
            }
            else
            {
                throw new TexComposerException(node, string.Format(
                                                   errorMessageUnexpectedNumberOfChildren, node.Symbol, node.Children.Count));
            }
        }
 public TexParserException(TexToken token, string message)
     : base(token, message)
 {
     this.Token = token;
 }
 public TexParserException(TexToken token, ICollection <TexSymbolKind> expectedSymbolKinds)
     : this(token, string.Format(errorMessageInvalidSymbol,
                                 string.Join(", ", expectedSymbolKinds.Select(tokenKind => tokenKind.ToString()).ToArray())))
 {
 }
 public WriterException(TexToken token)
     : base(null)
 {
     this.Token = token;
 }
 public WriterException(TexToken token, string message)
     : base(message)
 {
     this.Token = token;
 }