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)); } }
private int GetOperatorPrecedence(TexExpressionNode node) { // Higher value means higher precedence. switch (node.Symbol) { case TexSymbolKind.Plus: case TexSymbolKind.Minus: case TexSymbolKind.PlusMinus: case TexSymbolKind.MinusPlus: if (node.Children.Count == 1) { return(3); } return(2); case TexSymbolKind.Star: case TexSymbolKind.Dot: case TexSymbolKind.Cross: case TexSymbolKind.Divide: case TexSymbolKind.Fraction: case TexSymbolKind.InlineModulo: return(4); case TexSymbolKind.RaiseToIndex: case TexSymbolKind.LowerToIndex: return(5); default: if (node.Symbol.IsRelationOperator()) { return(1); } return(-1); } }
private static TexExpressionNode FromInfixOperatorParseNode(ParseNode parseNode) { if (parseNode.Children.Count == 1) { return(FromParseTree(parseNode.Children[0])); } else if (parseNode.Children.Count == 3) { var node = new TexExpressionNode(parseNode.Children[1].Token.Symbol); node.Children.Add(FromParseTree(parseNode.Children[0])); node.Children.Add(FromParseTree(parseNode.Children[2])); // If node is root of sub-expression and operator is left-recursive, then convert sub-tree from right // recursive to left recursive. if (!parseNode.IsSubExpression && node.Symbol.IsLtrInfixOperator()) { return(ConvertTreeToLeftRecursive(node, parseNode)); } else { return(node); } } throw new TexExpressionTreeBuilderException(parseNode, string.Format( errorMessageUnexpectedNumberOfChildren, parseNode.Kind, parseNode.Children.Count)); }
private static IEnumerable <TexExpressionNode> FromPrefixOperatorIndicesParseNode(ParseNode parseNode) { TexExpressionNode indexNode = null; if (parseNode.Children.Count == 0) { yield break; } else if (parseNode.Children.Count == 2) { indexNode = new TexExpressionNode(parseNode.Children[0].Token.Symbol); indexNode.Children.Add(FromParseTree(parseNode.Children[1])); yield return(indexNode); yield break; } else if (parseNode.Children.Count == 4) { indexNode = new TexExpressionNode(parseNode.Children[0].Token.Symbol); indexNode.Children.Add(FromParseTree(parseNode.Children[1])); yield return(indexNode); indexNode = new TexExpressionNode(parseNode.Children[2].Token.Symbol); indexNode.Children.Add(FromParseTree(parseNode.Children[3])); yield return(indexNode); yield break; } throw new TexExpressionTreeBuilderException(parseNode, string.Format( errorMessageUnexpectedNumberOfChildren, parseNode.Kind, parseNode.Children.Count)); }
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 TokenStream Write(TexExpressionNode node) { using (var tokenStream = new ComposedTokenStream()) { WriteNode(tokenStream, node, new ComposerState()); return(tokenStream); } }
private bool IsRightMostNode(TexExpressionNode node) { if (node.Parent == null) { return(true); } return(node.Parent.Children.IndexOf(node) == node.Parent.Children.Count && IsRightMostNode(node.Parent)); }
private static TexExpressionNode ConvertTreeToLeftRecursive(TexExpressionNode node, ParseNode parseNode) { Debug.Assert(node.Children.Count == 2); Debug.Assert(parseNode.Children.Count == 3); if (!parseNode.Children[2].IsSubExpression) { return(node); } var secondOperandNode = node.Children[1]; node.Children[1] = secondOperandNode.Children[0]; secondOperandNode.Children[0] = node; return(ConvertTreeToLeftRecursive(secondOperandNode, parseNode.Children[2])); }
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)); } }
public bool Equals(TexExpressionNode tree) { if (!this.Symbol.Equals(tree.Symbol)) { return(false); } if (this.Value != null && !this.Value.Equals(tree.Value)) { return(false); } if (!this.Children.Count.Equals(tree.Children.Count)) { return(false); } for (int i = 0; i < tree.Children.Count; i++) { if (!this.Children[i].Equals(tree.Children[i])) { return(false); } } return(true); }
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 static TokenStream CreateTokenStream(this TexExpressionNode tree) { var texComposer = new TexComposer(); return(texComposer.Write(tree)); }
private static TexExpressionNode FromPostfixOperatorIndicesParseNode(ParseNode parseNode, ParseNode childParseNode) { TexExpressionNode firstIndexNode = null; TexExpressionNode secondIndexNode = null; if (parseNode.Children.Count == 0) { return(FromParseTree(childParseNode)); } else if (parseNode.Children.Count == 2) { firstIndexNode = new TexExpressionNode(parseNode.Children[0].Token.Symbol); } else if (parseNode.Children.Count == 4) { firstIndexNode = new TexExpressionNode(parseNode.Children[0].Token.Symbol); secondIndexNode = new TexExpressionNode(parseNode.Children[2].Token.Symbol); } else { throw new TexExpressionTreeBuilderException(parseNode, string.Format( errorMessageUnexpectedNumberOfChildren, parseNode.Kind, parseNode.Children.Count)); } Debug.Assert(firstIndexNode == null || firstIndexNode.Symbol == TexSymbolKind.RaiseToIndex || firstIndexNode.Symbol == TexSymbolKind.LowerToIndex, "First index node is not RaiseToIndex or LowerToIndex."); Debug.Assert(secondIndexNode == null || secondIndexNode.Symbol == TexSymbolKind.RaiseToIndex || secondIndexNode.Symbol == TexSymbolKind.LowerToIndex, "Second index node is not RaiseToIndex or LowerToIndex."); TexExpressionNode outerIndexNode; TexExpressionNode innerIndexNode; if (secondIndexNode == null) { outerIndexNode = firstIndexNode; innerIndexNode = firstIndexNode; } else { // Use raised index as outer exprNode. if (firstIndexNode.Symbol == TexSymbolKind.RaiseToIndex) { outerIndexNode = firstIndexNode; innerIndexNode = secondIndexNode; } else { outerIndexNode = secondIndexNode; innerIndexNode = firstIndexNode; } outerIndexNode.Children.Add(innerIndexNode); } // Add child nodes, and then nodes for indices. innerIndexNode.Children.Add(FromParseTree(childParseNode)); firstIndexNode.Children.Add(FromParseTree(parseNode.Children[1])); if (secondIndexNode != null) { secondIndexNode.Children.Add(FromParseTree(parseNode.Children[3])); } return(outerIndexNode); }
public TexComposerException(TexExpressionNode node, string message) : base(message) { this.Node = node; }
public TexComposerException(TexExpressionNode node, ICollection <TexSymbolKind> expectedSymbolKinds) : this(node, string.Format(errorMessageInvalidSymbol, string.Join(", ", expectedSymbolKinds.Select(tokenKind => tokenKind.ToString()).ToArray()))) { }
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 static string CreateText(this TexExpressionNode tree) { return(CreateText(CreateTokenStream(tree))); }