Beispiel #1
0
		public  Statement (Parser yyp, FunctionCall  fc ):base(((LSLSyntax
		                                                        )yyp)){ kids . Add ( fc );
		}
Beispiel #2
0
		public  FunctionCallExpression (Parser yyp, FunctionCall  fc ):base(((LSLSyntax
		                                                                     )yyp)){ kids . Add ( fc );
		}
        /// <summary>
        /// Generates the code for a FunctionCall node.
        /// </summary>
        /// <param name="fc">The FunctionCall node.</param>
        /// <returns>String containing C# code for FunctionCall fc.</returns>
        private string GenerateFunctionCall(FunctionCall fc)
        {
            string retstr = "";

            bool marc = FuncCallsMarc();

            string Mname = "";
            bool isEnumerable = false;
            string tempString = "";
            string FunctionCalls = "";

            int NeedCloseParent = 0;

            foreach (SYMBOL kid in fc.kids)
            {
                //                if (kid is ArgumentList && m_SLCompatabilityMode)
                if (kid is ArgumentList)
                {
                    ArgumentList al = kid as ArgumentList;
                    int comma = al.kids.Count - 1;  // tells us whether to print a comma

                    foreach (SYMBOL s in al.kids)
                    {
                        if (s is BinaryExpression)
                        {
                            BinaryExpression be = s as BinaryExpression;
                            //FunctionCalls += GenerateNode(s);
                            if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
                            {
                                // special case handling for logical and/or, see Mantis 3174
                                tempString += "((bool)(";
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += "))";
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)), be);
                                tempString += "((bool)(";
                                foreach (SYMBOL kidb in be.kids)
                                    retstr += GenerateNode(kidb);
                                tempString += "))";
                            }
                            else
                            {
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
                                foreach (SYMBOL kidb in be.kids)
                                {
                                    if (kidb is FunctionCallExpression)
                                    {
                                        tempString += GenerateNode(kidb);
                                    }
                                    else if (kidb is TypecastExpression)
                                    {
                                        tempString += Generate(String.Format("({0}) (", ((TypecastExpression)kidb).TypecastType));
                                        tempString += GenerateNode((SYMBOL)kidb.kids.Pop());
                                        tempString += Generate(")");
                                    }

                                    else
                                        tempString += GenerateNode(kidb);
                                }
                            }
                        }
                        else if (s is TypecastExpression)
                        {
                            tempString += Generate(String.Format("({0}) (", ((TypecastExpression)s).TypecastType));
                            tempString += GenerateNode((SYMBOL)s.kids.Pop());
                            tempString += Generate(")");
                        }
                        else
                        {
                            tempString += GenerateNode(s);
                        }

                        if (0 < comma--)
                            tempString += Generate(", ");
                    }
                }
                else
                {
                    tempString += GenerateNode(kid);
                }
            }
            /*
                        string TempStringForEnum = "";
                        TempStringForEnum = OriginalScript.Remove(0, fc.pos);
                        TempStringForEnum = TempStringForEnum.Remove(0, fc.Id.Length);
                        TempStringForEnum = TempStringForEnum.Split(')')[0];
                        string TestOriginal = OriginalScript.Replace(" ", "");
                        TestOriginal = TestOriginal.Replace("\n", "");
                        string TestScript = fc.Id + TempStringForEnum + ")" + "{";
                        string TestTestScript = fc.Id + "(*){";

                        foreach (string testOriginal in TestOriginal.Split(';'))
                        {
                            if (testOriginal.CompareWildcard(TestTestScript, true))
                            {
                                isEnumerable = true;
                            }
                        }
                        if (TestOriginal.Contains(TestScript))
                        {
                            //This DOES need to exist, this is for nested function calls to user-generated methods!
                            isEnumerable = true;
                        }
                        else if (retstr.ToString().Contains("IEnumerator " + fc.Id))
                        {
                            isEnumerable = true;
                        }
            */
            isEnumerable = false;
            bool DTFunction = false;

            string rettype = "void";
            if (LocalMethods.TryGetValue(fc.Id, out rettype))
                isEnumerable = true;

            else if (DTFunctions.Contains(fc.Id))
            {
                DTFunction = true;
            }

            if (DTFunction)
            {
                //                retstr.Append(GenerateLine("{"));
                retstr += Generate("yield return ");
                retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
                retstr += tempString;

                retstr += GenerateLine(")");
                //                retstr.Append(Generate("yield return null;"));
                //                retstr.Append(GenerateLine("}"));
            }
            else if (isEnumerable)
            {
                if (rettype != "void")
                {
                    Mname = RandomString(10, true);
                    FunctionCalls += GenerateLine(rettype + " " + Mname + ";");
                }

                FunctionCalls += GenerateLine("{");

                //We can use enumerator here as the { in the above line breaks off possible issues upward in the method (or should anyway)
                FunctionCalls += Generate("IEnumerator enumerator = ");
                FunctionCalls += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
                FunctionCalls += tempString;
                FunctionCalls += Generate(");");

                FunctionCalls += GenerateLine("while (true)");
                FunctionCalls += GenerateLine("{");
                string FunctionName = RandomString(10, true);
                FunctionCalls += GenerateLine("bool " + FunctionName + " = false;");

                FunctionCalls += GenerateLine("try");
                FunctionCalls += GenerateLine("{");
                FunctionCalls += GenerateLine("" + FunctionName + " = enumerator.MoveNext();");
                FunctionCalls += GenerateLine("if(!" + FunctionName + ")");
                FunctionCalls += GenerateLine("break;"); //All done, break out of the loop
                FunctionCalls += GenerateLine("}");
                FunctionCalls += GenerateLine("catch");
                FunctionCalls += GenerateLine("{");
                FunctionCalls += GenerateLine("yield break;");//End it since we are erroring out -> now abort 
                FunctionCalls += GenerateLine("}"); //End of catch
                FunctionCalls += GenerateLine("if( enumerator.Current == null || enumerator.Current is DateTime) yield return enumerator.Current;"); //Let the other things process for a bit here at the end of each enumeration
                FunctionCalls += GenerateLine("else break;"); //Let the other things process for a bit here at the end of each enumeration
                FunctionCalls += GenerateLine("}"); //End of while
                if (rettype != "void")
                {
                    FunctionCalls += GenerateLine(Mname + " = (" + rettype + ") enumerator.Current;");
                    retstr += Mname;
                }
                FunctionCalls += GenerateLine("}");
                FuncCalls.Add(FunctionCalls);
            }
            else
            {
                retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
                retstr += tempString;

                retstr += Generate(")");
            }
            /*
                        if (FunctionCalls != "")
                        {
                            retstr.Append(Generate(";")); //We do this because we can't just do ) } .... otherwise we have issues!
                            // Add it to the end so that everything is covered 
                            //so that lines like 'if(test) callStatement(FunctionCall());'
                            //don't error out because of brackets
                            retstr.Append(GenerateLine("}"));
                            retstr.Append(GenerateLine("TESTREMOVE")); //Gets removed later and tells it not to print a ; at the end
                        }
            */
            //Function calls are first
            return DumpFunc(marc) + retstr.ToString();
        }
