public static Token ExecuteUserFunction(string funcName, List <Token> arguments) { functionCallNumber++; Token result = Token.Error("Invalid call to user function"); if (!userFunctions.ContainsKey(variables.GetStringData(funcName))) { return(result); } UserFunction userFunc = userFunctions[variables.GetStringData(funcName)]; Dictionary <string, string> names = new Dictionary <string, string>(); for (int i = 0; i < arguments.Count; i++) { //var tempName = "_" + Guid.NewGuid().ToString("N"); var tempName = GenerateRandomName(); //This is much faster than Guid due to smaller string length names.Add(tempName, arguments[i].TokenName); arguments[i].TokenName = tempName; variables.AddToken(arguments[i]); } string executbleCode = ReplaceNames(arguments, userFunc); Token temp = new Token(TokenType.Block, "", executbleCode); callDepth++; if (callDepth == 0) { variables.RemoveReservedWord("return"); } try { temp = BlockCommands.ExecuteBlock(temp); } catch (Exception) { temp = Token.Error("An error occured while performaing the operation"); } callDepth--; if (callDepth < 0) { variables.AddReservedWord("return"); } foreach (var pair in names) { var item = variables.GetToken(pair.Key); item.TokenName = pair.Value; variables.Remove(pair.Key); } if (userFunc.returns && temp.TokenType != TokenType.Error) { try { temp = variables.GetToken("return"); } catch (Exception) { temp = Token.Error("Return value not valid in function definition"); } } return(temp); }
public static Token TokenizeString(String expression, out List <Token> tokens) //str --> a trimmed string { tokens = new List <Token>(); int i = 0; String nextTokenStr; bool unaryFlag = true; while (i < expression.Length) { nextTokenStr = ""; while (i < expression.Length && Char.IsWhiteSpace(expression[i])) { i++; } if (i == expression.Length) { break; } nextTokenStr += expression[i++].ToString(); OpEnum opEnum = IsOperator(nextTokenStr); if (opEnum == OpEnum.Yes || opEnum == OpEnum.YesKeepGo) { if (opEnum == OpEnum.YesKeepGo) { if (i < expression.Length) { String tempStr = nextTokenStr + expression[i].ToString(); if (IsOperator(tempStr) == OpEnum.Yes) { tokens.Add(new Token(TokenType.Operator, tempStr)); i++; unaryFlag = true; continue; } } if (nextTokenStr == "!") { nextTokenStr = "~"; } } if (((nextTokenStr == "+" || nextTokenStr == "-") && unaryFlag) || nextTokenStr == "~") { tokens.Add(new Token(TokenType.Operator, "u" + nextTokenStr)); } else { tokens.Add(new Token(TokenType.Operator, nextTokenStr)); } if (expression[i - 1] != ')') { unaryFlag = true; } else { unaryFlag = false; } continue; } else { unaryFlag = false; } if (nextTokenStr == "\"") { i = SkipString(i, ref nextTokenStr, expression, false); if (i < 0) { return(Token.Error("Bad input. Input not valid: [ " + nextTokenStr + " ]")); } tokens.Add(new Token(TokenType.Text, nextTokenStr.Substring(1, nextTokenStr.Length - 2))); continue; } if (nextTokenStr == "{") { int startedCount = 1; while (i < expression.Length) { nextTokenStr += expression[i++].ToString(); if (expression[i - 1] == '\"') { i = SkipString(i, ref nextTokenStr, expression, true); if (i < 0) { return(Token.Error("Bad input. Input not valid: [ " + nextTokenStr + " ]")); } continue; } if (expression[i - 1] == '}') { startedCount--; if (startedCount == 0) { break; } } else if (expression[i - 1] == '{') { startedCount++; } } if (startedCount != 0) { return(Token.Error("Bad input. Bracket mismatch :[ " + nextTokenStr + " ]")); } tokens.Add(new Token(TokenType.Block, "", nextTokenStr.Substring(1, nextTokenStr.Length - 2))); continue; } while (i < expression.Length && !Char.IsWhiteSpace(expression[i]) && (IsOperator(expression[i].ToString()) == OpEnum.No) && expression[i] != '"' && expression[i] != '{') { nextTokenStr += expression[i++].ToString(); } if (Char.IsDigit(nextTokenStr[0]) || nextTokenStr[0] == '.') { try { Double.Parse(nextTokenStr); tokens.Add(new Token(TokenType.Vector, Double.Parse(nextTokenStr))); } catch (Exception) { return(Token.Error("Bad input: [ " + nextTokenStr + " ]")); } } else if (variables.Contains(nextTokenStr)) { tokens.Add(variables.GetToken(nextTokenStr)); } else { if (Function.IsDirective(nextTokenStr)) { tokens.Add(new Token(TokenType.Directive, nextTokenStr)); } else if (Function.IsFuction(nextTokenStr)) { tokens.Add(new Token(TokenType.Function, nextTokenStr)); } else if (BlockCommands.IsConditionCommand(nextTokenStr)) { tokens.Add(new Token(TokenType.Condition, nextTokenStr)); if (nextTokenStr == "else") { tokens.Add(new Token(TokenType.Operator, "(")); tokens.Add(new Token(TokenType.Bool, 0, 1)); tokens.Add(new Token(TokenType.Operator, ")")); } } else if (BlockCommands.IsLoopCommand(nextTokenStr)) { tokens.Add(new Token(TokenType.Loop, nextTokenStr)); if (nextTokenStr == "while") { nextTokenStr = ""; while (i < expression.Length && Char.IsWhiteSpace(expression[i])) { i++; } if (i == expression.Length || expression[i++] != '(') { return(Token.Error("Wrong use of 'while' statement.")); } int closeCount = -1; while (i < expression.Length) { if (expression[i] == ')') { ++closeCount; } else if (expression[i] == '(') { --closeCount; } if (closeCount == 0) { i++; break; } nextTokenStr += expression[i++].ToString(); } if (closeCount == 0) { tokens.Add(new Token(TokenType.Text, "(")); tokens.Add(new Token(TokenType.Text, nextTokenStr, nextTokenStr)); tokens.Add(new Token(TokenType.Text, ")")); } else { return(Token.Error("Wrong use of 'while' statement. () mismatch.")); } } } else if (nextTokenStr == "break") { tokens.Add(new Token(TokenType.Break, nextTokenStr)); } else if (nextTokenStr == "function") { tokens.Add(new Token(TokenType.FunctionDefiner, nextTokenStr)); } else { tokens.Add(new Token(TokenType.Text, nextTokenStr)); } } } return(Token.Void); }
public static Token Calculate(List <Token> postfixTokens) { Stack <Token> operands = new Stack <Token>(); Token result = Token.Void; try { for (int index = 0; index < postfixTokens.Count; index++) { Token t = postfixTokens[index]; if (t.TokenType == TokenType.Vector || t.TokenType == TokenType.Text || t.TokenType == TokenType.Bool || t.TokenType == TokenType.Block || t.TokenType == TokenType.Break || t.TokenType == TokenType.Matrix || t.TokenType == TokenType.Custom) { operands.Push(t); } else if (t.TokenType == TokenType.Function || t.TokenType == TokenType.Loop || t.TokenType == TokenType.Condition || t.TokenType == TokenType.UserFunction || t.TokenType == TokenType.FunctionDefiner) { int paramCount = (int)(operands.Pop().FirstValue); List <Token> parameters = new List <Token>(); for (int i = 0; i < paramCount; i++) { parameters.Add(operands.Pop()); } parameters.Reverse(); Token resultToken; if (t.TokenType == TokenType.Function) { resultToken = Function.InvokeFunction(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else if (t.TokenType == TokenType.UserFunction) { resultToken = FunctionDefiner.ExecuteUserFunction(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else if (t.TokenType == TokenType.Loop) { loopDepth++; resultToken = BlockCommands.ExecuteLoop(t.TokenName, parameters); if (resultToken.TokenType == TokenType.Error) { loopDepth = 0; return(resultToken); } loopDepth--; } else if (t.TokenType == TokenType.Condition) { Token param = Token.Void; if (t.TokenName == "elseif" || t.TokenName == "else") { param = operands.Pop(); } resultToken = BlockCommands.ExecuteCondition(t.TokenName, param, parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } else { if (operands.Count == 0) { return(Token.Error("User function must be assigned to a name")); } resultToken = FunctionDefiner.CreateUserFunction(parameters); if (resultToken.TokenType == TokenType.Error) { return(resultToken); } } operands.Push(resultToken); } else if (operands.Count >= 1 && t.TokenName.StartsWith("u")) { if (operands.Peek().TokenType != TokenType.Vector && operands.Peek().TokenType != TokenType.Bool && operands.Peek().TokenType != TokenType.Matrix) { return(Token.Error("Operand not valid for [ " + t.TokenName + " ]")); } Token firstParam = operands.Pop(); Token temp = null; if (!DoCalculateUnary(t.TokenName, firstParam, out temp)) { return(Token.Error("Operand not valid for [ " + t.TokenName + " ]")); } operands.Push(temp); } else if (operands.Count > 1) { Token temp = null; Token firstParam = operands.Pop(); Token secondParam = operands.Pop(); switch (t.TokenName) { case "*": case "/": case "%": case "+": case "-": case "^": case "==": case "!=": case "?": case "??": case "<": case ">": case ">=": case "<=": if (firstParam.TokenType == TokenType.Text && secondParam.TokenType == TokenType.Text) { temp = new Token(TokenType.Bool, 1, firstParam.StrData == secondParam.StrData ? 1 : 0); } else if (firstParam.TokenType == TokenType.Custom && secondParam.TokenType == TokenType.Custom && firstParam.IsOfType(typeof(StringsToken)) && secondParam.IsOfType(typeof(StringsToken))) { List <string> first = (List <string>)firstParam.CustomData; List <string> second = (List <string>)secondParam.CustomData; if (first.Count == second.Count) { for (var i = 0; i < first.Count; i++) { if (first[i] != second[i]) { temp = new Token(TokenType.Bool, 1, 0); } } } else { temp = new Token(TokenType.Bool, 1, 0); } temp = new Token(TokenType.Bool, 1, 1); } else if ((firstParam.TokenType != TokenType.Vector && firstParam.TokenType != TokenType.Bool && firstParam.TokenType != TokenType.Matrix) || (secondParam.TokenType != TokenType.Vector && secondParam.TokenType != TokenType.Bool && secondParam.TokenType != TokenType.Matrix) ) { return(Token.Error("Operands not valid for [ " + t.TokenName + " ]. Both must be the same type.")); } else { temp = DoCalculate(t.TokenName, secondParam, firstParam); } if (temp.TokenType == TokenType.Error) //yep stack is upside down! { return(temp); } break; case "=": if (firstParam.TokenType == TokenType.Void || string.IsNullOrEmpty(secondParam.TokenName)) { return(Token.Error("Assignment not valid.")); } secondParam.ResetValues(firstParam); if (variables.Contains(secondParam.TokenName)) { temp = variables.SetTokenVerify(secondParam); } else { temp = variables.AddTokenVerify(secondParam); } if (temp.TokenType == TokenType.Error) { return(temp); } else { temp = secondParam; } if (secondParam.TokenType == TokenType.UserFunction) { if (operands.Count == 0) { return(new Token(TokenType.Text, "", "User function named [ " + temp.TokenName + " ] added")); } else { return(Token.Error("Bad definition of User function")); } } break; default: return(Token.Error("Error in expression")); } operands.Push(temp); } else { return(Token.Error("Error in expression")); } } if (operands.Count != 1) { return(Token.Error("Error in expression")); } result = operands.Pop(); if (result.TokenType == TokenType.Block) { result = BlockCommands.ExecuteBlock(result); if (result.TokenType != TokenType.Error) { return(Token.Void); } } else if (result.TokenType == TokenType.Operator || result.TokenType == TokenType.Loop || result.TokenType == TokenType.Condition) { return(Token.Error("Error in expression")); } } catch (Exception) { return(Token.Error("Error in expression")); } if (result.TokenType == TokenType.ConditionExecuted) { return(Token.Void); } return(result); }
private static string ReplaceNames(List <Token> arguments, UserFunction userFunc) { executbleCode.Clear(); string str = userFunc.data; for (int j = 0; j < str.Length;) { int k = BlockCommands.SkipString(j, str); if (k > j) { executbleCode.Append(str.Substring(j, k - j)); j = k; continue; } while (j < str.Length && Char.IsWhiteSpace(str[j])) { j++; } if (j < str.Length) { k = j; string currentStr = null; var isOp = Tokenizer.IsOperator(str[j].ToString()); if (isOp != OpEnum.No) { if (isOp == OpEnum.YesKeepGo && j < str.Length - 1) { isOp = Tokenizer.IsOperator(str.Substring(j, 2)); if (isOp == OpEnum.Yes) { j++; } } j++; currentStr = str.Substring(k, j - k); } else { //executbleCode.Append(" "); while (j < str.Length && !Char.IsWhiteSpace(str[j]) && str[j] != ';' && str[j] != ':' && str[j] != '{' && str[j] != '}' && Tokenizer.IsOperator(str[j].ToString()) == OpEnum.No) { j++; } if (k == j) { j++; } currentStr = str.Substring(k, j - k); for (int i = 0; i < arguments.Count; i++) { string oldStr = userFunc.signatureList[i]; if (currentStr == oldStr) { currentStr = arguments[i].TokenName; break; } } } executbleCode.Append(currentStr); } } return(executbleCode.ToString()); }