/// <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++; }
/// <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; }
/// <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++; }
/// <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++; }
/// <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; }
/// <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); }
/// <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++; }
/// <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);
/// <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()); } } }
/// <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()); } } }