Beispiel #4
0
        /// <summary>
        /// Generates the code for a FunctionCall node.
        /// </summary>
        /// <param name="fc">The FunctionCall node.</param>
        /// <returns>String containing C# code for FunctionCall fc.</returns>
        private string GenerateFunctionCall(FunctionCall fc, bool NeedRetVal)
        {
            string retstr = "";

            bool marc = FuncCallsMarc();

            string Mname = "";
            bool isEnumerable = false;
            string tempString = "";
            
            //int NeedCloseParent = 0;

            foreach (SYMBOL kid in fc.kids)
            {
                //                if (kid is ArgumentList && m_SLCompatabilityMode)
                if (kid is ArgumentList)
                {
                    ArgumentList al = kid as ArgumentList;
                    int comma = al.kids.Count - 1;  // tells us whether to print a comma

                    foreach (SYMBOL s in al.kids)
                    {
                        if (s is BinaryExpression)
                        {
                            BinaryExpression be = s as BinaryExpression;
                            //FunctionCalls += GenerateNode(s);
                            if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
                            {
                                // special case handling for logical and/or, see Mantis 3174
                                tempString += "((bool)(";
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += "))";
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)), be);
                                tempString += "((bool)(";
                                foreach (SYMBOL kidb in be.kids)
                                    retstr += GenerateNode(kidb);
                                tempString += "))";
                            }
                            else
                            {
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
                                foreach (SYMBOL kidb in be.kids)
                                {
                                    if (kidb is FunctionCallExpression)
                                    {
                                        tempString += GenerateNode(kidb);
                                    }
                                    else if (kidb is TypecastExpression)
                                    {
                                        tempString += Generate(String.Format("({0}) (", ((TypecastExpression)kidb).TypecastType));
                                        tempString += GenerateNode((SYMBOL)kidb.kids.Pop());
                                        tempString += Generate(")");
                                    }

                                    else
                                        tempString += GenerateNode(kidb);
                                }
                            }
                        }
                        else if (s is TypecastExpression)
                        {
                            tempString += Generate(String.Format("({0}) (", ((TypecastExpression)s).TypecastType));
                            tempString += GenerateNode((SYMBOL)s.kids.Pop());
                            tempString += Generate(")");
                        }
                        else
                        {
                            tempString += GenerateNode(s);
                        }

                        if (0 < comma--)
                            tempString += Generate(", ");
                    }
                }
                else
                {
                    tempString += GenerateNode(kid);
                }
            }
            
            isEnumerable = false;
            bool DTFunction = false;

            string rettype = "void";
            if (LocalMethods.TryGetValue(fc.Id, out rettype))
                isEnumerable = true;
