This is the main class of teh Equationator. It contains one entire equation. Usage is to create one of these, add all the delegate methods, parse the equation string, and then call teh Solve function whenever need a result from it. A good idea would be to subclass this and have the child class set up all the delegate methods in it's constructor.
Пример #1
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //get the number out of the list
            try
            {
                ParamIndex = Convert.ToInt32(tokenList[curIndex].TokenText);
            }
            catch
            {
                throw new FormatException("Could not parse \"" + tokenList[curIndex].TokenText.ToString() + "\" into a parameter index.");
            }

            //double check that the index is valid
            if ((ParamIndex <= 0) || (ParamIndex > 9))
            {
                throw new FormatException("Parameter index must be between 1 - 9");
            }

            //increment the current index since we consumed the parameter index token
            curIndex++;
        }
Пример #2
0
        /// <summary>
        /// This method gets called when the token parser encounters a minus sign in front of a value.
        /// If the next token is a number, it will be changed to a negative number.
        /// If the next token is a funcion, param, or equation, an equation will be generated that multiplies the result by -1
        /// </summary>
        /// <returns>The negative token.</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">Owner.</param>
        public static BaseNode ParseNegativeToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            //verify that this is not the last token
            if (curIndex >= (tokenList.Count - 1))
            {
                throw new FormatException("Can't end an equation with an operator");
            }

            //check that the token is a minus sign
            if ("-" != tokenList[curIndex].TokenText)
            {
                throw new FormatException("Expected a value, but found an invalid operator instead");
            }

            //skip past the minus sign so we can get to the next token
            curIndex++;

            //create a number node, parse the next token into it
            BaseNode valueNode = BaseNode.ParseValueNode(tokenList, ref curIndex, owner);
            Debug.Assert(null != valueNode);

            //what did we get back?
            if (valueNode is NumberNode)
            {
                //the next node is a number, multiply it by minus one
                NumberNode myNumberNode = valueNode as NumberNode;
                myNumberNode.NumberValue *= -1.0f;
            }
            else
            {
                //ok the node was a function, param, or equation

                //create another equation to multiply that resdult by -1
                NumberNode negativeOne = new NumberNode();
                negativeOne.NumberValue = -1.0f;
                OperatorNode multiplyNode = new OperatorNode();
                multiplyNode.Operator = '*';

                //string it all together
                negativeOne.AppendNextNode(multiplyNode);
                multiplyNode.AppendNextNode(valueNode);

                //put that into an equation node and treeify it
                EquationNode myEquationNode = new EquationNode();
                myEquationNode.SubEquation = negativeOne.Treeify();
                Debug.Assert(null != myEquationNode.SubEquation);

                //set our result to the whole equation
                valueNode = myEquationNode;
            }

            //return it as the result
            return valueNode;
        }
Пример #3
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //get the number out of the list
            if (!float.TryParse(tokenList[curIndex].TokenText, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out _num))
            {
                throw new FormatException("Could not parse \"" + tokenList[curIndex].TokenText.ToString() + "\" into a number.");
            }

            //increment the current index since we consumed the number token
            curIndex++;
        }
Пример #4
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //get the function name
            FunctionName = tokenList[curIndex].TokenText;

            //check if the function is in the equation dictionary
            if (!owner.FunctionDictionary.ContainsKey(FunctionName))
            {
                throw new FormatException("Unknown function call: " + FunctionName);
            }

            //set the function delegate
            MyFunction = owner.FunctionDictionary[FunctionName];

            //increment the current index since we consumed the function name token
            curIndex++;
        }
Пример #5
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //get the function name
            FunctionName = tokenList[curIndex].TokenText;

            //check if the function is in the equation dictionary
            if (!owner.FunctionDictionary.ContainsKey(FunctionName))
            {
                throw new FormatException("Unknown function call: " + FunctionName);
            }

            //set the function delegate
            MyFunction = owner.FunctionDictionary[FunctionName];

            //increment the current index since we consumed the function name token
            curIndex++;
        }
