diff --git a/Core/CodeNS/XMLParser.cs b/Core/CodeNS/XMLParser.cs index 8057635e9d5c5852216780b5827beb1648a1b279..d36c2233c5d2a004c540fa2ddb60b2a08b4f0355 100644 --- a/Core/CodeNS/XMLParser.cs +++ b/Core/CodeNS/XMLParser.cs @@ -2,6 +2,7 @@ using Core.DataTypeNS; using Core.FunctionNS; using Core.MemoryNS; +using System.Collections; using System.Xml.Linq; using System.Xml.XPath; @@ -9,6 +10,31 @@ namespace Core.CodeNS { public static class XMLParser { + private static Dictionary<string, string> ExpressionF = new Dictionary<string, string>() + { + {"abs", "ABS"}, + {"arcsin", "ASIN"}, + {"arccos", "ACOS"}, + {"cos", "COS"}, + {"int", "INT"}, + {"ln", "LN"}, + {"log", "LN"}, + {"log10", "LOG10"}, + {"sin", "SIN"}, + {"sqrt", "SQRT"}, + {"tan", "TAN"}, + + {"len", "LEN"}, + + {"tochar", "CHAR"}, + {"tocode", "CODE"}, + + {"random", "RAND"}, + }; + private static ArrayList ImplementedF = new ArrayList() + { + "sgn", "char", "tofixed", "tointeger", "toreal", "tostring", "size" + }; public static List<string> AvailableStructures { get; private set; } private static XElement? xElement = null; @@ -23,6 +49,20 @@ namespace Core.CodeNS } } + public static string functionNameInExpression(string name) + { + if (ExpressionF.ContainsKey(name.ToLower())) + { + return ExpressionF[name]; + } + return null; + } + + public static bool functionIsImplemented(string name) + { + return ImplementedF.Contains(name.ToLower()); + } + public static Structure createStructure(String name) { XElement structureElement = xElement?.XPathSelectElement("./structure[@name='" + name + "']"); @@ -64,13 +104,13 @@ namespace Core.CodeNS createFunction("Main", null); } - public static void createFunction(string name, Queue<object> parameters) + public static void createFunction(string name, Queue<StackObj> parameters) { XElement functionElement = xElement?.XPathSelectElement("./function[@name='" + name + "']"); createFunction(null, functionElement, parameters); } - public static void createFunction(Structure structure, XElement functionElement, Queue<object> parameters) + public static void createFunction(Structure structure, XElement functionElement, Queue<StackObj> parameters) { if (functionElement == null) { @@ -82,7 +122,7 @@ namespace Core.CodeNS Memory.peekFunction().Structure = structure; } - private static void createFunctionP(string name, XElement FunctionElement, Queue<object> parameters) + private static void createFunctionP(string name, XElement FunctionElement, Queue<StackObj> parameters) { Function f = new Function(name, null); @@ -133,7 +173,7 @@ namespace Core.CodeNS parseCommands(FunctionCommands); } - public static void parseParameters(XElement[] FunctionParameters, Queue<object> parameters) + public static void parseParameters(XElement[] FunctionParameters, Queue<StackObj> parameters) { Function f = Memory.peekFunction(); @@ -168,14 +208,14 @@ namespace Core.CodeNS type = type.Replace("[]", "").Trim(); stackObject = new StackObj(name, EDataTypeConverter.TextToDataType(type), arrayDimension); - stackObject.Value = parameters.Dequeue(); + stackObject.Value = parameters.Dequeue().Value; } else { //TODO: dodělat strukturu stackObject = new StackObj(name, EDataTypeConverter.TextToDataType(type)); - stackObject.Value = parameters.Dequeue(); + stackObject.Value = parameters.Dequeue().Value; } f.AddVariable(name, stackObject); diff --git a/Core/CommandsNS/ACommand.cs b/Core/CommandsNS/ACommand.cs index bae52d4deeb3a46d53f7d9a7398da5d05180cce8..66d3cb747c6e2f53dbfeb5afe776f9c4716689f1 100644 --- a/Core/CommandsNS/ACommand.cs +++ b/Core/CommandsNS/ACommand.cs @@ -90,7 +90,7 @@ namespace Core.CommandsNS public override object Clone() { - throw new NotImplementedException(); + return new AssignCommand(this.VariableName, this.Expression); } } diff --git a/Core/DataTypeNS/Array.cs b/Core/DataTypeNS/Array.cs index 77b64532b9a304e63337a4ef47e2b89e16a0b768..12aa3b98a247a58651e1bae77160b9be756d7ae6 100644 --- a/Core/DataTypeNS/Array.cs +++ b/Core/DataTypeNS/Array.cs @@ -18,7 +18,7 @@ namespace Core.DataTypeNS */ private int References; private int Dimensions; - private int Size; + public int Size; private StackObj[] Values; /* * Contructors diff --git a/Core/DataTypeNS/Structure.cs b/Core/DataTypeNS/Structure.cs index f5e775934f33fad2748a4f1ffa29ffd3150ba23c..cd8109faf49f10f1e3202dd4e6d75a201871055b 100644 --- a/Core/DataTypeNS/Structure.cs +++ b/Core/DataTypeNS/Structure.cs @@ -49,7 +49,7 @@ namespace Core.DataTypeNS stackObj.Value = value; } - public void callFunction(string name, Queue<object> parameters) + public void callFunction(string name, Queue<StackObj> parameters) { if (Functions.TryGetValue(name, out XElement element)) { diff --git a/Core/ExpressionSolverNS/ExpressionSolver.cs b/Core/ExpressionSolverNS/ExpressionSolver.cs index a5139f518f3608030d5673b7d1a317b663740e09..b94198174af13fe048b49a9e0d12fa5882890889 100644 --- a/Core/ExpressionSolverNS/ExpressionSolver.cs +++ b/Core/ExpressionSolverNS/ExpressionSolver.cs @@ -66,7 +66,10 @@ namespace Core.ExpressionSolverNS } else { this.Operator = hit.Character; - this.LNode = new ExpressionSolver(this.Expression.Substring(0, hit.Index), false); + if (hit.Index != 0) + { + this.LNode = new ExpressionSolver(this.Expression.Substring(0, hit.Index), false); + } this.RNode = new ExpressionSolver(Expression.Substring(hit.Index + hit.Character.Length), false); } return evaluate(); @@ -81,11 +84,14 @@ namespace Core.ExpressionSolverNS private bool evaluate() { - if (!LNode.IsSolved) + if (LNode != null) { - if (!LNode.Solve()) + if (!LNode.IsSolved) { - return false; + if (!LNode.Solve()) + { + return false; + } } } if (RNode != null) @@ -97,15 +103,36 @@ namespace Core.ExpressionSolverNS return false; } } + } + + if (LNode != null && RNode != null) + { Expression exp = new Expression("a" + this.Operator + "b"); - //Console.WriteLine(LNode.GetValue()); - //Console.WriteLine(RNode.GetValue()); exp.Bind("a", LNode.GetValue()); exp.Bind("b", RNode.GetValue()); this.Result = new StackObj(exp.Eval()); this.IsSolved = true; return true; - } else + } else if (RNode != null && Operator.Equals("!")) + { + if ((bool)RNode.GetValue()) + { + this.Result = new StackObj(false); + } else + { + this.Result = new StackObj(true); + } + this.IsSolved = true; + return true; + } else if (RNode != null && Operator.Equals("-")) + { + Expression exp = new Expression("a * (-1)"); + exp.Bind("a", RNode.GetValue()); + this.Result = new StackObj(exp.Eval()); + this.IsSolved = true; + return true; + } + else { this.Result = LNode.GetStackObj(); this.IsSolved = true; @@ -191,8 +218,6 @@ namespace Core.ExpressionSolverNS */ private void preprocessExpression() { - this.Expression = Expression.Replace("&", "&"); - this.Expression = Expression.Replace(""", "\""); StringBuilder result = new StringBuilder(); bool insideQuotes = false; foreach (char c in Expression) @@ -269,9 +294,19 @@ namespace Core.ExpressionSolverNS { priority = 5; } - else if (index == 6 || index == 7) + else if (index == 6) { priority = 3; + } + else if (index == 7) + { + if (Char.ToString(expression.ElementAt(i + 1)).Equals("(")) + { + priority = 4; + } else + { + priority = 3; + } } else { diff --git a/Core/ExpressionSolverNS/FunctionSolver.cs b/Core/ExpressionSolverNS/FunctionSolver.cs index 32d7e4af29c7e9a4eaf5d2c310d1a6dce743ba77..5adff7b076983ddbd6e36bbf07ae66ab2cf66819 100644 --- a/Core/ExpressionSolverNS/FunctionSolver.cs +++ b/Core/ExpressionSolverNS/FunctionSolver.cs @@ -9,11 +9,12 @@ namespace Core.ExpressionSolverNS using MemoryNS; using Core.CodeNS; using Core.DataTypeNS; + using org.matheval; internal class FunctionSolver : ITreeNode { private Queue<string> UnsolvedPar; - private Queue<object> SolvedPar = new Queue<object>(); + private Queue<StackObj> SolvedPar = new Queue<StackObj>(); private string Name; private ExpressionSolver Solver; private bool FunctionCreated = false; @@ -48,7 +49,18 @@ namespace Core.ExpressionSolverNS Parent.GetStackObj().GetStructure().callFunction(Name, SolvedPar); } else { - XMLParser.createFunction(Name, SolvedPar); + string expressionF = XMLParser.functionNameInExpression(Name); + bool implementedF = XMLParser.functionIsImplemented(Name); + if (expressionF != null) { + SolveFWithExpression(expressionF); + return true; + } else if (implementedF) { + SolveImplementedF(); + return true; + } else + { + XMLParser.createFunction(Name, SolvedPar); + } } FunctionCreated = true; return false; @@ -63,7 +75,7 @@ namespace Core.ExpressionSolverNS while (!ParSolved) { if (!Solver.Solve()) { return false; } - SolvedPar.Enqueue(Solver.GetValue()); + SolvedPar.Enqueue(Solver.GetStackObj()); if (UnsolvedPar.Count() < 1) { ParSolved = true; } else { @@ -72,5 +84,227 @@ namespace Core.ExpressionSolverNS } return true; } + + private void SolveFWithExpression(string fName) + { + StringBuilder st = new StringBuilder(); + st.Append(fName + "("); + bool first = true; + while (SolvedPar.Count > 0) + { + if (!first) + { + st.Append(", "); + } + st.Append(SolvedPar.Dequeue().Value); + if (SolvedPar.Count == 0) + { + st.Append(")"); + } + first = false; + } + Expression exp = new Expression(st.ToString()); + this.Result = new StackObj(exp.Eval()); + this.IsSolved = true; + } + + private void SolveImplementedF() + { + switch (Name.ToLower()) + { + case "sgn": + sgnF(); + break; + case "char": + charF(); + break; + case "tofixed": + toFixedF(); + break; + case "tointeger": + toIntegerF(); + break; + case "toreal": + toRealF(); + break; + case "tostring": + toStringF(); + break; + case "size": + sizeF(); + break; + } + } + + private void sgnF() + { + if (SolvedPar.Count() == 1) + { + StackObj st = SolvedPar.Dequeue(); + if (st != null) + { + if (st.Type == EDataType.INTEGER) + { + Int32 i = (Int32)st.Value; + if (i < 0) { this.Result = new StackObj(-1); } + else if (i == 0) { this.Result = new StackObj(0); } + else if (i > 0) { this.Result = new StackObj(1); } + this.IsSolved = true; + return; + } else if (st.Type == EDataType.REAL) + { + Double i = (Double)st.Value; + if (i < 0) { this.Result = new StackObj(-1); } + else if (i == 0) { this.Result = new StackObj(0); } + else if (i > 0) { this.Result = new StackObj(1); } + this.IsSolved = true; + return; + } + } + else + { + Console.WriteLine("Sgn function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("Sgn function: Wrong number of param"); + } + + } + + private void charF() + { + if (SolvedPar.Count() == 2) + { + StackObj stString = SolvedPar.Dequeue(); + StackObj stIndex = SolvedPar.Dequeue(); + if (stString != null && stIndex != null) + { + string text = (string) stString.Value; + if (Int32.TryParse(stIndex.Value.ToString(), out Int32 num)) + { + this.Result = new StackObj(text.ElementAt(num)); + this.IsSolved = true; + } + } + else + { + Console.WriteLine("Char function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("Char function: Wrong number of param"); + } + } + + private void toFixedF() + { + if (SolvedPar.Count() == 2) + { + StackObj stDouble = SolvedPar.Dequeue(); + StackObj stDigits = SolvedPar.Dequeue(); + if (stDouble != null && stDigits != null) + { + if (Int32.TryParse(stDigits.Value.ToString(), out Int32 num)) + { + this.Result = new StackObj(Math.Round((double)stDouble.Value, num).ToString()); + this.IsSolved = true; + } + } + else + { + Console.WriteLine("ToFixed function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("ToFixed function: Wrong number of param"); + } + } + + private void toIntegerF() + { + if (SolvedPar.Count() == 1) + { + StackObj st = SolvedPar.Dequeue(); + if (st != null && Int32.TryParse(st.Value.ToString(), out Int32 num)) + { + this.Result = new StackObj(num); + this.IsSolved = true; + } + else + { + Console.WriteLine("ToInteger function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("ToInteger function: Wrong number of param"); + } + } + + private void toRealF() + { + if (SolvedPar.Count() == 1) + { + StackObj st = SolvedPar.Dequeue(); + if (st != null && Double.TryParse(st.Value.ToString(), out Double num)) + { + this.Result = new StackObj(num); + this.IsSolved = true; + } + else + { + Console.WriteLine("ToReal function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("ToReal function: Wrong number of param"); + } + } + + private void toStringF() + { + if (SolvedPar.Count() == 1) + { + StackObj st = SolvedPar.Dequeue(); + if (st != null && st.Value != null) + { + this.Result = new StackObj(st.Value.ToString()); + this.IsSolved = true; + } + else + { + Console.WriteLine("ToString function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("ToString function: Wrong number of param"); + } + } + + private void sizeF() + { + if (SolvedPar.Count() == 1) + { + StackObj st = SolvedPar.Dequeue(); + if (st != null && st.IsArray && st.GetArray() != null) + { + this.Result = new StackObj(st.GetArray().Size); + this.IsSolved = true; + } else + { + Console.WriteLine("Size function: Wrong StackObj"); + } + } + else + { + Console.WriteLine("Size function: Wrong number of param"); + } + } } } diff --git a/Core/Tests/test_2.fprg b/Core/Tests/test_2.fprg index b4a3b7b7ca6ab8622b317a76909cb7219f704031..8729de3aafeb81b023a1f3467c592eede1f234fc 100644 --- a/Core/Tests/test_2.fprg +++ b/Core/Tests/test_2.fprg @@ -16,7 +16,7 @@ <assign variable="B" expression="new Real[1]"/> <assign variable="B[0]" expression="1,5"/> <assign variable="A" expression="(((B[0]*74,756+sin(4))/a())-5,265)%6"/> - <if expression="A == 5.0104395009384"> + <if expression="A == 5,0104395009384"> <then> <output expression=""True"" newline="True"/> </then> diff --git a/Core/Tests/test_20.fprg b/Core/Tests/test_20.fprg index 8cd33a2415a3488d8a1abbf79a66eb3cf2cc8e22..61590cefa0082fd8e21a924ccf1e25ab3fe6017b 100644 --- a/Core/Tests/test_20.fprg +++ b/Core/Tests/test_20.fprg @@ -12,7 +12,7 @@ <parameters/> <body> <declare name="Clovek" type="Person" array="False" size=""/> - <assign variable="Clovek" expression="new Person"/> + <assign variable="Clovek" expression="new Person()"/> <assign variable="Clovek.vek" expression="10"/> <if expression="Clovek.vek == 10"> <then> diff --git a/Core/Tests/test_21.fprg b/Core/Tests/test_21.fprg index 029b09ae061321820bccf681cf47e5f9f4258d64..ad9e1f5e207ced0d73f2c545da9a9e83fd81c91c 100644 --- a/Core/Tests/test_21.fprg +++ b/Core/Tests/test_21.fprg @@ -12,7 +12,7 @@ <parameters/> <body> <declare name="Clovek" type="Person" array="False" size=""/> - <assign variable="Clovek" expression="new Person"/> + <assign variable="Clovek" expression="new Person()"/> <assign variable="Clovek.vek" expression="10"/> <if expression="Clovek.getVek() == 10"> <then>