/* suspended.. API fails with IEnums
            else if (IenFunctions.TryGetValue(fc.Id, out rettype))
                isEnumerable = true;
*/
            else if (DTFunctions.Contains(fc.Id))
            {
                DTFunction = true;
            }

            //Check whether this function is an API function
            if (m_apiFunctions.ContainsKey(CheckName(fc.Id)))
            {
                //Add the m_apis link
                fc.Id = String.Format("(({0})m_apis[\"{1}\"]).{2}", 
                    m_apiFunctions[CheckName(fc.Id)].InterfaceName,
                    m_apiFunctions[CheckName(fc.Id)].Name, fc.Id);
            }

            if (DTFunction)
            {
                retstr += Generate("yield return ");
                retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
                retstr += tempString;
                retstr += Generate(")");
            }
            else if (isEnumerable)
            {
                if (m_isInEnumeratedDeclaration && NeedRetVal) //Got to have a retVal for do/while
                {
                    //This is for things like the do/while statement, where a function is in the while() part and can't be dumped in front of the do/while
                    string MethodName = RandomString(10, true);
                    string typeDefs = "";
                    ObjectList arguements = null;
                    if (LocalMethodArguements.TryGetValue(fc.Id, out arguements))
                    {
                        // print the state arguments, if any
                        foreach (SYMBOL kid in arguements)
                        {
                            if (kid is ArgumentDeclarationList)
                            {
                                ArgumentDeclarationList ADL = (ArgumentDeclarationList)kid;
                                typeDefs += (GenerateArgumentDeclarationList(ADL)) + ",";
                            }
                        }
                    }
                    if (typeDefs.Length != 0)
                        typeDefs = typeDefs.Remove(typeDefs.Length - 1);

                    string newMethod = string.Format("private {0} {1}({2}, out bool ahwowuerogng)", rettype, MethodName, typeDefs);
                    newMethod += (Generate("{"));
                    newMethod += (Generate("ahwowuerogng = true;"));
                    Mname = RandomString(10, true);
                    newMethod += (Generate("IEnumerator " + Mname + " = "));
                    newMethod += (Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                    newMethod += (tempString);
                    newMethod += (Generate(");"));

                    newMethod += (Generate(" try {"));
                    newMethod += (Generate(Mname + ".MoveNext();"));
                    newMethod += (Generate("  if(" + Mname + ".Current != null)"));
                    newMethod += (Generate("   return (" + rettype + ")" + Mname + ".Current;"));
                    newMethod += (Generate("  }")); //End of try
                    newMethod += (Generate(" catch(Exception ex) "));
                    newMethod += (Generate("  {"));
                    newMethod += (Generate("  }")); //End of catch
                    newMethod += (Generate("ahwowuerogng = true;"));
                    newMethod += (Generate("return default(" + rettype + ");")); //End while
                    newMethod += "}";
                    MethodsToAdd.Add(newMethod);

                    List<string> fCalls = new List<string>();
                    string boolname = RandomString(10, true);
                    fCalls.Add(Generate("bool " + boolname + " = true;"));
                    retstr += MethodName + "(" + tempString + ", out " + boolname + ")";
                    lock (FuncCalls)
                        FuncCalls.AddRange(fCalls);
                }
                else
                {
                    //Function calls are added to the DumpFunc command, and will be dumped safely before the statement that occurs here, so we don't have to deal with the issues behind having { and } in this area.
                    Mname = RandomString(10, true);
                    string Exname = RandomString(10, true);
                    List<string> fCalls = new List<string>();
                    fCalls.Add(Generate("string " + Exname + " =  \"\";"));
                    fCalls.Add(Generate("IEnumerator " + Mname + " = "));
                    fCalls.Add(Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                    fCalls.Add(tempString);
                    fCalls.Add(Generate(");"));

                    fCalls.Add(Generate("while (true) {"));
                    fCalls.Add(Generate(" try {"));
                    fCalls.Add(Generate("  if(!" + Mname + ".MoveNext())"));
                    fCalls.Add(Generate("   break;"));
                    fCalls.Add(Generate("  }")); //End of try
                    fCalls.Add(Generate(" catch(Exception ex) "));
                    fCalls.Add(Generate("  {"));
                    fCalls.Add(Generate("  " + Exname + " = ex.Message;"));
                    fCalls.Add(Generate("  }")); //End of catch
                    fCalls.Add(Generate(" if(" + Exname + " != \"\")"));
                    fCalls.Add(Generate("   yield return " + Exname + ";")); //Exceptions go first
                    fCalls.Add(Generate(" else if(" + Mname + ".Current == null || " + Mname + ".Current is DateTime)"));
                    fCalls.Add(Generate("   yield return " + Mname + ".Current;"));
                        //Let the other things process for a bit here at the end of each enumeration
                    fCalls.Add(Generate(" else break;"));
                        //Let the other things process for a bit here at the end of each enumeration
                    fCalls.Add(Generate(" }")); //End while
                    if (NeedRetVal && rettype != "void")
                    {
                        retstr += " (" + rettype + ") " + Mname + ".Current";
                    }
                    lock (FuncCalls)
                        FuncCalls.AddRange(fCalls);
                }
            }
            else
            {
                retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
                retstr += tempString;

                retstr += Generate(")");
            }

            //Function calls are first if needed
            return DumpFunc(marc) + retstr.ToString();
        }
Beispiel #5
0
        /// <summary>
        /// Generates the code for a FunctionCall node.
        /// </summary>
        /// <param name="fc">The FunctionCall node.</param>
        /// <returns>String containing C# code for FunctionCall fc.</returns>
        private string GenerateFunctionCall(FunctionCall fc, bool NeedRetVal)
        {
            string retstr = String.Empty;
            //Check whether this function is an API function
            if (m_apiFunctions.ContainsKey(CheckName(fc.Id)))
            {
                //Add the m_apis link
                fc.Id = String.Format("(({0})m_apis[\"{1}\"]).{2}",
                    m_apiFunctions[CheckName(fc.Id)].InterfaceName,
                    m_apiFunctions[CheckName(fc.Id)].Name, fc.Id);
            }
            retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);

            foreach (SYMBOL kid in fc.kids)
                retstr += GenerateNode(kid);

            retstr += Generate(")");

            return retstr;
        }
        /// <summary>
        /// Generates the code for a FunctionCall node.
        /// </summary>
        /// <param name="fc">The FunctionCall node.</param>
        /// <returns>String containing C# code for FunctionCall fc.</returns>
        private string GenerateFunctionCall(FunctionCall fc)
        {
            StringBuilder retstr = new StringBuilder();

            string tempString = "";
            foreach (SYMBOL kid in fc.kids)
                tempString += GenerateNode(kid);

            //We can assume pretty well that there are no enumerator functions in the legacy parser, as only state events are IEnumerator, and you can't call those

            //We still MUST check these though!
            bool DTFunction = false;
            if (DTFunctions.Contains(fc.Id))
                DTFunction = true;

            if (DTFunction && IsParentEnumerable)
            {
                retstr.Append(GenerateLine("{"));
                retstr.Append(Generate("yield return "));
                retstr.Append(Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                retstr.Append(tempString);

                retstr.Append(GenerateLine(");"));
                retstr.Append(Generate("yield return null"));
                retstr.Append(GenerateLine("}"));
            }
            else if (DTFunction)
            {
                //Uhoh, sleeping in a void.... it returns a DT,
                //   but we can't handle like in the other enumerator places
                //   so we have to force the sleep in HERE
                retstr.Append(GenerateLine("{"));
                retstr.Append("DateTime time = " + Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                retstr.Append(tempString);
                retstr.Append(GenerateLine(");"));

                //Ex. --- 

                //DateTime time = DateTime.Now.AddMilliseconds(10000); // 10 s
                //System.Threading.Thread.Sleep((DateTime.Now - time).TotalMilliseconds);

                //End Ex. ---

                //Do the sleep now
                retstr.Append("System.Threading.Thread.Sleep((DateTime.Now - time).TotalMilliseconds);");

                retstr.Append(GenerateLine("}"));
            }

            return retstr.ToString();
        }
Beispiel #7
0
        /// <summary>
        /// Generates the code for a FunctionCall node.
        /// </summary>
        /// <param name="fc">The FunctionCall node.</param>
        /// <returns>String containing C# code for FunctionCall fc.</returns>
        private string GenerateFunctionCall(FunctionCall fc)
        {
            StringBuilder retstr = new StringBuilder();

            bool isEnumerable = false;
            string tempString = "";
            string FunctionCalls = "";
            foreach (SYMBOL kid in fc.kids)
            {
                if (kid is ArgumentList && m_SLCompatabilityMode)
                {
                    ArgumentList al = kid as ArgumentList;
                    int comma = al.kids.Count - 1;  // tells us whether to print a comma

                    foreach (SYMBOL s in al.kids)
                    {
                        if (s is BinaryExpression)
                        {
                            BinaryExpression be = s as BinaryExpression;
                            //FunctionCalls += GenerateNode(s);
                            if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
                            {
                                // special case handling for logical and/or, see Mantis 3174
                                tempString += "((bool)(";
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += "))";
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)), be);
                                tempString += "((bool)(";
                                foreach (SYMBOL kidb in be.kids)
                                    retstr.Append(GenerateNode(kidb));
                                tempString += "))";
                            }
                            else
                            {
                                tempString += GenerateNode((SYMBOL)be.kids.Pop());
                                tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
                                foreach (SYMBOL kidb in be.kids)
                                {
                                    if (kidb is FunctionCallExpression)
                                    {
                                        string FunctionName = RandomString(10, true);
                                        if (FunctionCalls == "")
                                        {
                                            FunctionCalls += GenerateLine("{"); //Add extra bracketing
                                        }
                                        FunctionCalls += "object "+FunctionName+" = " + GenerateNode(kidb) + ";";
                                        tempString += FunctionName;
                                    }
                                    else
                                        tempString += GenerateNode(kidb);
                                }
                            }
                        }
                        else
                        {
                            tempString += GenerateNode(s);
                        }
                        if (0 < comma--)
                            tempString += Generate(", ");
                    }
                }
                else
                {
                    tempString += GenerateNode(kid);
                }
            }

            string TempStringForEnum = "";
            TempStringForEnum = OriginalScript.Remove(0, fc.pos);
            TempStringForEnum = TempStringForEnum.Remove(0, fc.Id.Length);
            TempStringForEnum = TempStringForEnum.Split(')')[0];
            string TestOriginal = OriginalScript.Replace(" ", "");
            TestOriginal = TestOriginal.Replace("\n", "");
            string TestScript = fc.Id + TempStringForEnum + ")" + "{";
            string TestTestScript = fc.Id + "(*){";

            foreach (string testOriginal in TestOriginal.Split(';'))
            {
                if (testOriginal.CompareWildcard(TestTestScript, true))
                {
                    isEnumerable = true;
                }
            }
            if (TestOriginal.Contains(TestScript))
            {
                //This DOES need to exist, this is for nested function calls to user-generated methods!
                isEnumerable = true;
            }
            else if (retstr.ToString().Contains("IEnumerator " + fc.Id))
            {
                isEnumerable = true;
            }
            bool DTFunction = false;
            if (DTFunctions.Contains(fc.Id))
            {
                DTFunction = true;
            }

            if (DTFunction)
            {
                retstr.Append(GenerateLine("{"));
                retstr.Append(Generate("yield return "));
                retstr.Append(Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                retstr.Append(tempString);

                retstr.Append(GenerateLine(");"));
                retstr.Append(Generate("yield return null;"));
                retstr.Append(GenerateLine("}"));
            }
            else if (isEnumerable)
            {
                retstr.Append(GenerateLine("{"));

                retstr.Append(Generate("IEnumerator enumerator = "));
                retstr.Append(Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                retstr.Append(tempString);
                retstr.Append(Generate(");"));

                retstr.Append(GenerateLine("while (true)"));
                retstr.Append(GenerateLine("{"));
                retstr.Append(GenerateLine("bool running = false;"));

                retstr.Append(GenerateLine("try"));
                retstr.Append(GenerateLine("{"));
                retstr.Append(GenerateLine("running = enumerator.MoveNext();"));
                retstr.Append(GenerateLine("if(!running)"));
                retstr.Append(GenerateLine("break;")); //All done, break out of the loop
                retstr.Append(GenerateLine("}"));
                retstr.Append(GenerateLine("catch"));
                retstr.Append(GenerateLine("{"));
                retstr.Append(GenerateLine("break;"));//End it since we are erroring out
                retstr.Append(GenerateLine("}")); //End of catch
                retstr.Append(GenerateLine("yield return enumerator.Current;")); //Let the other things process for a bit here at the end of each enumeration
                retstr.Append(GenerateLine("}")); //End of while
                
                retstr.Append(GenerateLine("}"));
                retstr.Append(GenerateLine("TESTREMOVE")); //Gets removed later and tells it not to print a ; at the end
            }
            else
            {
                retstr.Append(Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
                retstr.Append(tempString);

                retstr.Append(Generate(")"));
            }
            if (FunctionCalls != "")
            {
                retstr.Append(Generate(";")); //We do this because we can't just do ) } .... otherwise we have issues!
                // Add it to the end so that everything is covered 
                //so that lines like 'if(test) callStatement(FunctionCall());'
                //don't error out because of brackets
                retstr.Append(GenerateLine("}"));
                retstr.Append(GenerateLine("TESTREMOVE")); //Gets removed later and tells it not to print a ; at the end
            }

            //Function calls are first
            return FunctionCalls + retstr;
        }