Пример #6
0
        /// <summary>
        /// Parse a list of tokens into a linked list of equation nodes.
        /// This will sort it out into a flat equation
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index. When this function exits, will be incremented to the past any tokens consumed by this method</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        /// <returns>A basenode pointing at the head of a linked list parsed by this method</returns>
        static public BaseNode Parse(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //first get a value, which will be a number, function, param, or equation node
            BaseNode myNumNode = BaseNode.ParseValueNode(tokenList, ref curIndex, owner);

            Debug.Assert(null != myNumNode);

            //if there are any tokens left, get an operator
            if (curIndex < tokenList.Count)
            {
                BaseNode myOperNode = BaseNode.ParseOperNode(tokenList, ref curIndex, owner);

                if (null != myOperNode)
                {
                    //add that node to the end of the list
                    myNumNode.AppendNextNode(myOperNode);

                    //If it was able to pull an operator out, there has to be a number after it.
                    if (curIndex >= tokenList.Count)
                    {
                        throw new FormatException("Can't end an equation with an operator.");
                    }

                    //Recurse into the parse function and sort out the rest of the tokens
                    BaseNode nextNode = BaseNode.Parse(tokenList, ref curIndex, owner);
                    Debug.Assert(null != nextNode);

                    //add that node to the end of the list
                    myOperNode.AppendNextNode(nextNode);
                }
            }

            //return the head node that I found
            return(myNumNode);
        }
Пример #7
0
        /// <summary>
        /// Parse a list of tokens into a linked list of equation nodes.
        /// This will sort it out into a flat equation
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index. When this function exits, will be incremented to the past any tokens consumed by this method</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        /// <returns>A basenode pointing at the head of a linked list parsed by this method</returns>
        public static BaseNode Parse(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //first get a value, which will be a number, function, param, or equation node
            BaseNode myNumNode = BaseNode.ParseValueNode(tokenList, ref curIndex, owner);
            Debug.Assert(null != myNumNode);

            //if there are any tokens left, get an operator
            if (curIndex < tokenList.Count)
            {
                BaseNode myOperNode = BaseNode.ParseOperNode(tokenList, ref curIndex, owner);

                if (null != myOperNode)
                {
                    //add that node to the end of the list
                    myNumNode.AppendNextNode(myOperNode);

                    //If it was able to pull an operator out, there has to be a number after it.
                    if (curIndex >= tokenList.Count)
                    {
                        throw new FormatException("Can't end an equation with an operator.");
                    }

                    //Recurse into the parse function and sort out the rest of the tokens
                    BaseNode nextNode = BaseNode.Parse(tokenList, ref curIndex, owner);
                    Debug.Assert(null != nextNode);

                    //add that node to the end of the list
                    myOperNode.AppendNextNode(nextNode);
                }
            }

            //return the head node that I found
            return myNumNode;
        }
Пример #8
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //parse the equation into our subnode
            SubEquation = BaseNode.Parse(tokenList, ref curIndex, owner);

            //if some smart ass types in () the parse method wouldve returned null.
            //it should evaluate to 0 in that case, so create a number node and set the value.
            if (null == SubEquation)
            {
                NumberNode fakeNode = new NumberNode();
                fakeNode.NumberValue = 0.0f;
                SubEquation          = fakeNode;
            }
            Debug.Assert(null != SubEquation);

            //treeify the subequation so we can solve it
            SubEquation = SubEquation.Treeify();
            Debug.Assert(null != SubEquation);
        }
Пример #9
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //make sure the token text is the correct length
            if (tokenList[curIndex].TokenText.Length != 1)
            {
                throw new FormatException("operator text length can only be one character, was given " + tokenList[curIndex].TokenText);
            }

            //get the operator
            Operator = tokenList[curIndex].TokenText[0];

            //increment the current index since we consumed the operator token
            curIndex++;
        }
Пример #10
0
        /// <summary>
        /// Given a list of tokens and the index, get an operator node based on whatever is at that index.
        /// </summary>
        /// <returns>The oper node, or null if it hit the end of the equation.</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        static protected BaseNode ParseOperNode(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //what kind of token do I have at that index?
            switch (tokenList[curIndex].TypeOfToken)
            {
            case TokenType.Operator:
            {
                //ok create an operator node
                OperatorNode operNode = new OperatorNode();

                //parse into that node
                operNode.ParseToken(tokenList, ref curIndex, owner);

                //return the thing
                return(operNode);
            }

            case TokenType.CloseParen:
            {
                //close paren, just eat it and return null.  It means this equation is finished parsing
                curIndex++;
                return(null);
            }

            default:
            {
                //should just be close paren nodes in here, which we should never get
                throw new FormatException("Expected a \"operator\" token, but got a " + tokenList[curIndex].TypeOfToken.ToString());
            }
            }
        }
Пример #11
0
 /// <summary>
 /// Parse the specified tokenList and curIndex.
 /// overloaded by child types to do there own specific parsing.
 /// </summary>
 /// <param name="tokenList">Token list.</param>
 /// <param name="curIndex">Current index.</param>
 /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
 protected abstract void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner);
