/// <summary> /// Custom-operator constructor. /// </summary> /// <param name="operators">Array of operator definitions. Currently, no sanity check is performed on the /// operator list, so make sure it is not ambiguous or anything.</param> public rsep(Operator[] operators) { { // copy all (unique) operator names , create lexer List<String> opSymbols = new List<String>(); for (int i = 0; i < operators.Length; i++) if (!opSymbols.Contains(operators[i].Symbol)) opSymbols.Add(operators[i].Symbol); m_lex = new rsel(opSymbols.ToArray()); } // sort operators based on precedence, store in m_operators m_operators = (Operator[])operators.Clone(); System.Array.Sort(m_operators, new OperatorPrecedenceComparer()); }
/// <summary> /// Adds an operator binding. If the operator was already in use, the old binding /// is overwritten. /// </summary> public void AddOperator(Operator newOp) { if ((newOp.Symbol == null) || (newOp.Symbol.Length == 0)) throw new Exception("Specification.AddOperator(): empty operator symbol"); // internal error? if ((newOp.FunctionName == null) || (newOp.FunctionName.Length == 0)) throw new Exception("Specification.AddOperator(): empty operator function"); // internal error? if ((newOp.NbArguments < 1) || (newOp.NbArguments > 2)) throw new Exception("Specification.AddOperator(): invalid number of arguments for operator '" + newOp.Symbol + "' bound to '" + newOp.FunctionName + "' (" + newOp.NbArguments + ")"); // internal error? int pos = -1; // check if operator is already in used for (int i = 0; i < m_operators.Count; i++) { Operator otherOp = m_operators[i]; bool prefixMatch = false; if ((newOp.NbArguments == 1) && (otherOp.IsPrefix == newOp.IsPrefix)) prefixMatch = true; if ((otherOp.NbArguments == newOp.NbArguments) && (otherOp.Symbol == newOp.Symbol) && prefixMatch) pos = i; } // if not already defined, create new position, otherwise overwrite the existing operator if (pos < 0) { pos = m_operators.Count; m_operators.Add(null); } m_operators[pos] = newOp; }