public IIFShortCircuit(TokenItem Parent) { parent = Parent; rpn_condition = new Evaluation.Engine.Support.ExQueue <TokenItem>(); rpn_true = new Evaluation.Engine.Support.ExQueue <TokenItem>(); rpn_false = new Evaluation.Engine.Support.ExQueue <TokenItem>(); }
public IIFShortCircuit(TokenItem Parent) { parent = Parent; rpn_condition = new Support.ExQueue<TokenItem>(); rpn_true = new Support.ExQueue<TokenItem>(); rpn_false = new Support.ExQueue<TokenItem>(); }
public TokenItem Evaluate(out string ErrorMsg) { // initialize the outgoing variables ErrorMsg = ""; // local variables string result = ""; // get the parent token object Token token = this.Parent.Parent.Parent; // create the evaluator object to evaluate the condition Evaluation.Engine.Evaluate.Evaluator eval = null; try { eval = new Evaluation.Engine.Evaluate.Evaluator(token); } catch (Exception err) { ErrorMsg = "Failed to evaluation the condition in IIFShortCircuit(): " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(null); } // evaluate the condition if (eval.Evaluate(this.rpn_condition, out result, out ErrorMsg) == false) { return(null); } // determine if we need to run the "true" or "false" result Support.ExQueue <TokenItem> resultQueue = null; if (result.Trim().ToLower() == "true") { // evaluate the true parameter resultQueue = this.rpn_true; } else { // evaluate the false parameter resultQueue = this.rpn_false; } // do the final evaluation if (eval.Evaluate(resultQueue, out result, out ErrorMsg) == false) { return(null); } // all done return(new TokenItem(result, TokenType.Token_Operand, TokenDataType.Token_DataType_String, false)); }
/// <summary> /// This new evaluate function includes support to assignment and short circuit of the IIF[] operand function /// </summary> /// <param name="RPNQueue"></param> /// <param name="sValue"></param> /// <param name="ErrorMsg"></param> /// <returns></returns> public bool Evaluate(Support.ExQueue <Parser.TokenItem> RPNQueue, out string sValue, out string ErrorMsg) { // initialize the outgoing variable ErrorMsg = ""; sValue = ""; // reset the results in the token token.LastEvaluationResult = ""; // create a stop watch to time the evaluation //System.Diagnostics.Stopwatch evalTime = System.Diagnostics.Stopwatch.StartNew(); // make sure the otkens are valid if (token.AnyErrors == true) { // the token already has an error, return the token error as the evaluator error message ErrorMsg = token.LastErrorMessage; XapLogger.Instance.Error(ErrorMsg); return(false); } // create the evaluation stack Support.ExStack <Parser.TokenItem> eval = new Support.ExStack <Parser.TokenItem>(token.TokenItems.Count); // start looping through the tokens int count = RPNQueue.Count; int index = 0; // the index of the curent token item in the rpn queue while (index < count) { // get the next token item Parser.TokenItem item = RPNQueue[index]; index++; if (item.TokenDataType == Evaluation.Engine.Parser.TokenDataType.Token_DataType_Variable) { #region Token_DataType_Variable // determine if we need to assign the variable represented by the token // or the rule syntax is doing the assignment if (item.WillBeAssigned == false) { // The rule syntax is not doing the assignment, we are doing it. // lookup the value of the variable and push it onto the evaluation stack if (token.Variables.VariableExists(item.TokenName) == true) { // the variable exists, push it on the stack eval.Push(new Parser.TokenItem(token.Variables[item.TokenName].VariableValue, Parser.TokenType.Token_Operand, item.InOperandFunction)); } else { // the variable does not exist...push an empty string on the stack eval.Push(new Parser.TokenItem("", Parser.TokenType.Token_Operand, item.InOperandFunction)); } } else { // the rule syntax is doing the assignment, add the token item to the evaluation stack eval.Push(item); } #endregion } else if (item.TokenType == Evaluation.Engine.Parser.TokenType.Token_Operator) { #region Token_Operator // pop 2 items off the stack and perform the operation // push the result back onto the evaluation stack Parser.TokenItem rightOperand = null; Parser.TokenItem leftOperand = null; try { if (eval.Count > 0) { rightOperand = eval.Pop(); } if (eval.Count > 0) { leftOperand = eval.Pop(); } } catch (Exception err) { ErrorMsg = "Error in Evaluation.Engine.Evaluator.Evaluate() while popping 2 tokens for an operator: " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(false); } // double check that we got the tokens before we evaluate if (rightOperand == null) { ErrorMsg = "Failed to evaluate the rule expression: The right operand token is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } if (leftOperand == null) { ErrorMsg = "Failed to evaluate the rule expression: The left operand token is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } // process the operator try { Parser.TokenItem result = null; if (EvaluateTokens(leftOperand, rightOperand, item, out result, out ErrorMsg) == false) { return(false); } else { // double check that we got a result if (result == null) { ErrorMsg = "Failed to evaluate the rule expression: The result of an operator is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } else { eval.Push(result); } } } catch (Exception err) { ErrorMsg = "Failed to evaluate the rule expression: The result of an operator threw an error: " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(false); } #endregion } else if (item.TokenType == Evaluation.Engine.Parser.TokenType.Token_Operand_Function_Stop) { #region Token_Operand_Function_Stop // find the start of the function by popping off items // evaluate the function and push the result back onto the evaluation stack // start popping items from the evaluation stack // until we get the start of the of the operand function int evalCount = eval.Count; Parser.TokenItems parameters = new Parser.TokenItems(token); try { for (int j = 0; j < evalCount; j++) { Parser.TokenItem opItem = eval.Pop(); if (opItem.TokenType == Evaluation.Engine.Parser.TokenType.Token_Operand_Function_Start) { // we found the start of the operand function; let's evaluate it Parser.TokenItem result = null; EvaluateOperandFunction(opItem, parameters, out result, out ErrorMsg); //if (EvaluateOperandFunction(opItem, parameters, out result, out ErrorMsg) == false) // return false; //else //{ // make sure we got a result if (result == null) { ErrorMsg = "Failed to evaluate the rule expression: The result of an operand function is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } else { eval.Push(result); } //} break; } else if (opItem.TokenType != Evaluation.Engine.Parser.TokenType.Token_Operand_Function_Delimiter) { // we have a parameter to the operand function parameters.AddToFront(opItem); } } } catch (Exception err) { ErrorMsg = "Failed to evaluate the rule expression: The evaluation of an operand function threw an error: " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(false); } #endregion } else if (item.TokenType == Evaluation.Engine.Parser.TokenType.Token_Assignemt_Start) { #region Token_Assignment_Start // assign the value to the variable // pop 2 items off the stack - save the value into the variable Parser.TokenItem rightOperand = null; Parser.TokenItem leftOperand = null; try { if (eval.Count > 0) { rightOperand = eval.Pop(); } if (eval.Count > 0) { leftOperand = eval.Pop(); } } catch (Exception err) { ErrorMsg = "Error in Evaluation.Engine.Evaluator.Evaluate() while popping 2 tokens for an operator: " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(false); } // double check that we got the tokens before we evaluate if (rightOperand == null) { ErrorMsg = "Failed to evaluate the rule expression: The right operand token is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } if (leftOperand == null) { ErrorMsg = "Failed to evaluate the rule expression: The left operand token is null: There may be an issue with the rule syntax."; XapLogger.Instance.Error(ErrorMsg); return(false); } // look for the variable and assign the value to it if (token.Variables.VariableExists(leftOperand.TokenName) == true) { // the variable exists, push it on the stack token.Variables[leftOperand.TokenName].VariableValue = rightOperand.TokenName; } else { // failed to find the variable....this is an error ErrorMsg = "Failed to evaluate the rule expression: Failed to find the variable '" + leftOperand.TokenName + "' for the assignment."; XapLogger.Instance.Error(ErrorMsg); return(false); } #endregion } else if (item.TokenType == Evaluation.Engine.Parser.TokenType.Token_Operand_Function_Start) { #region New Short Circuit Code // we are only short circuiting the IIF[] operand function if (item.TokenName.Trim().ToLower() != "iif[") { // add the token to the evaluation stack eval.Push(item); } else { // we found the iif statement. // see if the iff[] operand function allows for short circuiting if (item.CanShortCircuit == false) { // no short circuiting, add it to the evaluation stack eval.Push(item); } else { //////////////////////////////////////////////// // We can short circuit this iif[] statement // //////////////////////////////////////////////// Parser.TokenItem result = item.ShortCircuit.Evaluate(out ErrorMsg); if (result == null) { // there was an error doing the short circuit return(false); } else { // we successfully did the short circuit eval.Push(result); // increment the index so we skip the ] which should be the next token index++; } } } #endregion } else { // push the item on the evaluation stack eval.Push(item); } } if (eval.Count == 1) { // just 1 item on the stack; should be our answer try { Parser.TokenItem final = eval.Pop(); sValue = final.TokenName; // set the results in the token token.LastEvaluationResult = sValue; } catch (Exception err) { ErrorMsg = "Failed to evaluate the rule expression after all the tokens have been considered: " + err.Message; XapLogger.Instance.Error(ErrorMsg); return(false); } } else if (eval.Count == 0) { // there is no result in the evaluation stack because it my have been assigned // do nothing here } else { ErrorMsg = "Invalid Rule Syntax"; XapLogger.Instance.Error(ErrorMsg); return(false); } // stop the timer //evalTime.Stop(); //tokenEvalTime = evalTime.Elapsed.TotalMilliseconds; // token.LastEvaluationTime = tokenEvalTime; // set this evaluation time in the token object. return(true); }
private void MakeRPNQueue() { /* While there are tokens to be read: Read a token. If the token is a number, then add it to the output queue. If the token is a function token, then push it onto the stack. If the token is a function argument separator (e.g., a comma): Until the topmost element of the stack is a left parenthesis, pop the element onto the output queue. If no left parentheses are encountered, either the separator was misplaced or parentheses were mismatched. If the token is an operator, o1, then: while there is an operator, o2, at the top of the stack, and either o1 is associative or left-associative and its precedence is less than (lower precedence) or equal to that of o2, or o1 is right-associative and its precedence is less than (lower precedence) that of o2, pop o2 off the stack, onto the output queue; push o1 onto the operator stack. If the token is a left parenthesis, then push it onto the stack. If the token is a right parenthesis: Until the token at the top of the stack is a left parenthesis, pop operators off the stack onto the output queue. Pop the left parenthesis from the stack, but not onto the output queue. If the token at the top of the stack is a function token, pop it and onto the output queue. If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. When there are no more tokens to read: While there are still operator tokens in the stack: If the operator token on the top of the stack is a parenthesis, then there are mismatched parenthesis. Pop the operator onto the output queue. Exit. */ // set the last error message lastErrorMessage = ""; // make sure we have parsed tokens if (this.tokenItems.Count == 0) { lastErrorMessage = "No tokens to add to the RPN stack"; return; } #region Version 4 ////////////////////////////////////////////////////////////////////////// // This version supports short curcuiting the iif[] operand function ////////////////////////////////////////////////////////////////////////// // create the output queue...This is the final queue that is exposed through the public property rpn_queue = new Support.ExQueue<TokenItem>(tokenItems.Count); // create the operator stack Support.ExStack<TokenItem> operators = new Support.ExStack<TokenItem>(); // create the operator stack for operators Support.ExStack<TokenItem> param_operators = new Support.ExStack<TokenItem>(); // create a temporary queue for expressions that are in operand functions Support.ExQueue<TokenItem> param_queue = new Support.ExQueue<TokenItem>(); // local variables //int count = 0; bool startedShortCircuit = false; // indicates if short circuit has started TokenItem shortCircuitItem = null; // pointer to the short circuit item IIFShortCircuitState shortCircuitState = IIFShortCircuitState.ShortCircuit_Condition; // the current parameter in the short circuit iif[] operand int matchingSquare = 0; // used to track the number of closing square parenthesis untile the end of the short circuit item. // create a "fake" delimiter token item Parser.TokenItem delimiter = new TokenItem(",", TokenType.Token_Operand_Function_Delimiter, false); // loop through all the token items foreach (TokenItem item in tokenItems) { System.Diagnostics.Debug.WriteLine(item.TokenName); switch (item.TokenType) { case TokenType.Token_Close_Parenthesis: #region Token_Close_Parenthesis if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // start peeking at the top operator do { if (param_operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard param_operators.Pop(); break; } else { // pop the operator and push it on the queue param_queue.Add(param_operators.Pop()); } if (param_operators.Count == 0) break; } while (true); } #endregion } else { #region Operator Stack if (operators.Count > 0) { // start peeking at the top operator do { System.Diagnostics.Debug.WriteLine(" Peek = " + operators.Peek().TokenName); // see what is on top of the operator stack if (operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard operators.Pop(); break; } else { // pop the operator and push it on the queue rpn_queue.Add(operators.Pop()); } if (operators.Count == 0) break; } while (true); } #endregion } #endregion break; case TokenType.Token_Open_Parenthesis: #region Token_Open_Parenthesis if (item.InOperandFunction == true) { #region Parameter Operator Stack // add open parenthesis to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack // add open parenthesis to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Operand: #region Token_Operand if (item.InOperandFunction == true) { #region Operand Queue param_queue.Add(item); // if token is an operand, then write it to output. #endregion } else { #region Operand Queue rpn_queue.Add(item); // if token is an operand, then write it to output. #endregion } #endregion break; case TokenType.Token_Operand_Function_Delimiter: #region Token_Operand_Function_Delimiter // pop the operators from the parameter stack util it's empty or we get a delimiter do { // check if the parameters operator stack is empty if (param_operators.Count == 0) break; // pop an item from the stack Parser.TokenItem opItem = param_operators.Pop(); // if the item is a delimiter...discard it and exit loop if (opItem.TokenType == TokenType.Token_Operand_Function_Delimiter) break; // add the item to the paramter queue param_queue.Add(opItem); } while (true); // start removing items from the paraemters queue and add them to the RPN queue // unill it's empty or we access an operand function start do { // see if the parameter queue is empty if (param_queue.Count == 0) break; // get the item from the queue Parser.TokenItem qItem = param_queue.Dequeue(); // add the item to the appropriate rpn queue if (startedShortCircuit == true) { if (qItem.TokenName.Trim().ToLower() != "iif[") { // we are in short circuit mode switch (shortCircuitState) { case IIFShortCircuitState.ShortCircuit_Condition: shortCircuitItem.ShortCircuit.RPNCondition.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_False: shortCircuitItem.ShortCircuit.RPNFalse.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_True: shortCircuitItem.ShortCircuit.RPNTrue.Add(qItem); break; } } } else rpn_queue.Add(qItem); // if the qItem is the start of another operand function, then we are done if (startedShortCircuit == false) { if (qItem.TokenType == TokenType.Token_Operand_Function_Start) break; } } while (true); // push the delimiter on the parameter operator stack param_operators.Push(item); // add the delimiter to the queue if (startedShortCircuit == true) { if (matchingSquare == 0) { // we are in short circuit mode switch (shortCircuitState) { case IIFShortCircuitState.ShortCircuit_Condition: shortCircuitState = IIFShortCircuitState.ShortCircuit_True; break; case IIFShortCircuitState.ShortCircuit_False: // don't change state break; case IIFShortCircuitState.ShortCircuit_True: shortCircuitState = IIFShortCircuitState.ShortCircuit_False; break; } } } else rpn_queue.Add(item); #endregion break; case TokenType.Token_Operand_Function_Start: #region Token_Operand_Function_Start if (item.InOperandFunction == true) { if (item.CanShortCircuit == true) { // add the item to the "regular" queue rpn_queue.Add(item); } else { #region Parameter Operand Queue param_queue.Add(item); // whenever we add a new operand function to the parameter queue, // add a "fake" delimiter to the parameter operator queue param_operators.Push(delimiter); #endregion } } else { #region Operand Queue rpn_queue.Add(item); // if token is an operand function, then write it to output. #endregion } // check if the item is a short circuit item if (item.CanShortCircuit == true) { // start a new short circuit startedShortCircuit = true; shortCircuitItem = item; shortCircuitState = IIFShortCircuitState.ShortCircuit_Condition; } else { matchingSquare++; // we have an operand function in a short citcuit IIF[] operand function } #endregion break; case TokenType.Token_Operand_Function_Stop: #region Token_Operand_Function_Stop if (item.InOperandFunction == true) { #region Parameter Queue // pop the operators from the parameter stack util it's empty or we get a delimiter do { // check if the parameters operator stack is empty if (param_operators.Count == 0) break; // pop an item from the stack Parser.TokenItem opItem = param_operators.Pop(); // if the item is a delimiter...discard it and exit loop if (opItem.TokenType == TokenType.Token_Operand_Function_Delimiter) break; // add the item to the paramter queue param_queue.Add(opItem); } while (true); // add the square bracket to the queue param_queue.Add(item); // start removing items from the paraemters queue and add them to the RPN queue // unill it's empty or we access an operand function start do { // see if the parameter queue is empty if (param_queue.Count == 0) break; // get the item from the queue Parser.TokenItem qItem = param_queue.Dequeue(); if (startedShortCircuit == true) { // we may be at the end of the short circuit....double check the state if ((matchingSquare == 0) && (shortCircuitState != IIFShortCircuitState.ShortCircuit_False)) { // this is a problem, we should be on the false condition by now. lastErrorMessage = "Error parsing the iif[] short circuit operand function: Invalid format: Expecting the false condition"; return; } if (qItem.TokenType == TokenType.Token_Operand_Function_Stop) { if (matchingSquare == 0) { // the stop token will go in the "regualar" queue rpn_queue.Add(qItem); } else { // this clocing token is for an operand function embedded in the iif[] short circuit. switch (shortCircuitState) { case IIFShortCircuitState.ShortCircuit_Condition: shortCircuitItem.ShortCircuit.RPNCondition.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_False: shortCircuitItem.ShortCircuit.RPNFalse.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_True: shortCircuitItem.ShortCircuit.RPNTrue.Add(qItem); break; } } } else { //shortCircuitItem.ShortCircuit.RPNFalse.DeleteOnSubmit(qItem); // this clocing token is for an operand function embedded in the iif[] short circuit. switch (shortCircuitState) { case IIFShortCircuitState.ShortCircuit_Condition: shortCircuitItem.ShortCircuit.RPNCondition.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_False: shortCircuitItem.ShortCircuit.RPNFalse.Add(qItem); break; case IIFShortCircuitState.ShortCircuit_True: shortCircuitItem.ShortCircuit.RPNTrue.Add(qItem); break; } } } else rpn_queue.Add(qItem); // if the qItem is the end of an operand function, then we are done if (qItem.TokenType == TokenType.Token_Operand_Function_Stop) break; } while (true); if (startedShortCircuit == true) { if (matchingSquare == 0) { // we are done with the short circuiting startedShortCircuit = false; shortCircuitItem = null; shortCircuitState = IIFShortCircuitState.ShortCircuit_Condition; } else matchingSquare--; } #endregion } else { #region Operand Queue rpn_queue.Add(item); // if token is an operand function, then write it to output. #endregion } #endregion break; case TokenType.Token_Operator: #region Token_Operator if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= param_operators.Peek().OrderOfOperationPrecedence) { param_queue.Add(param_operators.Pop()); } else break; if (param_operators.Count == 0) break; } while (true); } // push the token to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack if (operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.Add(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Assignemt_Start: #region Token_Assignemt_Start if (operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.Add(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion break; case TokenType.Token_Assignment_Stop: #region Token_Assignment_Stop // start popping items from the operator stack until we find the assignemtn start if (operators.Count > 0) { // peek at the top item of the operator stack do { TokenItem t1 = operators.Pop(); rpn_queue.Add(t1); if (t1.TokenType == TokenType.Token_Assignemt_Start) { // we are all don popping operators break; } if (operators.Count == 0) break; } while (true); } #endregion break; } } // pop the remaining operators int opCount = operators.Count; for (int i = 0; i < opCount; i++) rpn_queue.Add(operators.Pop()); #endregion #region Version 3 ////////////////////////////////////////////////////////////////////////// // This version is working good...however, it does not include // support for short curcuiting the iif[] operand functions ////////////////////////////////////////////////////////////////////////// /* // create the output queue...This is the final queue that is exposed through the public property rpn_queue = new Support.ExQueue<TokenItem>(tokenItems.Count); // create the operator stack Support.ExStack<TokenItem> operators = new Support.ExStack<TokenItem>(); // create the operator stack for operators Support.ExStack<TokenItem> param_operators = new Support.ExStack<TokenItem>(); // create a temporary queue for expressions that are in operand functions Support.ExQueue<TokenItem> param_queue = new Support.ExQueue<TokenItem>(); // local variables int count = 0; // create a "fake" delimiter token item Parser.TokenItem delimiter = new TokenItem(",", TokenType.Token_Operand_Function_Delimiter, false); // loop through all the token items foreach (TokenItem item in tokenItems) { System.Diagnostics.Debug.WriteLine(item.TokenName); switch (item.TokenType) { case TokenType.Token_Close_Parenthesis: #region Token_Close_Parenthesis if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // start peeking at the top operator do { if (param_operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard param_operators.Pop(); break; } else { // pop the operator and push it on the queue param_queue.DeleteOnSubmit(param_operators.Pop()); } if (param_operators.Count == 0) break; } while (true); } #endregion } else { #region Operator Stack if (operators.Count > 0) { // start peeking at the top operator do { System.Diagnostics.Debug.WriteLine(" Peek = " + operators.Peek().TokenName); // see what is on top of the operator stack if (operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard operators.Pop(); break; } else { // pop the operator and push it on the queue rpn_queue.DeleteOnSubmit(operators.Pop()); } if (operators.Count == 0) break; } while (true); } #endregion } #endregion break; case TokenType.Token_Open_Parenthesis: #region Token_Open_Parenthesis if (item.InOperandFunction == true) { #region Parameter Operator Stack // add open parenthesis to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack // add open parenthesis to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Operand: #region Token_Operand if (item.InOperandFunction == true) { #region Operand Queue param_queue.DeleteOnSubmit(item); // if token is an operand, then write it to output. #endregion } else { #region Operand Queue rpn_queue.DeleteOnSubmit(item); // if token is an operand, then write it to output. #endregion } #endregion break; case TokenType.Token_Operand_Function_Delimiter: #region Token_Operand_Function_Delimiter // pop the operators from the parameter stack util it's empty or we get a delimiter do { // check if the parameters operator stack is empty if (param_operators.Count == 0) break; // pop an item from the stack Parser.TokenItem opItem = param_operators.Pop(); // if the item is a delimiter...discard it and exit loop if (opItem.TokenType == TokenType.Token_Operand_Function_Delimiter) break; // add the item to the paramter queue param_queue.DeleteOnSubmit(opItem); } while (true); // start removing items from the paraemters queue and add them to the RPN queue // unill it's empty or we access an operand function start do { // see if the parameter queue is empty if (param_queue.Count == 0) break; // get the item from the queue Parser.TokenItem qItem = param_queue.Dequeue(); rpn_queue.DeleteOnSubmit(qItem); // if the qItem is the start of another operand function, then we are done if (qItem.TokenType == TokenType.Token_Operand_Function_Start) break; } while (true); // push the delimiter on the parameter operator stack param_operators.Push(item); // add the delimiter to the queue rpn_queue.DeleteOnSubmit(item); #endregion break; case TokenType.Token_Operand_Function_Start: #region Token_Operand_Function_Start if (item.InOperandFunction == true) { #region Parameter Operand Queue param_queue.DeleteOnSubmit(item); // whenever we add a new operand function to the parameter queue, // add a "fake" delimiter to the parameter operator queue param_operators.Push(delimiter); #endregion } else { #region Operand Queue rpn_queue.DeleteOnSubmit(item); // if token is an operand function, then write it to output. #endregion } #endregion break; case TokenType.Token_Operand_Function_Stop: #region Token_Operand_Function_Stop if (item.InOperandFunction == true) { #region Parameter Queue // pop the operators from the parameter stack util it's empty or we get a delimiter do { // check if the parameters operator stack is empty if (param_operators.Count == 0) break; // pop an item from the stack Parser.TokenItem opItem = param_operators.Pop(); // if the item is a delimiter...discard it and exit loop if (opItem.TokenType == TokenType.Token_Operand_Function_Delimiter) break; // add the item to the paramter queue param_queue.DeleteOnSubmit(opItem); } while (true); // add the square bracket to the queue param_queue.DeleteOnSubmit(item); // start removing items from the paraemters queue and add them to the RPN queue // unill it's empty or we access an operand function start do { // see if the parameter queue is empty if (param_queue.Count == 0) break; // get the item from the queue Parser.TokenItem qItem = param_queue.Dequeue(); rpn_queue.DeleteOnSubmit(qItem); // if the qItem is the end of an operand function, then we are done if (qItem.TokenType == TokenType.Token_Operand_Function_Stop) break; } while (true); #endregion } else { #region Operand Queue rpn_queue.DeleteOnSubmit(item); // if token is an operand function, then write it to output. #endregion } #endregion break; case TokenType.Token_Operator: #region Token_Operator if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= param_operators.Peek().OrderOfOperationPrecedence) { param_queue.DeleteOnSubmit(param_operators.Pop()); } else break; if (param_operators.Count == 0) break; } while (true); } // push the token to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack if (operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.DeleteOnSubmit(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Assignemt_Start: #region Token_Assignemt_Start if (operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.DeleteOnSubmit(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion break; case TokenType.Token_Assignment_Stop: #region Token_Assignment_Stop // start popping items from the operator stack until we find the assignemtn start if (operators.Count > 0) { // peek at the top item of the operator stack do { TokenItem t1 = operators.Pop(); rpn_queue.DeleteOnSubmit(t1); if (t1.TokenType == TokenType.Token_Assignemt_Start) { // we are all don popping operators break; } if (operators.Count == 0) break; } while (true); } #endregion break; } } // pop the remaining operators int opCount = operators.Count; for (int i = 0; i < opCount; i++) rpn_queue.DeleteOnSubmit(operators.Pop()); */ #endregion #region Version 2 /* // create the output queue rpn_queue = new Support.ExQueue<TokenItem>(tokenItems.Count); // create the operator stack Support.ExStack<TokenItem> operators = new Support.ExStack<TokenItem>(); // create the operator stack for operators Support.ExStack<TokenItem> param_operators = new Support.ExStack<TokenItem>(); // create a temporary queue for expressions that are in operand functions Support.ExQueue<TokenItem> parameter_queue = new Support.ExQueue<TokenItem>(); // local variables int count = 0; // loop through all the token items foreach (TokenItem item in tokenItems) { //System.Diagnostics.Debug.WriteLine(item.TokenName); switch (item.TokenType) { case TokenType.Token_Close_Parenthesis: #region Parenthesis Handling if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // start peeking at the top operator do { // see what is on top of the operator stack if (param_operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard param_operators.Pop(); break; } else { // pop the operator and push it on the queue parameter_queue.DeleteOnSubmit(param_operators.Pop()); } if (param_operators.Count == 0) break; } while (true); } #endregion } else { #region Operator Stack if (operators.Count > 0) { // start peeking at the top operator do { // see what is on top of the operator stack if (operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard operators.Pop(); break; } else { // pop the operator and push it on the queue rpn_queue.DeleteOnSubmit(operators.Pop()); } if (operators.Count == 0) break; } while (true); } #endregion } #endregion break; case TokenType.Token_Open_Parenthesis: #region Parenthesis Handling if (item.InOperandFunction == true) { #region Parameter Operator Stack // add open parenthesis to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack // add open parenthesis to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Operand: #region Operand Handling if (item.InOperandFunction == true) { #region Operand Queue parameter_queue.DeleteOnSubmit(item); // if token is an operand, then write it to output. #endregion } else { #region Operand Queue rpn_queue.DeleteOnSubmit(item); // if token is an operand, then write it to output. #endregion } #endregion break; case TokenType.Token_Operand_Function_Start: #region Operand Function Handling if (item.InOperandFunction == true) { parameter_queue.DeleteOnSubmit(item); } else { rpn_queue.DeleteOnSubmit(item); // if token is an operand function, then write it to output. } #endregion break; case TokenType.Token_Operand_Function_Stop: #region Operand Function Handling if (item.InOperandFunction == true) { // pop the operators from the operand function parameter count = param_operators.Count; for (int i = 0; i < count; i++) parameter_queue.DeleteOnSubmit(param_operators.Pop()); // add the items from the temporary parameter quue to the RPN queue count = parameter_queue.Count; for (int i = 0; i < count; i++) rpn_queue.DeleteOnSubmit(parameter_queue[i]); // clear the parameter queue parameter_queue.Clear(); // add the delimiter or stop operand function rpn_queue.DeleteOnSubmit(item); } else { rpn_queue.DeleteOnSubmit(item); // if token is an operand function, then write it to output. } #endregion break; case TokenType.Token_Operator: #region Operator Handling if (item.InOperandFunction == true) { #region Parameter Operator Stack if (param_operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= param_operators.Peek().OrderOfOperationPrecedence) { parameter_queue.DeleteOnSubmit(param_operators.Pop()); } else break; if (param_operators.Count == 0) break; } while (true); } // push the token to the operator stack param_operators.Push(item); #endregion } else { #region Operator Stack if (operators.Count > 0) { // peek at the top item of the operator stack do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.DeleteOnSubmit(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion } #endregion break; case TokenType.Token_Operand_Function_Delimiter: #region Delimiter Handling // pop the operators from the operand function parameter count = param_operators.Count; for (int i = 0; i < count; i++) parameter_queue.DeleteOnSubmit(param_operators.Pop()); // add the items from the temporary parameter quue to the RPN queue count = parameter_queue.Count; for (int i = 0; i < count; i++) rpn_queue.DeleteOnSubmit(parameter_queue[i]); // clear the parameter queue parameter_queue.Clear(); // add the delimiter or stop operand function //rpn_queue.DeleteOnSubmit(item); #endregion break; } } // pop the operators int opCount = operators.Count; for (int i = 0; i < opCount; i++) rpn_queue.DeleteOnSubmit(operators.Pop()); */ #endregion #region Version 1 /* // loop through all the token items foreach (TokenItem item in tokenItems) { if ((item.TokenType == TokenType.Token_Operand) && (item.InOperandFunction == false)) { // if token is an operand, then write it to output. rpn_queue.DeleteOnSubmit(item); } else if (item.TokenType == TokenType.Token_Open_Parenthesis) { // add open parenthesis to the operator stack operators.Push(item); } else if ((item.TokenType == TokenType.Token_Operator) && (item.InOperandFunction == false)) { #region Operator Handling // peek at the top item of the operator stack if (operators.Count > 0) { do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence >= operators.Peek().OrderOfOperationPrecedence) { rpn_queue.DeleteOnSubmit(operators.Pop()); } else break; if (operators.Count == 0) break; } while (true); } // push the token to the operator stack operators.Push(item); #endregion } else if (item.TokenType == TokenType.Token_Close_Parenthesis) { #region Parenthesis Handling if (operators.Count > 0) { do { // see when is on top of the operator stack if (operators.Peek().TokenType == TokenType.Token_Open_Parenthesis) { // we found the matching open parenthesis...pop it and discard operators.Pop(); break; } else { rpn_queue.DeleteOnSubmit(operators.Pop()); } if (operators.Count == 0) break; } while (true); } #endregion } else if (item.TokenType == TokenType.Token_Operand_Function_Start) { // push the operand function onto the output queue rpn_queue.DeleteOnSubmit(item); } else if ((item.TokenType == TokenType.Token_Operand_Function_Stop) || (item.TokenType == TokenType.Token_Operand_Function_Delimiter)) { // pop the operators from the operand function parameter int tempCount = param_operators.Count; for (int i = 0; i < tempCount; i++) parameter_queue.DeleteOnSubmit(param_operators.Pop()); // add the items from the temporary parameter quue to the RPN queue tempCount = parameter_queue.Count; for (int i = 0; i < tempCount; i++) rpn_queue.DeleteOnSubmit(parameter_queue[i]); // clear the parameter queue parameter_queue.Clear(); // add the delimiter or stop operand function rpn_queue.DeleteOnSubmit(item); } else if ((item.TokenType == TokenType.Token_Operand) && (item.InOperandFunction == true)) { // push the parameter on the temporary parameter queue parameter_queue.DeleteOnSubmit(item); } else if ((item.TokenType == TokenType.Token_Operator) && (item.InOperandFunction == true)) { #region Operand Function Operator Handling // peek at the top item of the operator stack if (param_operators.Count > 0) { do { // see if the current tokens precedence is less than or equal to the tokenItem on the operator stack if (item.OrderOfOperationPrecedence > param_operators.Peek().OrderOfOperationPrecedence) { parameter_queue.DeleteOnSubmit(param_operators.Pop()); } else break; if (param_operators.Count == 0) break; } while (true); } // push the token to the operand function operator stack param_operators.Push(item); #endregion } } // pop the operators int opCount = operators.Count; for (int i = 0; i < opCount; i++) rpn_queue.DeleteOnSubmit(operators.Pop()); */ #endregion }