Пример #12
0
        /// <summary>
        /// Given a list of tokens and the index, get a node based on whatever is at that index
        /// </summary>
        /// <returns>The value node, will be a number, function, param, or equation node</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected static BaseNode ParseValueNode(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //what kind of token do I have at that index?
            switch (tokenList[curIndex].TypeOfToken)
            {
                case TokenType.Number:
                {
                    //awesome, that's nice and easy... just shove the text into a node as a number

                    //create the number node
                    NumberNode valueNode = new NumberNode();

                    //parse the text into the number node
                    valueNode.ParseToken(tokenList, ref curIndex, owner);

                    //return the number node as our result
                    return valueNode;
                }

                case TokenType.Param:
                {
                    //also not bad, grab the text as a parameter index and put in a node

                    //create the param node
                    ParamNode valueNode = new ParamNode();

                    //parse the parameter index into the node
                    valueNode.ParseToken(tokenList, ref curIndex, owner);

                    //return it as our result
                    return valueNode;
                }

                case TokenType.Function:
                {
                    //hmmm... need to get the delegate and put in a node?

                    //create the function node
                    FunctionNode valueNode = new FunctionNode();

                    //parse the function delegate into the node
                    valueNode.ParseToken(tokenList, ref curIndex, owner);

                    //return it as our result
                    return valueNode;
                }

                case TokenType.OpenParen:
                {
                    //ok don't panic...

                    //verify that this is not the last token
                    if (curIndex >= (tokenList.Count - 1))
                    {
                        throw new FormatException("Can't end an equation with an open paranthesis");
                    }

                    //move past this token, cuz nothing else to do with it
                    curIndex++;

                    //starting at the next token, start an equation node
                    EquationNode valueNode = new EquationNode();

                    //start parsing into the equation node
                    valueNode.ParseToken(tokenList, ref curIndex, owner);

                    //return it as the result
                    return valueNode;
                }

                case TokenType.Operator:
                {
                    //whoa, how did an operator get in here?  it better be a minus sign
                    return EquationNode.ParseNegativeToken(tokenList, ref curIndex, owner);
                }

                default:
                {
                    //should just be close paren nodes in here, which we should never get
                    throw new FormatException("Expected a \"value\" token, but got a " + tokenList[curIndex].TypeOfToken.ToString());
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Given a list of tokens and the index, get an operator node based on whatever is at that index.
        /// </summary>
        /// <returns>The oper node, or null if it hit the end of the equation.</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected static BaseNode ParseOperNode(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //what kind of token do I have at that index?
            switch (tokenList[curIndex].TypeOfToken)
            {
                case TokenType.Operator:
                {
                    //ok create an operator node
                    OperatorNode operNode = new OperatorNode();

                    //parse into that node
                    operNode.ParseToken(tokenList, ref curIndex, owner);

                    //return the thing
                    return operNode;
                }

                case TokenType.CloseParen:
                {
                    //close paren, just eat it and return null.  It means this equation is finished parsing
                    curIndex++;
                    return null;
                }

                default:
                {
                    //should just be close paren nodes in here, which we should never get
                    throw new FormatException("Expected a \"operator\" token, but got a " + tokenList[curIndex].TypeOfToken.ToString());
                }
            }
        }
Пример #14
0
        /// <summary>
        /// This method gets called when the token parser encounters a minus sign in front of a value.
        /// If the next token is a number, it will be changed to a negative number.
        /// If the next token is a funcion, param, or equation, an equation will be generated that multiplies the result by -1
        /// </summary>
        /// <returns>The negative token.</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">Owner.</param>
        public static BaseNode ParseNegativeToken(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            //verify that this is not the last token
            if (curIndex >= (tokenList.Count - 1))
            {
                throw new FormatException("Can't end an equation with an operator");
            }

            //check that the token is a minus sign
            if ("-" != tokenList[curIndex].TokenText)
            {
                throw new FormatException("Expected a value, but found an invalid operator instead");
            }

            //skip past the minus sign so we can get to the next token
            curIndex++;

            //create a number node, parse the next token into it
            BaseNode valueNode = BaseNode.ParseValueNode(tokenList, ref curIndex, owner);

            Debug.Assert(null != valueNode);

            //what did we get back?
            if (valueNode is NumberNode)
            {
                //the next node is a number, multiply it by minus one
                NumberNode myNumberNode = valueNode as NumberNode;
                myNumberNode.NumberValue *= -1.0f;
            }
            else
            {
                //ok the node was a function, param, or equation

                //create another equation to multiply that resdult by -1
                NumberNode negativeOne = new NumberNode();
                negativeOne.NumberValue = -1.0f;
                OperatorNode multiplyNode = new OperatorNode();
                multiplyNode.Operator = '*';

                //string it all together
                negativeOne.AppendNextNode(multiplyNode);
                multiplyNode.AppendNextNode(valueNode);

                //put that into an equation node and treeify it
                EquationNode myEquationNode = new EquationNode();
                myEquationNode.SubEquation = negativeOne.Treeify();
                Debug.Assert(null != myEquationNode.SubEquation);

                //set our result to the whole equation
                valueNode = myEquationNode;
            }

            //return it as the result
            return(valueNode);
        }
Пример #15
0
        /// <summary>
        /// Given a list of tokens and the index, get a node based on whatever is at that index
        /// </summary>
        /// <returns>The value node, will be a number, function, param, or equation node</returns>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        static protected BaseNode ParseValueNode(List <Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //what kind of token do I have at that index?
            switch (tokenList[curIndex].TypeOfToken)
            {
            case TokenType.Number:
            {
                //awesome, that's nice and easy... just shove the text into a node as a number

                //create the number node
                NumberNode valueNode = new NumberNode();

                //parse the text into the number node
                valueNode.ParseToken(tokenList, ref curIndex, owner);

                //return the number node as our result
                return(valueNode);
            }

            case TokenType.Param:
            {
                //also not bad, grab the text as a parameter index and put in a node

                //create the param node
                ParamNode valueNode = new ParamNode();

                //parse the parameter index into the node
                valueNode.ParseToken(tokenList, ref curIndex, owner);

                //return it as our result
                return(valueNode);
            }

            case TokenType.Function:
            {
                //hmmm... need to get the delegate and put in a node?

                //create the function node
                FunctionNode valueNode = new FunctionNode();

                //parse the function delegate into the node
                valueNode.ParseToken(tokenList, ref curIndex, owner);

                //return it as our result
                return(valueNode);
            }

            case TokenType.OpenParen:
            {
                //ok don't panic...

                //verify that this is not the last token
                if (curIndex >= (tokenList.Count - 1))
                {
                    throw new FormatException("Can't end an equation with an open paranthesis");
                }

                //move past this token, cuz nothing else to do with it
                curIndex++;

                //starting at the next token, start an equation node
                EquationNode valueNode = new EquationNode();

                //start parsing into the equation node
                valueNode.ParseToken(tokenList, ref curIndex, owner);

                //return it as the result
                return(valueNode);
            }

            case TokenType.Operator:
            {
                //whoa, how did an operator get in here?  it better be a minus sign
                return(EquationNode.ParseNegativeToken(tokenList, ref curIndex, owner));
            }

            default:
            {
                //should just be close paren nodes in here, which we should never get
                throw new FormatException("Expected a \"value\" token, but got a " + tokenList[curIndex].TypeOfToken.ToString());
            }
            }
        }
