public ParseNode(TexToken token) : this() { this.Kind = ParseNodeKind.Token; this.Token = token; this.Children = new ParseNodeCollection(this); }
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)); } }
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)); }
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); }
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 }); } }
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)); } }
public ParseNode(TexToken token, IEnumerable <ParseNode> children) : this(token) { foreach (var childNode in children) { this.Children.Add(childNode); } }
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("}"); } }
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)); } }
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); } }
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); } }
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)); } }
public void Write(TexToken token) { this.tokenList.AddLast(token); }
private void WriteValueNode(ComposedTokenStream tokenStream, TexExpressionNode node, ComposerState state) { tokenStream.Write(TexToken.FromValue(node.Symbol, node.Value)); }
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; }