public OperatorDescriptor(IBinaryOperatorType binaryOperatorType, OperatorAssociativity associativity, IEnumerable<string> operatorSymbols) { if (binaryOperatorType == null) { throw new ArgumentNullException("binaryOperatorType"); } this.binaryOperatorType = binaryOperatorType; this.associativity = associativity; if (operatorSymbols == null) { throw new ArgumentNullException("operatorSymbols"); } this.operatorSymbols = operatorSymbols.ToList().AsReadOnly(); }
private static Nodes.ParseTreeNode CombineBinaryOperators(List<Nodes.ParseTreeNode> operands, List<Token> operators, IBinaryOperatorType operatorType, OperatorAssociativity associativity) { if (operators.Count + 1 != operands.Count) { throw new InvalidOperationException("You cannot combine binary operators if the number of operands is not equal to the number of operators plus one."); } // If there is just one operand, just return it. if (operands.Count == 1) { return operands[0]; } // If there are just two operands, all associativity rules are equivalent. if (operands.Count == 2) { return new Nodes.BinaryOperatorNode { Left = operands[0], Operator = operators[0], OperatorType = operatorType, Right = operands[1], }; } // If there are more than two operands and the operator is non-associative, throw a parse error. if (associativity == OperatorAssociativity.NonAssociative) { throw new ParseException("The operator '" + operatorType.Name + "' is non-associative and therefore may not be used in groups of 3 or more without using parentheses for clarification.", operators[2].Span.Start); } // Otherwise, build up the tree with the proper associativity. if (associativity == OperatorAssociativity.LeftAssociative) { Nodes.ParseTreeNode accumulator = null; for (int i = 0; i < operands.Count; i++) { if (accumulator == null) { accumulator = operands[i]; } else { var thenNode = new Nodes.BinaryOperatorNode { Left = accumulator, Operator = operators[i - 1], OperatorType = operatorType, Right = operands[i], }; accumulator = thenNode; } } return accumulator; } else { Nodes.ParseTreeNode accumulator = null; for (int i = operands.Count - 1; i >= 0; i--) { if (accumulator == null) { accumulator = operands[i]; } else { var thenNode = new Nodes.BinaryOperatorNode { Left = operands[i], Operator = operators[i], OperatorType = operatorType, Right = accumulator }; accumulator = thenNode; } } return accumulator; } }