Пример #16
0
 /// <summary>
 /// Parse the specified tokenList and curIndex.
 /// overloaded by child types to do there own specific parsing.
 /// </summary>
 /// <param name="tokenList">Token list.</param>
 /// <param name="curIndex">Current index.</param>
 /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
 protected abstract void ParseToken(List <Token> tokenList, ref int curIndex, Equation owner);
Пример #17
0
        /// <summary>
        /// Parse the specified tokenList and curIndex.
        /// overloaded by child types to do there own specific parsing.
        /// </summary>
        /// <param name="tokenList">Token list.</param>
        /// <param name="curIndex">Current index.</param>
        /// <param name="owner">the equation that this node is part of.  required to pull function delegates out of the dictionary</param>
        protected override void ParseToken(List<Token> tokenList, ref int curIndex, Equation owner)
        {
            Debug.Assert(null != tokenList);
            Debug.Assert(null != owner);
            Debug.Assert(curIndex < tokenList.Count);

            //parse the equation into our subnode
            SubEquation = BaseNode.Parse(tokenList, ref curIndex, owner);

            //if some smart ass types in () the parse method wouldve returned null.
            //it should evaluate to 0 in that case, so create a number node and set the value.
            if (null == SubEquation)
            {
                NumberNode fakeNode = new NumberNode();
                fakeNode.NumberValue = 0.0f;
                SubEquation = fakeNode;
            }
            Debug.Assert(null != SubEquation);

            //treeify the subequation so we can solve it
            SubEquation = SubEquation.Treeify();
            Debug.Assert(null != SubEquation);
        }