/// <summary> /// Make token list and translate list tokens to Reverse Polish Notation /// </summary> /// <returns></returns> public string Prepare() { int x = 0; Stack <RPNToken> stack = new Stack <RPNToken>(); Stack <RPNToken> postfix = new Stack <RPNToken>(); string RetVal = string.Empty; RPNToken sItem; RPNToken tok; RPNTokenType types; RPNUtils.GetTokens(m_expr, Tokens); while (x < Tokens.Count) { tok = Tokens[x]; types = tok.sType; if (types == RPNTokenType.ALPHA) { if (!Arguments.Contains(tok.sToken)) { Arguments.Add(tok.sToken); } } //Check for numbers if (types == RPNTokenType.NONE || types == RPNTokenType.NUMBER || types == RPNTokenType.ALPHA || types == RPNTokenType.BOOL || types == RPNTokenType.STRING) { //Push number onto postfix stack. postfix.Push(tok); } else { //Check for LPARM if (tok.sToken[0] == '(') { //Push ( onto stack. stack.Push(tok); } //Check for closing param else if (tok.sToken[0] == ')') { sItem = stack.Pop(); while (sItem.sToken[0] != '(') { //Post item of stack onto postfix stack. postfix.Push(sItem); sItem = stack.Pop(); } } else { //While the stack is not empty pop of rest of items. while (stack.Count > 0) { //Get top item sItem = stack.Pop(); //Check order of operators. if (precedence(sItem) >= precedence(tok)) { //Push operator on stack postfix.Push(sItem); } else { //Push back onto stack. stack.Push(sItem); break; } } //Push current token. stack.Push(tok); } } //INC Counter x++; } //Pop off remaining on the stack. while (stack.Count > 0) { //Add to postfix. postfix.Push(stack.Pop()); } //Convert stack to string array. execTokens = postfix.Reverse().ToList(); for (x = 0; x < execTokens.Count; x++) { //Append string to RetVal RetVal += execTokens[x].sToken + " "; } //Return RPN string return(RetVal.Trim()); }
public static bool GetTokens(string expr, List <RPNToken> Tokens) { int i = 0; string tok = string.Empty; RPNToken token; bool IsGood = true; Tokens.Clear(); while (i <= expr.Length) { tok = string.Empty; token = new RPNToken(); if (i > expr.Length - 1) { break; } if (RPNUtils.IsWhiteSpace(expr[i])) { while (RPNUtils.IsWhiteSpace(expr[i])) { i++; if (i > expr.Length - 1) { break; } } } if (i > expr.Length - 1) { break; } if (expr[i] == '\'') { do { tok += expr[i]; i++; if (i > expr.Length - 1) { throw new Exception($"Invalid string [{tok}] , Expression [{expr}]"); } } while (!(expr[i] == '\'')); if (i <= expr.Length - 1) { tok += expr[i]; i++; } else { throw new Exception($"Invalid string [{tok}] , Expression [{expr}]"); } token.sType = RPNTokenType.STRING; token.sToken = tok; Tokens.Add(token); } if (i > expr.Length - 1) { break; } if (expr[i] == '[') { while (!(expr[i] == ']')) { tok += expr[i]; i++; if (i > expr.Length - 1) { break; } } if (i <= expr.Length - 1) { { tok += expr[i]; i++; } } else { throw new Exception($"Invalid string [{tok}] , Expression [{expr}]"); } token.sType = RPNTokenType.ALPHA; token.sToken = tok; Tokens.Add(token); } if (i > expr.Length - 1) { break; } if (expr[i] == '"') { while (!(expr[i] == '"')) { tok += expr[i]; i++; if (i > expr.Length - 1) { throw new Exception($"Invalid string [{tok}] , Expression [{expr}]"); } } if (i <= expr.Length - 1) { { tok += expr[i]; i++; } } else { throw new Exception($"Invalid string [{tok}] , Expression [{expr}]"); } token.sType = RPNTokenType.STRING; token.sToken = tok; Tokens.Add(token); } if (i > expr.Length - 1) { break; } if (char.IsLetter(expr[i]) || (expr[i] == ':')) { do { tok += expr[i]; i++; if (i > expr.Length - 1) { break; } } while (char.IsLetter(expr[i]) || (char.IsDigit(expr[i]) || (expr[i] == '_'))); token.sType = RPNTokenType.ALPHA; var t = tok.ToLower(); if (t.Equals("true") || t.Equals("false")) { token.sType = RPNTokenType.BOOL; tok = t; } else { if (i < expr.Length) { if (expr[i] == '(') { tok += "$"; token.sType = RPNTokenType.FUNCTION; } if (expr[i] == '$') { tok += "$"; i++; token.sType = RPNTokenType.FUNCTION; } } } token.sToken = tok; Tokens.Add(token); } else if (char.IsDigit(expr[i])) { while (char.IsDigit(expr[i]) || (expr[i] == '.')) { tok += expr[i]; i++; if (i > expr.Length - 1) { break; } } token.sType = RPNTokenType.NUMBER; token.sToken = tok; Tokens.Add(token); } else if ((i + 1 < expr.Length) && ((isDoubleOperation(expr[i].ToString() + expr[i + 1])))) { tok = expr[i].ToString(); tok = tok + expr[i + 1]; i++; token.sType = RPNTokenType.OPERAND; token.sToken = tok; token.OperandType = RPNOperandType.ARIFMETICAL; OperationConvertor.GetOperation.TryGetValue(tok, out token.Operation); Tokens.Add(token); i++; if (i > expr.Length - 1) { break; } } else if (isOperation(expr[i])) { tok = expr[i].ToString(); token.sType = RPNTokenType.OPERAND; token.sToken = tok; token.OperandType = RPNOperandType.ARIFMETICAL; OperationConvertor.GetOperation.TryGetValue(tok, out token.Operation); if (token.Operation == RPNOperandType.MINUS) { if (Tokens.Count == 0) { token.Operation = RPNOperandType.JUSTMINUS; token.sToken = tok = "~"; } else if (Tokens.Count > 0 && ((Tokens[Tokens.Count - 1].sType == RPNTokenType.OPERAND))) { if (Tokens[Tokens.Count - 1].Operation != RPNOperandType.END_PARENTHESES) { token.Operation = RPNOperandType.JUSTMINUS; token.sToken = tok = "~"; } } } if (token.Operation == RPNOperandType.PLUS) { if (Tokens.Count > 0 && Tokens[Tokens.Count - 1].sType == RPNTokenType.OPERAND) { if (Tokens[Tokens.Count - 1].Operation != RPNOperandType.END_PARENTHESES) { token.Operation = RPNOperandType.JUSTPLUS; } } } Tokens.Add(token); i++; if (i > expr.Length - 1) { break; } } else { IsGood = false; Tokens.Clear(); if (i < expr.Length) { throw new Exception($"Invalid token type [{expr[i]}] Expression [{expr}]"); } else { throw new Exception($"Invalid Expression [{expr}]"); } } } return(IsGood); }
public object Exec() { double tempDouble; object ret = ""; int i = 0; double a = 0; double b = 0; bool a1 = true; bool b1 = true; string tok = string.Empty; //Go though the tokens al = new Stack <object>(); int x = 0; while (i < Tokens.Count) { tok = Tokens[i].sToken; switch (Tokens[i].sType) { case RPNTokenType.NONE: break; case RPNTokenType.BOOL: if (tok.ToLower().Equals("true")) { al.Push(true); break; } else { al.Push(false); break; } break; case RPNTokenType.ALPHA: if (vars.TryGetValue(tok, out RPNArguments arg)) { a = arg.value; al.Push(a); } else { throw new Exception($"Value [{tok}] not exists"); } break; case RPNTokenType.NUMBER: tempDouble = 0; RPNUtils.TryToDouble(tok, out tempDouble); al.Push(tempDouble); break; case RPNTokenType.STRING: al.Push(tok.Substring(1, tok.Length - 2)); break; case RPNTokenType.FUNCTION: if (Environment != null) { #if DEBUG String argumentList = ""; #endif String funcName = Tokens[i].sToken; funcName = funcName.Substring(0, funcName.Length - 1); var func = Environment.FindFunction(funcName); if (func != null) { FunctionAttribute funcAttrib = (FunctionAttribute)Attribute.GetCustomAttribute(func.GetType(), typeof(FunctionAttribute)); List <object> arguments = new List <object>(); if (funcAttrib.ParamTypes != null && funcAttrib.ParamTypes.Length > 0) { foreach (var paramType in funcAttrib.ParamTypes) { object obj = al.Pop(); func.Params.Add(obj); #if DEBUG argumentList += " "; argumentList += obj.ToString(); #endif } } object retObject = func.Calc(); al.Push(retObject); #if DEBUG Console.WriteLine($"Function , {funcName}({argumentList}) = {retObject.ToString()}"); #endif // al.Push(r); } } break; case RPNTokenType.OPERAND: object r = 0; switch (Tokens[i].Operation) { case RPNOperandType.JUSTPLUS: a = Convert.ToDouble(al.Pop()); r = +a; #if DEBUG Console.WriteLine($"JustPlus , {r} = {a.ToString()}"); #endif break; case RPNOperandType.PLUS: a = Convert.ToDouble(al.Pop()); var b11 = al.Pop(); if (b11 is DateTime) { DateTime dDateTime = (DateTime)b11; r = dDateTime.AddHours(a); } else { b = Convert.ToDouble(b11); r = a + b; } #if DEBUG Console.WriteLine($"{b.ToString()} + {a.ToString()} = {r.ToString()}"); #endif break; case RPNOperandType.JUSTMINUS: a = Convert.ToDouble(al.Pop()); r = -a; break; case RPNOperandType.MINUS: var t = al.Pop(); a = Convert.ToDouble(t); var b12 = al.Pop(); if (b12 is DateTime) { DateTime dDateTime = (DateTime)b12; r = dDateTime.AddHours(-a); } else { b = Convert.ToDouble(b12); r = b - a; } #if DEBUG Console.WriteLine($"{b} - {a} = {r}"); #endif break; case RPNOperandType.MULITIPLY: a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = a * b; #if DEBUG Console.WriteLine($"{b} * {a} = {r}"); #endif break; case RPNOperandType.DIVIDE: a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b / a); #if DEBUG Console.WriteLine($"{b} / {a} = {r}"); #endif break; case RPNOperandType.EXPONENTIATION: a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = Math.Pow(b, a); #if DEBUG Console.WriteLine($"{b} ^ {a} = {r}"); #endif break; case RPNOperandType.DIV: // "/=" a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b / a); #if DEBUG Console.WriteLine($"{b} /= {a} = {r}"); #endif break; case RPNOperandType.MOD: //"%=", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b %= a); #if DEBUG Console.WriteLine($"{b} %= {a} = {r}"); #endif break; case RPNOperandType.LESS: //"<", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b < a); #if DEBUG Console.WriteLine($"{b} < {a} = {r}"); #endif break; case RPNOperandType.GREATER: //">", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b > a); #if DEBUG Console.WriteLine($"{b} > {a} = {r}"); #endif break; case RPNOperandType.LESSOREQUAL: //"<=", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b <= a); #if DEBUG Console.WriteLine($"{b} <= {a} = {r}"); #endif break; case RPNOperandType.GREATEOREQUAL: //">=", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b >= a); #if DEBUG Console.WriteLine($"{b} >={a} = {r}"); #endif break; case RPNOperandType.NOTEQUAL: //"!=", a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b != a); #if DEBUG Console.WriteLine($"{b} !={a} = {r}"); #endif break; case RPNOperandType.EQUAL: //"==" a = Convert.ToDouble(al.Pop()); b = Convert.ToDouble(al.Pop()); r = (b == a); #if DEBUG Console.WriteLine($"{b} =={a} = {r}"); #endif break; case RPNOperandType.OR: //"||", a1 = Convert.ToBoolean(al.Pop()); b1 = Convert.ToBoolean(al.Pop()); r = (b1 || a1); #if DEBUG Console.WriteLine($"{b1} || {a1} = {r}"); #endif break; case RPNOperandType.AND: //"&&", a1 = Convert.ToBoolean(al.Pop()); b1 = Convert.ToBoolean(al.Pop()); r = (b1 && a1); #if DEBUG Console.WriteLine($"{b1} && {a1} = {r}"); #endif break; case RPNOperandType.NOT: //"!", a1 = Convert.ToBoolean(al.Pop()); r = (!a1); #if DEBUG Console.WriteLine($" !{a1} = {r}"); #endif break; } al.Push(r); break; } i++; } while (x < al.Count) { ret = al.Pop(); } return(ret); }