From d9ab80e76ebba277417efbdd8abbe0081163cd76 Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Tue, 16 Apr 2024 00:56:00 +0200 Subject: [PATCH 1/7] re #11255 @20m - convert and info help --- CLI/CommandNS/ConvertCommand.cs | 18 +++++++++++++++--- CLI/CommandNS/InfoCommand.cs | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CLI/CommandNS/ConvertCommand.cs b/CLI/CommandNS/ConvertCommand.cs index 121336a..597a65a 100644 --- a/CLI/CommandNS/ConvertCommand.cs +++ b/CLI/CommandNS/ConvertCommand.cs @@ -2,13 +2,25 @@ { public class ConvertCommand : AbstractCommand { + Dictionary<string, /*Flowgorithm.ProgramTemplate*/string> languages; public override string Name => "Convert"; - public override string Description => "Description for Convert command."; + public override string Description => "Converts flowgorithm program to selected language"; public override void Help() { - // TODO - Console.WriteLine("How to use Help command"); + Console.WriteLine("The Covnert command converts the provided input file to selected language or fprg."); + Console.WriteLine("Syntax: CLI.exe convert <infile> [<template.fpgt>] <outfile.(language extension)>"); + Console.WriteLine(); + Console.WriteLine("Supported languages: "); + + languages.ToList().ForEach(kv => + { + var (language, template) = kv; + Console.WriteLine($" {language,-10} {template}"); + }); + + Console.WriteLine(); + Console.WriteLine("It is also possible to provide custom language template file (.fpgt) as the middle parameter."); } public override void Execute(string[] args) diff --git a/CLI/CommandNS/InfoCommand.cs b/CLI/CommandNS/InfoCommand.cs index 51f7b4f..884aeb7 100644 --- a/CLI/CommandNS/InfoCommand.cs +++ b/CLI/CommandNS/InfoCommand.cs @@ -6,7 +6,7 @@ namespace CLI.CommandNS public class InfoCommand : AbstractCommand { public override string Name => "Info"; - public override string Description => "Description for Info command."; + public override string Description => "Outputs Flowgorithm program info"; public override void Help() { -- GitLab From becebd7ec9a20a027a7cd021f3ad372e67c1bcbe Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Fri, 19 Apr 2024 00:18:24 +0200 Subject: [PATCH 2/7] re #11255 @4h40m - conversion to C sharp --- CLI/CommandNS/ConvertCommand.cs | 37 +++- CLI/Properties/launchSettings.json | 2 +- Core/CodeConversionNS/ACodeConverter.cs | 127 +++++++++++++ Core/CodeConversionNS/CSharpConverter.cs | 179 ++++++++++++++++++ Core/CodeConversionNS/PythonConverter.cs | 93 +++++++++ Core/CodeNS/XMLParser.cs | 5 +- ...AttributeException.cs => XmlExceptions.cs} | 8 + Core/Interpreter.cs | 56 +++++- test.cs | 82 ++++++++ test.fprg | 23 ++- 10 files changed, 600 insertions(+), 12 deletions(-) create mode 100644 Core/CodeConversionNS/ACodeConverter.cs create mode 100644 Core/CodeConversionNS/CSharpConverter.cs create mode 100644 Core/CodeConversionNS/PythonConverter.cs rename Core/ExceptionNS/{XmlMissingAttributeException.cs => XmlExceptions.cs} (58%) create mode 100644 test.cs diff --git a/CLI/CommandNS/ConvertCommand.cs b/CLI/CommandNS/ConvertCommand.cs index 597a65a..09fd0f7 100644 --- a/CLI/CommandNS/ConvertCommand.cs +++ b/CLI/CommandNS/ConvertCommand.cs @@ -1,22 +1,30 @@ -namespace CLI.CommandNS +using Core; +using Core.CodeConversionNS; + +namespace CLI.CommandNS { public class ConvertCommand : AbstractCommand { - Dictionary<string, /*Flowgorithm.ProgramTemplate*/string> languages; + Dictionary<string, ACodeConverter> languages => new Dictionary<string, ACodeConverter> + { + { "csharp", new CSharpConverter() }, + { "python", new PythonConverter() }, + }; + public override string Name => "Convert"; public override string Description => "Converts flowgorithm program to selected language"; public override void Help() { Console.WriteLine("The Covnert command converts the provided input file to selected language or fprg."); - Console.WriteLine("Syntax: CLI.exe convert <infile> [<template.fpgt>] <outfile.(language extension)>"); + Console.WriteLine("Syntax: CLI.exe convert <infile> [csharp|python] <outfile.(language extension)>"); Console.WriteLine(); Console.WriteLine("Supported languages: "); languages.ToList().ForEach(kv => { - var (language, template) = kv; - Console.WriteLine($" {language,-10} {template}"); + var (language, codeConverter) = kv; + Console.WriteLine($" {language,-10} {codeConverter}"); }); Console.WriteLine(); @@ -25,7 +33,24 @@ public override void Execute(string[] args) { - // TODO + if (args.Length < 3) { Help(); return; } + + string inFile = args[1]; + Interpreter interpreter = new Interpreter(inFile); + + var language = args[2]; + var converter = languages[language]; + if (converter == null) + { + Console.WriteLine($"Language {language} is not supported."); + return; + } + + interpreter.CodeConverter = converter; + interpreter.ConvertCode(); + + string outFile = args.Length == 4 ? args[3] : inFile.Replace(".fprg", converter.FileExtension); + interpreter.CodeConverter.WriteToFile(outFile); } } } diff --git a/CLI/Properties/launchSettings.json b/CLI/Properties/launchSettings.json index daa07fc..4ccd676 100644 --- a/CLI/Properties/launchSettings.json +++ b/CLI/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "CLI": { "commandName": "Project", - "commandLineArgs": "info test.fprg", + "commandLineArgs": "convert test.fprg csharp", "workingDirectory": "S:\\Projects\\Flowrunner\\" } } diff --git a/Core/CodeConversionNS/ACodeConverter.cs b/Core/CodeConversionNS/ACodeConverter.cs new file mode 100644 index 0000000..00b7210 --- /dev/null +++ b/Core/CodeConversionNS/ACodeConverter.cs @@ -0,0 +1,127 @@ +using Core.ExceptionNS; +using System.Xml.Linq; + + +namespace Core.CodeConversionNS +{ + public static class Utils + { + public static XElement GetSafeElement(this XElement element, string elementName) + { + XElement? childElement = element.Element(elementName); + if (childElement == null) + { + throw new XmlMissingElementException(elementName); + } + + return childElement; + } + + public static XAttribute GetSafeAttribute(this XElement element, string attributeName) + { + XAttribute? attribute = element.Attribute(attributeName); + if (attribute == null) + { + throw new XmlMissingAttributeException(attributeName); + } + + return attribute; + } + + public static string Repeat(this string value, int count) + { + return new string(value[0], 4 * count); + } + + public static string Indent(int indent) + { + return " ".Repeat(indent); + } + } + + public abstract class ACodeConverter + { + + // Implement methods for translating each command + protected abstract void TranslateAssign(XElement element, int indent); + protected abstract void TranslateBreakpoint(); + protected abstract void TranslateCall(XElement element, int indent); + protected abstract void TranslateComment(XElement element, int indent); + protected abstract void TranslateDeclare(XElement element, int indent); + protected abstract void TranslateDo(XElement element, int indent); + protected abstract void TranslateFor(XElement element, int indent); + protected abstract void TranslateIf(XElement element, int indent); + protected abstract void TranslateInput(XElement element, int indent); + protected abstract void TranslateOutput(XElement element, int indent); + protected abstract void TranslateWhile(XElement element, int indent); + protected abstract void TranslateContinue(int indent); + protected abstract void TranslateBreak(int indent); + protected abstract void TranslateFunction(XElement element, int indent); + protected abstract void TranslateParameters(XElement element, int indent); + protected abstract void TranslateBlock(XElement element, int indent); + protected abstract void TranslateStructure(XElement element, int indent); + + public abstract string FileExtension { get; } + + protected List<string> Program { get; } = new List<string>(); + + protected void AddLine(string line, int indent) + { + Program.Add(Utils.Indent(indent) + line); + } + + + public void WriteToFile(string filePath) + { + using (StreamWriter writer = new StreamWriter(filePath)) + { + Program.ForEach(writer.WriteLine); + } + } + public void GenerateCode(XElement? xRoot) + { + if (xRoot == null) + { + Console.WriteLine("Empty XML document"); + return; + } + + var elements = xRoot.Elements(); + var functions = elements.Where(element => element.Name == "function").ToList(); + var structures = elements.Where(element => element.Name == "structure").ToList(); + + Program.Add("public class Program"); + Program.Add("{"); + functions.ForEach(element => TranslateElement(element, 1)); + structures.ForEach(element => TranslateElement(element, 1)); + Program.Add("}"); + } + + protected void TranslateElement(XElement element, int indent) + { + string statement = element.Name.ToString(); + Action action = statement switch + { + "assign" => () => TranslateAssign(element, indent), + "breakpoint" => () => TranslateBreakpoint(), + "call" => () => TranslateCall(element, indent), + "comment" => () => TranslateComment(element, indent), + "declare" => () => TranslateDeclare(element, indent), + "do" => () => TranslateDo(element, indent), + "for" => () => TranslateFor(element, indent), + "if" => () => TranslateIf(element, indent), + "input" => () => TranslateInput(element, indent), + "output" => () => TranslateOutput(element, indent), + "while" => () => TranslateWhile(element, indent), + "continue" => () => TranslateContinue(indent), + "break" => () => TranslateBreak(indent), + "function" => () => TranslateFunction(element, indent), + "parameters" => () => TranslateParameters(element, indent), + "structure" => () => TranslateStructure(element, indent), + _ => () => Console.WriteLine($"Unknown command=> () => {statement}") + + }; + action.Invoke(); + } + } +} diff --git a/Core/CodeConversionNS/CSharpConverter.cs b/Core/CodeConversionNS/CSharpConverter.cs new file mode 100644 index 0000000..ae3bf79 --- /dev/null +++ b/Core/CodeConversionNS/CSharpConverter.cs @@ -0,0 +1,179 @@ +using System.Xml.Linq; + + +namespace Core.CodeConversionNS +{ + public class CSharpConverter : ACodeConverter + { + public override string FileExtension => ".cs"; + + protected override void TranslateAssign(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"{variable} = {expression};", indent); + } + + protected override void TranslateBreak(int indent) + { + AddLine("break;", indent); + } + + protected override void TranslateBreakpoint() + { + + } + + protected override void TranslateCall(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + AddLine($"{expression};", indent); + } + + protected override void TranslateComment(XElement element, int indent) + { + + } + + protected override void TranslateContinue(int indent) + { + AddLine("continue;", indent); + } + + protected override void TranslateDeclare(XElement element, int indent) + { + string nameString = element.GetSafeAttribute("name").Value; + var names = nameString.Split(", ").ToList(); + string type = element.GetSafeAttribute("type").Value; + + names.ForEach(name => AddLine($"{type} {name};", indent)); + } + + protected override void TranslateDo(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"while({expression})", indent); + AddLine("{", indent); + TranslateBlock(element, indent + 1); + AddLine("}", indent); + } + + protected override void TranslateFor(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + string start = element.GetSafeAttribute("start").Value; + string end = element.GetSafeAttribute("end").Value; + string direction = element.GetSafeAttribute("direction").Value; + string step = element.GetSafeAttribute("step").Value; + + if (direction != "inc") { step = $"-{step}"; } + + AddLine($"for(int {variable} = {start}; {variable} < {end}; {variable} += {step} )", indent); + AddLine("{", indent); + TranslateBlock(element, indent + 1); + AddLine("}", indent); + } + + protected override void TranslateIf(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + XElement thenBlock = element.GetSafeElement("then"); + XElement elseBlock = element.GetSafeElement("else"); + + AddLine($"if({expression})", indent); + AddLine("{", indent); + TranslateBlock(thenBlock, indent + 1); + AddLine("}", indent); + AddLine("else", indent); + AddLine("{", indent); + TranslateBlock(elseBlock, indent + 1); + AddLine("}", indent); + } + + protected override void TranslateInput(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + AddLine($"{variable} = Console.ReadLine();", indent); + } + + protected override void TranslateOutput(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + string newLine = element.GetSafeAttribute("newline").Value; + + string consoleWriteString = newLine == "True" ? "Console.WriteLine" : "Console.Write"; + AddLine($"{consoleWriteString}({expression});", indent); + } + + protected override void TranslateWhile(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"while({expression})", indent); + AddLine("{", indent); + TranslateBlock(element, indent + 1); + AddLine("}", indent); + } + + protected override void TranslateFunction(XElement element, int indent) + { + string name = element.GetSafeAttribute("name").Value; + string type = element.GetSafeAttribute("type").Value; + + AddLine($"public static {(type == "None" ? "void" : type)} {name}(", indent); + TranslateParameters(element.GetSafeElement("parameters"), indent + 1); + AddLine(")", indent); + + AddLine("{", indent); + TranslateBlock(element.GetSafeElement("body"), indent + 1); + AddLine("}", indent); + } + + protected override void TranslateParameters(XElement element, int indent) + { + var parameters = new List<string>(); + element.Elements().ToList().ForEach(param => + { + string name = param.GetSafeAttribute("name").Value; + string type = param.GetSafeAttribute("type").Value; + parameters.Add($"{type} {name}"); + }); + + AddLine(string.Join(", ", parameters), indent); + } + + protected override void TranslateBlock(XElement element, int indent) + { + element.Elements().ToList().ForEach(el => TranslateElement(el, indent)); + } + + protected override void TranslateStructure(XElement element, int indent) + { + string name = element.GetSafeAttribute("name").Value; + List<XElement> xAttributes = element.GetSafeElement("parameters").Elements().ToList(); + List<XElement> methods = element.Elements("function").ToList(); + + var attributes = xAttributes.Select(attr => ( + name: attr.GetSafeAttribute("name").Value, + type: attr.GetSafeAttribute("type").Value + ) + ).ToList(); + + AddLine($"public struct {name} {{", indent); + attributes.ForEach(attr => AddLine($"public {attr.type} {attr.name};", indent + 1)); + + // constructor + AddLine($"public {name}(", indent + 1); + AddLine(string.Join(", ", attributes.Select(attr => $"{attr.type} {attr.name}")), indent + 2); + AddLine(")", indent + 1); + AddLine("{", indent + 1); + attributes.ForEach(attr => AddLine($"this.{attr.name} = {attr.name};", indent + 2)); + AddLine("}", indent + 1); + + methods.ForEach(method => TranslateFunction(method, indent + 1)); + AddLine("}", indent); + } + } +} \ No newline at end of file diff --git a/Core/CodeConversionNS/PythonConverter.cs b/Core/CodeConversionNS/PythonConverter.cs new file mode 100644 index 0000000..0c1412c --- /dev/null +++ b/Core/CodeConversionNS/PythonConverter.cs @@ -0,0 +1,93 @@ +using System.Xml.Linq; + +namespace Core.CodeConversionNS +{ + public class PythonConverter : ACodeConverter + { + public override string FileExtension => ".py"; + + protected override void TranslateAssign(XElement element, int indent) + { + + } + + protected override void TranslateBlock(XElement element, int indent) + { + + } + + protected override void TranslateBreak(int indent) + { + + } + + protected override void TranslateBreakpoint() + { + + } + + protected override void TranslateCall(XElement element, int indent) + { + + } + + protected override void TranslateComment(XElement element, int indent) + { + + } + + protected override void TranslateContinue(int indent) + { + + } + + protected override void TranslateDeclare(XElement element, int indent) + { + + } + + protected override void TranslateDo(XElement element, int indent) + { + + } + + protected override void TranslateFor(XElement element, int indent) + { + + } + + protected override void TranslateFunction(XElement element, int indent) + { + + } + + protected override void TranslateIf(XElement element, int indent) + { + + } + + protected override void TranslateInput(XElement element, int indent) + { + + } + + protected override void TranslateOutput(XElement element, int indent) + { + + } + + protected override void TranslateParameters(XElement element, int indent) + { + + } + + protected override void TranslateWhile(XElement element, int indent) + { + + } + protected override void TranslateStructure(XElement element, int indent) + { + + } + } +} diff --git a/Core/CodeNS/XMLParser.cs b/Core/CodeNS/XMLParser.cs index 93c9ae8..eedcd85 100644 --- a/Core/CodeNS/XMLParser.cs +++ b/Core/CodeNS/XMLParser.cs @@ -40,7 +40,7 @@ namespace Core.CodeNS "sgn", "char", "tofixed", "tointeger", "toreal", "tostring", "size" }; public static List<string> AvailableStructures { get; private set; } - private static XElement? xElement = null; + public static XElement? xElement = null; private static XAttribute getSafeAttribute(this XElement element, string attributeName) { @@ -288,7 +288,8 @@ namespace Core.CodeNS "do" => () => queue.Enqueue(HandleDo(statement)), "break" => () => queue.Enqueue(HandleBreak(statement)), "continue" => () => queue.Enqueue(HandleContinue(statement)), - "breakpoint" => () => { if (DebbugMode) { queue.Enqueue(HandleBreakpoint(statement)); }}, + "breakpoint" => () => { if (DebbugMode) { queue.Enqueue(HandleBreakpoint(statement)); } } + , _ => () => Console.WriteLine("Spatny statement") }; action.Invoke(); diff --git a/Core/ExceptionNS/XmlMissingAttributeException.cs b/Core/ExceptionNS/XmlExceptions.cs similarity index 58% rename from Core/ExceptionNS/XmlMissingAttributeException.cs rename to Core/ExceptionNS/XmlExceptions.cs index 336c89e..152fe4a 100644 --- a/Core/ExceptionNS/XmlMissingAttributeException.cs +++ b/Core/ExceptionNS/XmlExceptions.cs @@ -8,4 +8,12 @@ public XmlMissingAttributeException(string attributeName) : base($"Required attribute '{attributeName}' is missing.") { } } + public class XmlMissingElementException : Exception + { + public XmlMissingElementException() { } + + public XmlMissingElementException(string elementName) + : base($"Required element '{elementName}' is missing.") { } + } + } diff --git a/Core/Interpreter.cs b/Core/Interpreter.cs index 0fa6275..aae0b74 100644 --- a/Core/Interpreter.cs +++ b/Core/Interpreter.cs @@ -1,5 +1,6 @@ namespace Core { + using Core.CodeConversionNS; using Core.CodeNS; using Core.DataTypeNS; using Core.MemoryNS; @@ -10,6 +11,7 @@ public class Interpreter : ARunner { + public ACodeConverter CodeConverter { get; set; } public Dictionary<string, string> ProgramAttributes { get @@ -31,12 +33,64 @@ { long startTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; XmlParser.NoOutput = noOutput; - while (Step()); + while (Step()) ; long endTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; if (time) { Console.WriteLine("Time: " + (endTime - startTime) + " milliseconds"); } } } + public void ConvertCode() + { + CodeConverter.GenerateCode(XmlParser.xElement); + } + + public void RunInternTests() + { + int NumberOfTests = 21; + for (int i = 1; i <= NumberOfTests; i++) + { + string testFileName = "test_" + i + ".fprg"; + InputFile = Directory.GetCurrentDirectory() + "\\Core\\Tests\\" + testFileName; + succesfullyCreated = InitXMLParser(); + Console.Write(testFileName + ": "); + Run(false, false); + } + } + + private bool InitXMLParser() + { + if (InputFile != null) + { + if (!File.Exists(InputFile)) + { + Console.WriteLine("File: " + InputFile + " does not exist."); + return false; + } + InputDocument = XDocument.Load(InputFile); + } + + if (InputDocument.Root == null) + { + Console.WriteLine("Cannot load XDocument: " + InputFile); + return false; + } + validateXDocument(); + + XmlParser.Init(InputDocument.Root); + return true; + } + + private void validateXDocument() + { + var schema = new XmlSchemaSet(); + schema.Add("", "fprg.xsd"); + + InputDocument.Validate(schema, (xdoc, err) => + { + throw new Exception(err.Message); + }); + } + public void PrintHeap() { Console.WriteLine("---------------------\nHalda\n---------------------"); diff --git a/test.cs b/test.cs new file mode 100644 index 0000000..4ca51d5 --- /dev/null +++ b/test.cs @@ -0,0 +1,82 @@ +public class Program +{ + public static void Main( + + ) + { + Integer number; + Integer sum; + number = Console.ReadLine(); + sum = a() + b(); + for(int A = 0; A < a() * 5; A += C ) + { + while(B < a()) + { + A = A + 1; + B = B + 1; + } + if(A == 25) + { + Console.WriteLine("True"); + } + else + { + Console.WriteLine("False"); + } + } + Console.WriteLine(sum); + a(); + } + public static Integer a( + Integer cislo1, Integer cislo2, String znak + ) + { + Integer a; + a = 10; + } + public static Integer b( + + ) + { + Integer b; + b = 5; + } + public struct Person { + public Integer vek; + public Person( + Integer vek + ) + { + this.vek = vek; + } + public static void setVek( + Integer vek + ) + { + this.vek = vek; + } + } + public struct Car { + public String brand; + public Integer wheels; + public Car( + String brand, Integer wheels + ) + { + this.brand = brand; + this.wheels = wheels; + } + public static void setBrand( + String brand + ) + { + this.brand = Audi; + } + public static void setWheels( + Integer wheel + ) + { + this.wheels = 5; + } + } +} diff --git a/test.fprg b/test.fprg index 08d1b0f..90b0d43 100644 --- a/test.fprg +++ b/test.fprg @@ -12,14 +12,33 @@ <parameters/> <body> <declare name="number, sum" type="Integer"/> - <assign variable="number" expression="10"/> + <input variable="number"/> <assign variable="sum" expression="a() + b()"/> + <for variable="A" start="0" end="a() * 5" direction="inc" step="C"> + <while expression="B < a()"> + <assign variable="A" expression="A + 1"/> + <assign variable="B" expression="B + 1"/> + </while> + + <if expression="A == 25"> + <then> + <output expression=""True"" newline="True"/> + </then> + <else> + <output expression=""False"" newline="True"/> + </else> + </if> + </for> <output expression="sum" newline="True"/> <call expression="a()"/> </body> </function> <function name="a" type="Integer" variable="a"> - <parameters/> + <parameters> + <parameter name="cislo1" type="Integer" /> + <parameter name="cislo2" type="Integer" /> + <parameter name="znak" type="String" /> + </parameters> <body> <declare name="a" type="Integer"/> <breakpoint/> -- GitLab From 18fecce5bc62d545d0474ce45db569324ad182bd Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Fri, 19 Apr 2024 00:36:55 +0200 Subject: [PATCH 3/7] re #11255 @20m - rebase --- CLI/CommandNS/ConvertCommand.cs | 8 ++++-- CLI/CommandNS/InfoCommand.cs | 10 +++---- CLI/FileWorker/FileManager.cs | 3 +- Core/ARunner.cs | 11 ++------ Core/Interpreter.cs | 49 --------------------------------- test.cs | 1 - test.fprg | 1 - 7 files changed, 15 insertions(+), 68 deletions(-) diff --git a/CLI/CommandNS/ConvertCommand.cs b/CLI/CommandNS/ConvertCommand.cs index 09fd0f7..061c2b2 100644 --- a/CLI/CommandNS/ConvertCommand.cs +++ b/CLI/CommandNS/ConvertCommand.cs @@ -1,4 +1,5 @@ -using Core; +using CLI.FileWorker; +using Core; using Core.CodeConversionNS; namespace CLI.CommandNS @@ -35,8 +36,11 @@ namespace CLI.CommandNS { if (args.Length < 3) { Help(); return; } + string inFile = args[1]; - Interpreter interpreter = new Interpreter(inFile); + FileManager fileManager = new FileManager(inFile); + if (!fileManager.LoadFile()) { Help(); return; } + Interpreter interpreter = new Interpreter(fileManager.doc); var language = args[2]; var converter = languages[language]; diff --git a/CLI/CommandNS/InfoCommand.cs b/CLI/CommandNS/InfoCommand.cs index 884aeb7..9599bdc 100644 --- a/CLI/CommandNS/InfoCommand.cs +++ b/CLI/CommandNS/InfoCommand.cs @@ -18,13 +18,13 @@ namespace CLI.CommandNS public override void Execute(string[] args) { if (args.Length < 2) { Help(); return; } - string infile = args[1]; + string inFile = args[1]; - FileManager file = new FileManager(infile); - if (!file.LoadFile()) { Help(); return; } - Interpreter interpreter = new Interpreter(file.doc); + FileManager fileManager = new FileManager(inFile); + if (!fileManager.LoadFile()) { Help(); return; } + Interpreter interpreter = new Interpreter(fileManager.doc); - Console.WriteLine($"{"File:",-10}{infile}"); + Console.WriteLine($"{"File:",-10}{inFile}"); Console.WriteLine(); Console.WriteLine($"{"Name:",-10}{interpreter.ProgramAttributes["name"]}"); Console.WriteLine($"{"Author:",-10}{interpreter.ProgramAttributes["authors"]}"); diff --git a/CLI/FileWorker/FileManager.cs b/CLI/FileWorker/FileManager.cs index aa31d56..c084714 100644 --- a/CLI/FileWorker/FileManager.cs +++ b/CLI/FileWorker/FileManager.cs @@ -1,6 +1,5 @@ namespace CLI.FileWorker { - using Core.CodeNS; using System.Xml.Linq; using System.Xml.Schema; public class FileManager @@ -48,7 +47,7 @@ { fs.Close(); - throw new Exception(err.Message); + throw new XmlSchemaException(err.Message); }); if (doc.Root == null) diff --git a/Core/ARunner.cs b/Core/ARunner.cs index 25f8b1f..1af0a1e 100644 --- a/Core/ARunner.cs +++ b/Core/ARunner.cs @@ -1,11 +1,6 @@ using Core.CodeNS; using Core.FunctionNS; using Core.MemoryNS; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Xml.Linq; using System.Xml.Schema; @@ -42,20 +37,20 @@ namespace Core Console.WriteLine("Cannot load XDocument"); return false; } - validateXDocument(); + ValidateXDocument(); XmlParser.Init(InputDocument.Root); return true; } - private void validateXDocument() + private void ValidateXDocument() { var schema = new XmlSchemaSet(); schema.Add("", "fprg.xsd"); InputDocument.Validate(schema, (xdoc, err) => { - throw new Exception(err.Message); + throw new XmlSchemaException(err.Message); }); } } diff --git a/Core/Interpreter.cs b/Core/Interpreter.cs index aae0b74..c9bca26 100644 --- a/Core/Interpreter.cs +++ b/Core/Interpreter.cs @@ -4,10 +4,8 @@ using Core.CodeNS; using Core.DataTypeNS; using Core.MemoryNS; - using FunctionNS; using System.Collections; using System.Xml.Linq; - using System.Xml.Schema; public class Interpreter : ARunner { @@ -44,53 +42,6 @@ CodeConverter.GenerateCode(XmlParser.xElement); } - public void RunInternTests() - { - int NumberOfTests = 21; - for (int i = 1; i <= NumberOfTests; i++) - { - string testFileName = "test_" + i + ".fprg"; - InputFile = Directory.GetCurrentDirectory() + "\\Core\\Tests\\" + testFileName; - succesfullyCreated = InitXMLParser(); - Console.Write(testFileName + ": "); - Run(false, false); - } - } - - private bool InitXMLParser() - { - if (InputFile != null) - { - if (!File.Exists(InputFile)) - { - Console.WriteLine("File: " + InputFile + " does not exist."); - return false; - } - InputDocument = XDocument.Load(InputFile); - } - - if (InputDocument.Root == null) - { - Console.WriteLine("Cannot load XDocument: " + InputFile); - return false; - } - validateXDocument(); - - XmlParser.Init(InputDocument.Root); - return true; - } - - private void validateXDocument() - { - var schema = new XmlSchemaSet(); - schema.Add("", "fprg.xsd"); - - InputDocument.Validate(schema, (xdoc, err) => - { - throw new Exception(err.Message); - }); - } - public void PrintHeap() { Console.WriteLine("---------------------\nHalda\n---------------------"); diff --git a/test.cs b/test.cs index 4ca51d5..66aa05f 100644 --- a/test.cs +++ b/test.cs @@ -6,7 +6,6 @@ public class Program { Integer number; Integer sum; - number = Console.ReadLine(); sum = a() + b(); for(int A = 0; A < a() * 5; A += C ) { diff --git a/test.fprg b/test.fprg index 90b0d43..426b1a4 100644 --- a/test.fprg +++ b/test.fprg @@ -12,7 +12,6 @@ <parameters/> <body> <declare name="number, sum" type="Integer"/> - <input variable="number"/> <assign variable="sum" expression="a() + b()"/> <for variable="A" start="0" end="a() * 5" direction="inc" step="C"> <while expression="B < a()"> -- GitLab From 8f3b98bfb8ab4b7e31b2f0dc2f35449c972c4633 Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Fri, 19 Apr 2024 15:41:32 +0200 Subject: [PATCH 4/7] re #11255 @3h15m - python converter and minor fixes --- Core/CodeConversionNS/ACodeConverter.cs | 32 +++--- Core/CodeConversionNS/CSharpConverter.cs | 94 +++++++++++++---- Core/CodeConversionNS/PythonConverter.cs | 125 ++++++++++++++++++++--- Core/CodeNS/XMLParser.cs | 2 +- Core/Interpreter.cs | 2 +- test.cs | 45 ++++---- test.fprg | 5 +- test.py | 68 ++++++++++++ 8 files changed, 297 insertions(+), 76 deletions(-) create mode 100644 test.py diff --git a/Core/CodeConversionNS/ACodeConverter.cs b/Core/CodeConversionNS/ACodeConverter.cs index 00b7210..2c0106c 100644 --- a/Core/CodeConversionNS/ACodeConverter.cs +++ b/Core/CodeConversionNS/ACodeConverter.cs @@ -1,4 +1,5 @@ using Core.ExceptionNS; +using System.Text; using System.Xml.Linq; @@ -29,14 +30,9 @@ namespace Core.CodeConversionNS } public static string Repeat(this string value, int count) - { - return new string(value[0], 4 * count); - } + => new StringBuilder(value.Length * count).Insert(0, value, count).ToString(); - public static string Indent(int indent) - { - return " ".Repeat(indent); - } + public static string Indent(int indent) => " ".Repeat(indent); } public abstract class ACodeConverter @@ -60,16 +56,16 @@ namespace Core.CodeConversionNS protected abstract void TranslateParameters(XElement element, int indent); protected abstract void TranslateBlock(XElement element, int indent); protected abstract void TranslateStructure(XElement element, int indent); + protected abstract string TranslateType(string type); + protected abstract void GenerateProgramShellStart(); + protected abstract void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures); + protected abstract void GenerateProgramShellEnd(); public abstract string FileExtension { get; } protected List<string> Program { get; } = new List<string>(); - protected void AddLine(string line, int indent) - { - Program.Add(Utils.Indent(indent) + line); - } - + protected void AddLine(string line, int indent) => Program.Add(Utils.Indent(indent) + line); public void WriteToFile(string filePath) { @@ -78,7 +74,8 @@ namespace Core.CodeConversionNS Program.ForEach(writer.WriteLine); } } - public void GenerateCode(XElement? xRoot) + + public void Convert(XElement? xRoot) { if (xRoot == null) { @@ -90,11 +87,9 @@ namespace Core.CodeConversionNS var functions = elements.Where(element => element.Name == "function").ToList(); var structures = elements.Where(element => element.Name == "structure").ToList(); - Program.Add("public class Program"); - Program.Add("{"); - functions.ForEach(element => TranslateElement(element, 1)); - structures.ForEach(element => TranslateElement(element, 1)); - Program.Add("}"); + GenerateProgramShellStart(); + GenerateProgramInsides(functions, structures); + GenerateProgramShellEnd(); } protected void TranslateElement(XElement element, int indent) @@ -119,7 +114,6 @@ namespace Core.CodeConversionNS "parameters" => () => TranslateParameters(element, indent), "structure" => () => TranslateStructure(element, indent), _ => () => Console.WriteLine($"Unknown command=> () => {statement}") - }; action.Invoke(); } diff --git a/Core/CodeConversionNS/CSharpConverter.cs b/Core/CodeConversionNS/CSharpConverter.cs index ae3bf79..972464a 100644 --- a/Core/CodeConversionNS/CSharpConverter.cs +++ b/Core/CodeConversionNS/CSharpConverter.cs @@ -1,4 +1,5 @@ -using System.Xml.Linq; +using System.Text.RegularExpressions; +using System.Xml.Linq; namespace Core.CodeConversionNS @@ -7,6 +8,23 @@ namespace Core.CodeConversionNS { public override string FileExtension => ".cs"; + protected override void GenerateProgramShellStart() + { + AddLine("public class Program", 0); + AddLine("{", 0); + } + + protected override void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures) + { + functions?.ForEach(element => TranslateElement(element, 1)); + structures?.ForEach(element => TranslateElement(element, 1)); + } + + protected override void GenerateProgramShellEnd() + { + AddLine("}", 0); + } + protected override void TranslateAssign(XElement element, int indent) { string variable = element.GetSafeAttribute("variable").Value; @@ -45,20 +63,12 @@ namespace Core.CodeConversionNS { string nameString = element.GetSafeAttribute("name").Value; var names = nameString.Split(", ").ToList(); - string type = element.GetSafeAttribute("type").Value; + string type = TranslateType(element.GetSafeAttribute("type").Value); names.ForEach(name => AddLine($"{type} {name};", indent)); } - protected override void TranslateDo(XElement element, int indent) - { - string expression = element.GetSafeAttribute("expression").Value; - - AddLine($"while({expression})", indent); - AddLine("{", indent); - TranslateBlock(element, indent + 1); - AddLine("}", indent); - } + protected override void TranslateDo(XElement element, int indent) => TranslateWhile(element, indent); protected override void TranslateFor(XElement element, int indent) { @@ -95,7 +105,19 @@ namespace Core.CodeConversionNS protected override void TranslateInput(XElement element, int indent) { string variable = element.GetSafeAttribute("variable").Value; - AddLine($"{variable} = Console.ReadLine();", indent); + + AddLine("string _input = Console.ReadLine();", indent); + AddLine("if (int.TryParse(_input, out int intValue))", indent); + AddLine($"{variable} = intValue;", indent + 1); + + AddLine("else if (double.TryParse(_input, out double doubleValue))", indent); + AddLine($"{variable} = doubleValue;", indent + 1); + + AddLine("else if (DateTime.TryParse(_input, out DateTime dateTimeValue))", indent); + AddLine($"{variable} = dateTimeValue;", indent + 1); + + AddLine("else", indent); + AddLine($"{variable} = _input;", indent + 1); } protected override void TranslateOutput(XElement element, int indent) @@ -120,11 +142,20 @@ namespace Core.CodeConversionNS protected override void TranslateFunction(XElement element, int indent) { string name = element.GetSafeAttribute("name").Value; - string type = element.GetSafeAttribute("type").Value; + string type = TranslateType(element.GetSafeAttribute("type").Value); + type = type == "None" ? "void" : type; + var parameters = element.GetSafeElement("parameters"); - AddLine($"public static {(type == "None" ? "void" : type)} {name}(", indent); - TranslateParameters(element.GetSafeElement("parameters"), indent + 1); - AddLine(")", indent); + if (!parameters.Elements().Any()) + { + AddLine($"public static {type} {name}()", indent); + } + else + { + AddLine($"public static {type} {name}(", indent); + TranslateParameters(element.GetSafeElement("parameters"), indent + 1); + AddLine(")", indent); + } AddLine("{", indent); TranslateBlock(element.GetSafeElement("body"), indent + 1); @@ -137,7 +168,7 @@ namespace Core.CodeConversionNS element.Elements().ToList().ForEach(param => { string name = param.GetSafeAttribute("name").Value; - string type = param.GetSafeAttribute("type").Value; + string type = TranslateType(param.GetSafeAttribute("type").Value); parameters.Add($"{type} {name}"); }); @@ -157,7 +188,7 @@ namespace Core.CodeConversionNS var attributes = xAttributes.Select(attr => ( name: attr.GetSafeAttribute("name").Value, - type: attr.GetSafeAttribute("type").Value + type: TranslateType(attr.GetSafeAttribute("type").Value) ) ).ToList(); @@ -175,5 +206,32 @@ namespace Core.CodeConversionNS methods.ForEach(method => TranslateFunction(method, indent + 1)); AddLine("}", indent); } + + protected override string TranslateType(string type) + { + if (!type.Contains('[')) return type switch + { + "Integer" => "int", + "Real" => "double", + "String" => "string", + "Boolean" => "bool", + "Char" => "char", + _ => type + }; + + string typeWithoutBrackets = type.Substring(0, type.IndexOf('[')); + int bracketCount = Regex.Matches(type, @"\[\]").Count; + + string result = typeWithoutBrackets switch + { + "Integer" => "int", + "Real" => "double", + "String" => "string", + "Boolean" => "bool", + "Char" => "char", + _ => type + }; + return result + "[]".Repeat(bracketCount); + } } } \ No newline at end of file diff --git a/Core/CodeConversionNS/PythonConverter.cs b/Core/CodeConversionNS/PythonConverter.cs index 0c1412c..caecc47 100644 --- a/Core/CodeConversionNS/PythonConverter.cs +++ b/Core/CodeConversionNS/PythonConverter.cs @@ -6,19 +6,34 @@ namespace Core.CodeConversionNS { public override string FileExtension => ".py"; - protected override void TranslateAssign(XElement element, int indent) + protected override void GenerateProgramShellStart() { } + + protected override void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures) { + functions?.ForEach(element => TranslateElement(element, 0)); + structures?.ForEach(element => TranslateElement(element, 0)); + } + protected override void GenerateProgramShellEnd() + { + AddLine("", 0); + AddLine("", 0); + AddLine("if __name__ == \"__main__\":", 0); + AddLine("main()", 1); } - protected override void TranslateBlock(XElement element, int indent) + protected override void TranslateAssign(XElement element, int indent) { + string variable = element.GetSafeAttribute("variable").Value; + string expression = element.GetSafeAttribute("expression").Value; + variable = variable.Replace("this.", "self."); + AddLine($"{variable} = {expression}", indent); } protected override void TranslateBreak(int indent) { - + AddLine("break", indent); } protected override void TranslateBreakpoint() @@ -28,7 +43,8 @@ namespace Core.CodeConversionNS protected override void TranslateCall(XElement element, int indent) { - + string expression = element.GetSafeAttribute("expression").Value; + AddLine($"{expression};", indent); } protected override void TranslateComment(XElement element, int indent) @@ -38,56 +54,135 @@ namespace Core.CodeConversionNS protected override void TranslateContinue(int indent) { - + AddLine("continue", indent); } protected override void TranslateDeclare(XElement element, int indent) { + string nameString = element.GetSafeAttribute("name").Value; + var names = nameString.Split(", ").ToList(); + names.ForEach(name => AddLine($"{name} = None", indent)); } - protected override void TranslateDo(XElement element, int indent) + protected override void TranslateDo(XElement element, int indent) => TranslateWhile(element, indent); + + protected override void TranslateFor(XElement element, int indent) { + string variable = element.GetSafeAttribute("variable").Value; + string start = element.GetSafeAttribute("start").Value; + string end = element.GetSafeAttribute("end").Value; + string direction = element.GetSafeAttribute("direction").Value; + string step = element.GetSafeAttribute("step").Value; + + if (direction != "inc") { step = $"-{step}"; } + AddLine($"for {variable} in range({start}, {end}, {step}):", indent); + TranslateBlock(element, indent + 1); } - protected override void TranslateFor(XElement element, int indent) + protected override void TranslateIf(XElement element, int indent) { + string expression = element.GetSafeAttribute("expression").Value; + XElement thenBlock = element.GetSafeElement("then"); + XElement elseBlock = element.GetSafeElement("else"); + AddLine($"if {expression}:", indent); + TranslateBlock(thenBlock, indent + 1); + AddLine("else:", indent); + TranslateBlock(elseBlock, indent + 1); } - protected override void TranslateFunction(XElement element, int indent) + protected override void TranslateInput(XElement element, int indent) { - + string variable = element.GetSafeAttribute("variable").Value; + AddLine($"{variable} = input()", indent); } - protected override void TranslateIf(XElement element, int indent) + protected override void TranslateOutput(XElement element, int indent) { + string expression = element.GetSafeAttribute("expression").Value; + string newLine = element.GetSafeAttribute("newline").Value; + string end = newLine == "True" ? "\\n" : ""; + AddLine($"print({expression}, end=\"{end}\")", indent); } - protected override void TranslateInput(XElement element, int indent) + protected override void TranslateWhile(XElement element, int indent) { + string expression = element.GetSafeAttribute("expression").Value; + AddLine($"while {expression}:", indent); + TranslateBlock(element, indent + 1); } - protected override void TranslateOutput(XElement element, int indent) + protected override void TranslateFunction(XElement element, int indent) { + string name = element.GetSafeAttribute("name").Value; + var parameters = element.GetSafeElement("parameters"); + if (name == "Main") { name = name.ToLower(); } + AddLine("", 0); + AddLine("", 0); + if (!parameters.Elements().Any()) + { + AddLine($"def {name}():", indent); + } + else + { + AddLine($"def {name}(", indent); + TranslateParameters(parameters, indent + 1); + AddLine("):", indent); + } + + TranslateBlock(element.GetSafeElement("body"), indent + 1); } protected override void TranslateParameters(XElement element, int indent) { - + var parameters = element.Elements().Select(param => param.GetSafeAttribute("name").Value); + AddLine(string.Join(", ", parameters), indent); } - protected override void TranslateWhile(XElement element, int indent) + protected override void TranslateBlock(XElement element, int indent) { - + element.Elements().ToList().ForEach(el => TranslateElement(el, indent)); } + protected override void TranslateStructure(XElement element, int indent) { + string name = element.GetSafeAttribute("name").Value; + List<XElement> xAttributes = element.GetSafeElement("parameters").Elements().ToList(); + List<XElement> methods = element.Elements("function").ToList(); + + var attributes = xAttributes.Select(attr => attr.GetSafeAttribute("name").Value).ToList(); + attributes.Insert(0, "self"); + + AddLine("", 0); + AddLine("", 0); + AddLine($"class {name}:", indent); + // constructor + AddLine($"def __init__(", indent + 1); + AddLine(string.Join(", ", attributes), indent + 2); + AddLine("):", indent + 1); + attributes.ForEach(attr => AddLine($"self.{attr} = {attr}", indent + 2)); + + methods.ForEach(method => + { + string name = method.GetSafeAttribute("name").Value; + var parameters = method.GetSafeElement("parameters"); + + AddLine("", 0); + AddLine("", 0); + AddLine($"def {name}(self, ", indent); + TranslateParameters(parameters, indent + 1); + AddLine("):", indent); + + TranslateBlock(method.GetSafeElement("body"), indent + 1); + }); } + + protected override string TranslateType(string type) => ""; } } diff --git a/Core/CodeNS/XMLParser.cs b/Core/CodeNS/XMLParser.cs index eedcd85..5ffe0ba 100644 --- a/Core/CodeNS/XMLParser.cs +++ b/Core/CodeNS/XMLParser.cs @@ -327,7 +327,7 @@ namespace Core.CodeNS private static AStatement HandleInput(XElement statement) { string variableName = statement.getSafeAttribute("variable").Value; - string prompt = statement.getSafeAttribute("prompt").Value; + string prompt = ""; // statement.getSafeAttribute("prompt").Value; IXmlLineInfo info = statement; return new InputStatement(variableName, prompt, info.LineNumber); diff --git a/Core/Interpreter.cs b/Core/Interpreter.cs index c9bca26..e46c90c 100644 --- a/Core/Interpreter.cs +++ b/Core/Interpreter.cs @@ -39,7 +39,7 @@ public void ConvertCode() { - CodeConverter.GenerateCode(XmlParser.xElement); + CodeConverter.Convert(XmlParser.xElement); } public void PrintHeap() diff --git a/test.cs b/test.cs index 66aa05f..7fb5492 100644 --- a/test.cs +++ b/test.cs @@ -1,11 +1,18 @@ public class Program { - public static void Main( - - ) + public static void Main() { - Integer number; - Integer sum; + int[][] number; + int[][] sum; + string _input = Console.ReadLine(); + if (int.TryParse(_input, out int intValue)) + number = intValue; + else if (double.TryParse(_input, out double doubleValue)) + number = doubleValue; + else if (DateTime.TryParse(_input, out DateTime dateTimeValue)) + number = dateTimeValue; + else + number = _input; sum = a() + b(); for(int A = 0; A < a() * 5; A += C ) { @@ -26,53 +33,51 @@ public class Program Console.WriteLine(sum); a(); } - public static Integer a( - Integer cislo1, Integer cislo2, String znak + public static Person[][] a( + int cislo1, int cislo2, string znak ) { - Integer a; + int a; a = 10; } - public static Integer b( - - ) + public static int b() { - Integer b; + int b; b = 5; } public struct Person { - public Integer vek; + public int vek; public Person( - Integer vek + int vek ) { this.vek = vek; } public static void setVek( - Integer vek + int vek ) { this.vek = vek; } } public struct Car { - public String brand; - public Integer wheels; + public string brand; + public int wheels; public Car( - String brand, Integer wheels + string brand, int wheels ) { this.brand = brand; this.wheels = wheels; } public static void setBrand( - String brand + string brand ) { this.brand = Audi; } public static void setWheels( - Integer wheel + int wheel ) { this.wheels = 5; diff --git a/test.fprg b/test.fprg index 426b1a4..49194f9 100644 --- a/test.fprg +++ b/test.fprg @@ -11,7 +11,8 @@ <function name="Main" type="None" variable=""> <parameters/> <body> - <declare name="number, sum" type="Integer"/> + <declare name="number, sum" type="Integer[][]"/> + <input variable="number"/> <assign variable="sum" expression="a() + b()"/> <for variable="A" start="0" end="a() * 5" direction="inc" step="C"> <while expression="B < a()"> @@ -32,7 +33,7 @@ <call expression="a()"/> </body> </function> - <function name="a" type="Integer" variable="a"> + <function name="a" type="Person[]" variable="a"> <parameters> <parameter name="cislo1" type="Integer" /> <parameter name="cislo2" type="Integer" /> diff --git a/test.py b/test.py new file mode 100644 index 0000000..46a3adc --- /dev/null +++ b/test.py @@ -0,0 +1,68 @@ + + +def main(): + number = None + sum = None + number = input() + sum = a() + b() + for A in range(0, a() * 5, C): + while B < a(): + A = A + 1 + B = B + 1 + if A == 25: + print("True", end="\n") + else: + print("False", end="\n") + print(sum, end="\n") + a(); + + +def a( + cislo1, cislo2, znak +): + a = None + a = 10 + + +def b(): + b = None + b = 5 + + +class Person: + def __init__( + self, vek + ): + self.self = self + self.vek = vek + + +def setVek(self, + vek +): + self.vek = vek + + +class Car: + def __init__( + self, brand, wheels + ): + self.self = self + self.brand = brand + self.wheels = wheels + + +def setBrand(self, + brand +): + self.brand = Audi + + +def setWheels(self, + wheel +): + self.wheels = 5 + + +if __name__ == "__main__": + main() -- GitLab From 0d7c2c2eedadbe428fc299fe177b936f40e194ce Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Sat, 20 Apr 2024 20:04:31 +0200 Subject: [PATCH 5/7] re #11255 @3h30m - pseudocode converter --- CLI/CommandNS/ConvertCommand.cs | 2 +- CLI/FileWorker/FileManager.cs | 4 - CLI/Properties/launchSettings.json | 2 +- Core/CodeConversionNS/CSharpConverter.cs | 21 ++- Core/CodeConversionNS/PseudocodeConverter.cs | 188 +++++++++++++++++++ Core/CodeConversionNS/PythonConverter.cs | 43 +++-- test.cs | 16 +- test.fcode | 66 +++++++ test.fprg | 4 +- test.py | 31 +-- 10 files changed, 335 insertions(+), 42 deletions(-) create mode 100644 Core/CodeConversionNS/PseudocodeConverter.cs create mode 100644 test.fcode diff --git a/CLI/CommandNS/ConvertCommand.cs b/CLI/CommandNS/ConvertCommand.cs index 061c2b2..f69e98b 100644 --- a/CLI/CommandNS/ConvertCommand.cs +++ b/CLI/CommandNS/ConvertCommand.cs @@ -10,6 +10,7 @@ namespace CLI.CommandNS { { "csharp", new CSharpConverter() }, { "python", new PythonConverter() }, + { "fcode", new PseudocodeConverter() }, }; public override string Name => "Convert"; @@ -36,7 +37,6 @@ namespace CLI.CommandNS { if (args.Length < 3) { Help(); return; } - string inFile = args[1]; FileManager fileManager = new FileManager(inFile); if (!fileManager.LoadFile()) { Help(); return; } diff --git a/CLI/FileWorker/FileManager.cs b/CLI/FileWorker/FileManager.cs index c084714..5533ec5 100644 --- a/CLI/FileWorker/FileManager.cs +++ b/CLI/FileWorker/FileManager.cs @@ -6,10 +6,8 @@ { public string FileName { get; } private string Path { get; } - public XDocument doc { get; set; } - public FileManager(string path) { Path = path; @@ -24,7 +22,6 @@ string[] parts = path.Split(@"\"); FileName = parts[parts.Length - 1]; } - } public bool LoadFile() @@ -39,7 +36,6 @@ doc = XDocument.Load(fs); - var schema = new XmlSchemaSet(); schema.Add("", "fprg.xsd"); diff --git a/CLI/Properties/launchSettings.json b/CLI/Properties/launchSettings.json index 4ccd676..5f203e5 100644 --- a/CLI/Properties/launchSettings.json +++ b/CLI/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "CLI": { "commandName": "Project", - "commandLineArgs": "convert test.fprg csharp", + "commandLineArgs": "convert test.fprg fcode", "workingDirectory": "S:\\Projects\\Flowrunner\\" } } diff --git a/Core/CodeConversionNS/CSharpConverter.cs b/Core/CodeConversionNS/CSharpConverter.cs index 972464a..8063c11 100644 --- a/Core/CodeConversionNS/CSharpConverter.cs +++ b/Core/CodeConversionNS/CSharpConverter.cs @@ -68,7 +68,16 @@ namespace Core.CodeConversionNS names.ForEach(name => AddLine($"{type} {name};", indent)); } - protected override void TranslateDo(XElement element, int indent) => TranslateWhile(element, indent); + protected override void TranslateDo(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + + AddLine("do", indent); + AddLine("{", indent); + TranslateBlock(element, indent + 1); + AddLine("}", indent); + AddLine($"while({expression});", indent); + } protected override void TranslateFor(XElement element, int indent) { @@ -143,9 +152,12 @@ namespace Core.CodeConversionNS { string name = element.GetSafeAttribute("name").Value; string type = TranslateType(element.GetSafeAttribute("type").Value); - type = type == "None" ? "void" : type; + string variable = element.GetSafeAttribute("variable").Value; var parameters = element.GetSafeElement("parameters"); + bool isNone = type == "None"; + type = isNone ? "void" : type; + if (!parameters.Elements().Any()) { AddLine($"public static {type} {name}()", indent); @@ -159,7 +171,9 @@ namespace Core.CodeConversionNS AddLine("{", indent); TranslateBlock(element.GetSafeElement("body"), indent + 1); + if (!isNone) AddLine($"return {variable};", indent + 1); AddLine("}", indent); + AddLine("", 0); } protected override void TranslateParameters(XElement element, int indent) @@ -202,9 +216,12 @@ namespace Core.CodeConversionNS AddLine("{", indent + 1); attributes.ForEach(attr => AddLine($"this.{attr.name} = {attr.name};", indent + 2)); AddLine("}", indent + 1); + AddLine("", 0); methods.ForEach(method => TranslateFunction(method, indent + 1)); AddLine("}", indent); + + AddLine("", 0); } protected override string TranslateType(string type) diff --git a/Core/CodeConversionNS/PseudocodeConverter.cs b/Core/CodeConversionNS/PseudocodeConverter.cs new file mode 100644 index 0000000..26bd9e3 --- /dev/null +++ b/Core/CodeConversionNS/PseudocodeConverter.cs @@ -0,0 +1,188 @@ +using System.Xml.Linq; + +namespace Core.CodeConversionNS +{ + public class PseudocodeConverter : ACodeConverter + { + public override string FileExtension => ".fcode"; + + protected override void GenerateProgramShellStart() { } + + protected override void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures) + { + functions?.ForEach(element => TranslateElement(element, 0)); + structures?.ForEach(element => TranslateElement(element, 0)); + } + + protected override void GenerateProgramShellEnd() { } + + protected override void TranslateAssign(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"Assign {variable} = {expression}", indent); + } + + protected override void TranslateBreak(int indent) + { + AddLine("Break", indent); + } + + protected override void TranslateBreakpoint() + { + + } + + protected override void TranslateCall(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + AddLine($"Call {expression}", indent); + } + + protected override void TranslateComment(XElement element, int indent) + { + + } + + protected override void TranslateContinue(int indent) + { + AddLine("Continue", indent); + } + + protected override void TranslateDeclare(XElement element, int indent) + { + string nameString = element.GetSafeAttribute("name").Value; + string type = TranslateType(element.GetSafeAttribute("type").Value); + + AddLine($"Declare {type} {nameString}", indent); + AddLine("", 0); + } + + protected override void TranslateDo(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"Do {expression}", indent); + TranslateBlock(element, indent + 1); + AddLine("End", indent); + } + + protected override void TranslateFor(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + string start = element.GetSafeAttribute("start").Value; + string end = element.GetSafeAttribute("end").Value; + string direction = element.GetSafeAttribute("direction").Value; + string step = element.GetSafeAttribute("step").Value; + + if (direction != "inc") { step = $"-{step}"; } + + AddLine($"For {variable} = {start} to {end} {(direction != "inc" ? "decreasing" : "")} step {step}", indent); + TranslateBlock(element, indent + 1); + AddLine("End", indent); + } + + protected override void TranslateIf(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + XElement thenBlock = element.GetSafeElement("then"); + XElement elseBlock = element.GetSafeElement("else"); + + AddLine($"If {expression}", indent); + TranslateBlock(thenBlock, indent + 1); + AddLine("Else", indent); + TranslateBlock(elseBlock, indent + 1); + AddLine("End", indent); + } + + protected override void TranslateInput(XElement element, int indent) + { + string variable = element.GetSafeAttribute("variable").Value; + AddLine($"Input = {variable}", indent); + } + + protected override void TranslateOutput(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + // newLine informace se v pseudokódu zahazuje + string newLine = element.GetSafeAttribute("newline").Value; + + AddLine($"Output {expression}", indent); + } + + protected override void TranslateWhile(XElement element, int indent) + { + string expression = element.GetSafeAttribute("expression").Value; + + AddLine($"While {expression}", indent); + TranslateBlock(element, indent + 1); + AddLine("End", indent); + } + + protected override void TranslateFunction(XElement element, int indent) + { + string name = element.GetSafeAttribute("name").Value; + string type = TranslateType(element.GetSafeAttribute("type").Value); + string variable = element.GetSafeAttribute("variable").Value; + var parameters = element.GetSafeElement("parameters"); + + if (!parameters.Elements().Any()) + { + AddLine($"Function {name}", indent); + } + else + { + AddLine($"Function {name} (", indent); + TranslateParameters(element.GetSafeElement("parameters"), indent + 1); + AddLine(")", indent); + } + TranslateBlock(element.GetSafeElement("body"), indent + 1); + if (type != "None") { AddLine($"Return {type} {variable}", indent + 1); } + AddLine("End", indent); + AddLine("", 0); + } + + protected override void TranslateParameters(XElement element, int indent) + { + var parameters = new List<string>(); + element.Elements().ToList().ForEach(param => + { + string name = param.GetSafeAttribute("name").Value; + string type = TranslateType(param.GetSafeAttribute("type").Value); + parameters.Add($"{type} {name}"); + }); + + AddLine(string.Join(", ", parameters), indent); + } + + protected override void TranslateBlock(XElement element, int indent) + { + element.Elements().ToList().ForEach(el => TranslateElement(el, indent)); + } + + protected override void TranslateStructure(XElement element, int indent) + { + string name = element.GetSafeAttribute("name").Value; + List<XElement> xAttributes = element.GetSafeElement("parameters").Elements().ToList(); + List<XElement> methods = element.Elements("function").ToList(); + + var attributes = xAttributes.Select(attr => ( + name: attr.GetSafeAttribute("name").Value, + type: TranslateType(attr.GetSafeAttribute("type").Value) + ) + ).ToList(); + + AddLine($"Structure {name} (", indent); + AddLine(string.Join(", ", attributes.Select(attr => $"{attr.type} {attr.name}")), indent + 2); + AddLine(")", indent + 1); + AddLine("", 0); + + methods.ForEach(method => TranslateFunction(method, indent + 1)); + AddLine("End", indent); + AddLine("", 0); + } + + protected override string TranslateType(string type) => type; + } +} diff --git a/Core/CodeConversionNS/PythonConverter.cs b/Core/CodeConversionNS/PythonConverter.cs index caecc47..13fe860 100644 --- a/Core/CodeConversionNS/PythonConverter.cs +++ b/Core/CodeConversionNS/PythonConverter.cs @@ -16,8 +16,6 @@ namespace Core.CodeConversionNS protected override void GenerateProgramShellEnd() { - AddLine("", 0); - AddLine("", 0); AddLine("if __name__ == \"__main__\":", 0); AddLine("main()", 1); } @@ -44,7 +42,7 @@ namespace Core.CodeConversionNS protected override void TranslateCall(XElement element, int indent) { string expression = element.GetSafeAttribute("expression").Value; - AddLine($"{expression};", indent); + AddLine(expression, indent); } protected override void TranslateComment(XElement element, int indent) @@ -119,11 +117,12 @@ namespace Core.CodeConversionNS protected override void TranslateFunction(XElement element, int indent) { string name = element.GetSafeAttribute("name").Value; + string type = TranslateType(element.GetSafeAttribute("type").Value); + string variable = element.GetSafeAttribute("variable").Value; var parameters = element.GetSafeElement("parameters"); + if (name == "Main") { name = name.ToLower(); } - AddLine("", 0); - AddLine("", 0); if (!parameters.Elements().Any()) { AddLine($"def {name}():", indent); @@ -136,6 +135,9 @@ namespace Core.CodeConversionNS } TranslateBlock(element.GetSafeElement("body"), indent + 1); + if (type != "None") AddLine($"return {variable}", indent + 1); + AddLine("", 0); + AddLine("", 0); } protected override void TranslateParameters(XElement element, int indent) @@ -158,8 +160,6 @@ namespace Core.CodeConversionNS var attributes = xAttributes.Select(attr => attr.GetSafeAttribute("name").Value).ToList(); attributes.Insert(0, "self"); - AddLine("", 0); - AddLine("", 0); AddLine($"class {name}:", indent); // constructor @@ -167,20 +167,33 @@ namespace Core.CodeConversionNS AddLine(string.Join(", ", attributes), indent + 2); AddLine("):", indent + 1); attributes.ForEach(attr => AddLine($"self.{attr} = {attr}", indent + 2)); + AddLine("", 0); + AddLine("", 0); - methods.ForEach(method => + methods + // hack aby to mělo indexy + .Select((m, i) => (method: m, index: i)) + .ToList().ForEach((indexedMethod) => { - string name = method.GetSafeAttribute("name").Value; + var (method, index) = indexedMethod; + + string name = indexedMethod.method.GetSafeAttribute("name").Value; var parameters = method.GetSafeElement("parameters"); - AddLine("", 0); - AddLine("", 0); - AddLine($"def {name}(self, ", indent); - TranslateParameters(parameters, indent + 1); - AddLine("):", indent); + AddLine($"def {name}(self, ", indent + 1); + TranslateParameters(parameters, indent + 2); + AddLine("):", indent + 1); + + TranslateBlock(method.GetSafeElement("body"), indent + 2); - TranslateBlock(method.GetSafeElement("body"), indent + 1); + if (index != methods.Count - 1) + { + AddLine("", 0); + AddLine("", 0); + } }); + AddLine("", 0); + AddLine("", 0); } protected override string TranslateType(string type) => ""; diff --git a/test.cs b/test.cs index 7fb5492..1e3006d 100644 --- a/test.cs +++ b/test.cs @@ -33,18 +33,23 @@ public class Program Console.WriteLine(sum); a(); } + public static Person[][] a( int cislo1, int cislo2, string znak ) { int a; a = 10; + return a; } + public static int b() { int b; b = 5; + return b; } + public struct Person { public int vek; public Person( @@ -53,13 +58,16 @@ public class Program { this.vek = vek; } + public static void setVek( int vek ) { this.vek = vek; } + } + public struct Car { public string brand; public int wheels; @@ -70,17 +78,21 @@ public class Program this.brand = brand; this.wheels = wheels; } + public static void setBrand( string brand ) { - this.brand = Audi; + this.brand = brand; } + public static void setWheels( int wheel ) { - this.wheels = 5; + this.wheels = wheel; } + } + } diff --git a/test.fcode b/test.fcode new file mode 100644 index 0000000..28db4ee --- /dev/null +++ b/test.fcode @@ -0,0 +1,66 @@ +Function Main + Declare Integer[][] number, sum + + Input = number + Assign sum = a() + b() + For A = 0 to a() * 5 step C + While B < a() + Assign A = A + 1 + Assign B = B + 1 + End + If A == 25 + Output "True" + Else + Output "False" + End + End + Output sum + Call a() +End + +Function a ( + Integer cislo1, Integer cislo2, String znak +) + Declare Integer a + + Assign a = 10 + Return Person[] a +End + +Function b + Declare Integer b + + Assign b = 5 + Return Integer b +End + +Structure Person ( + Integer vek + ) + + Function setVek ( + Integer vek + ) + Assign this.vek = vek + End + +End + +Structure Car ( + String brand, Integer wheels + ) + + Function setBrand ( + String brand + ) + Assign this.brand = Audi + End + + Function setWheels ( + Integer wheel + ) + Assign this.wheels = 5 + End + +End + diff --git a/test.fprg b/test.fprg index 49194f9..f5b4f32 100644 --- a/test.fprg +++ b/test.fprg @@ -75,7 +75,7 @@ <parameter name="brand" type="String"/> </parameters> <body> - <assign variable="this.brand" expression="Audi"/> + <assign variable="this.brand" expression="brand"/> </body> </function> <function name="setWheels" type="None" variable=""> @@ -83,7 +83,7 @@ <parameter name="wheel" type="Integer"/> </parameters> <body> - <assign variable="this.wheels" expression="5"/> + <assign variable="this.wheels" expression="wheel"/> </body> </function> </structure> diff --git a/test.py b/test.py index 46a3adc..c5967a0 100644 --- a/test.py +++ b/test.py @@ -1,5 +1,3 @@ - - def main(): number = None sum = None @@ -14,7 +12,8 @@ def main(): else: print("False", end="\n") print(sum, end="\n") - a(); + a() + return def a( @@ -22,11 +21,13 @@ def a( ): a = None a = 10 + return a def b(): b = None b = 5 + return b class Person: @@ -37,10 +38,10 @@ class Person: self.vek = vek -def setVek(self, - vek -): - self.vek = vek + def setVek(self, + vek + ): + self.vek = vek class Car: @@ -52,16 +53,16 @@ class Car: self.wheels = wheels -def setBrand(self, - brand -): - self.brand = Audi + def setBrand(self, + brand + ): + self.brand = brand -def setWheels(self, - wheel -): - self.wheels = 5 + def setWheels(self, + wheel + ): + self.wheels = wheel if __name__ == "__main__": -- GitLab From da74eac9d639c953f1444b8b7fcd1b6f99a48cbb Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Sun, 21 Apr 2024 01:28:58 +0200 Subject: [PATCH 6/7] re #11255 @3h20m - intrinsic functions --- Core/CodeConversionNS/ACodeConverter.cs | 13 ++++ Core/CodeConversionNS/CSharpConverter.cs | 70 ++++++++++++++++-- Core/CodeConversionNS/PseudocodeConverter.cs | 2 + Core/CodeConversionNS/PythonConverter.cs | 78 ++++++++++++++++++-- test.cs | 16 ++++ test.fcode | 19 ++++- test.fprg | 15 ++++ test.py | 19 +++++ 8 files changed, 219 insertions(+), 13 deletions(-) diff --git a/Core/CodeConversionNS/ACodeConverter.cs b/Core/CodeConversionNS/ACodeConverter.cs index 2c0106c..74afb7d 100644 --- a/Core/CodeConversionNS/ACodeConverter.cs +++ b/Core/CodeConversionNS/ACodeConverter.cs @@ -57,6 +57,7 @@ namespace Core.CodeConversionNS protected abstract void TranslateBlock(XElement element, int indent); protected abstract void TranslateStructure(XElement element, int indent); protected abstract string TranslateType(string type); + protected abstract string TranslateIntrinsicFunctions(string expression); protected abstract void GenerateProgramShellStart(); protected abstract void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures); protected abstract void GenerateProgramShellEnd(); @@ -65,6 +66,18 @@ namespace Core.CodeConversionNS protected List<string> Program { get; } = new List<string>(); + protected List<string> IntrinsicFunctions { get; } = new List<string>() { + // Math + "Abs", "Arcsin", "Arccos", "Arctan", "Cos", "Int", + "Ln", "Log", "Log10", "Sgn", "Sin", "Sqrt", "Tan", + // Strings + "Len", "Char", + // Types + "ToChar", "ToCode", "ToFixed", "ToInteger", "ToReal", "ToString", + // Other + "Random", "Size" + }; + protected void AddLine(string line, int indent) => Program.Add(Utils.Indent(indent) + line); public void WriteToFile(string filePath) diff --git a/Core/CodeConversionNS/CSharpConverter.cs b/Core/CodeConversionNS/CSharpConverter.cs index 8063c11..9e0390b 100644 --- a/Core/CodeConversionNS/CSharpConverter.cs +++ b/Core/CodeConversionNS/CSharpConverter.cs @@ -30,7 +30,7 @@ namespace Core.CodeConversionNS string variable = element.GetSafeAttribute("variable").Value; string expression = element.GetSafeAttribute("expression").Value; - AddLine($"{variable} = {expression};", indent); + AddLine($"{variable} = {TranslateIntrinsicFunctions(expression)};", indent); } protected override void TranslateBreak(int indent) @@ -46,7 +46,7 @@ namespace Core.CodeConversionNS protected override void TranslateCall(XElement element, int indent) { string expression = element.GetSafeAttribute("expression").Value; - AddLine($"{expression};", indent); + AddLine($"{TranslateIntrinsicFunctions(expression)};", indent); } protected override void TranslateComment(XElement element, int indent) @@ -76,7 +76,7 @@ namespace Core.CodeConversionNS AddLine("{", indent); TranslateBlock(element, indent + 1); AddLine("}", indent); - AddLine($"while({expression});", indent); + AddLine($"while({TranslateIntrinsicFunctions(expression)});", indent); } protected override void TranslateFor(XElement element, int indent) @@ -101,7 +101,7 @@ namespace Core.CodeConversionNS XElement thenBlock = element.GetSafeElement("then"); XElement elseBlock = element.GetSafeElement("else"); - AddLine($"if({expression})", indent); + AddLine($"if({TranslateIntrinsicFunctions(expression)})", indent); AddLine("{", indent); TranslateBlock(thenBlock, indent + 1); AddLine("}", indent); @@ -135,14 +135,14 @@ namespace Core.CodeConversionNS string newLine = element.GetSafeAttribute("newline").Value; string consoleWriteString = newLine == "True" ? "Console.WriteLine" : "Console.Write"; - AddLine($"{consoleWriteString}({expression});", indent); + AddLine($"{consoleWriteString}({TranslateIntrinsicFunctions(expression)});", indent); } protected override void TranslateWhile(XElement element, int indent) { string expression = element.GetSafeAttribute("expression").Value; - AddLine($"while({expression})", indent); + AddLine($"while({TranslateIntrinsicFunctions(expression)})", indent); AddLine("{", indent); TranslateBlock(element, indent + 1); AddLine("}", indent); @@ -250,5 +250,63 @@ namespace Core.CodeConversionNS }; return result + "[]".Repeat(bracketCount); } + + protected override string TranslateIntrinsicFunctions(string expression) + { + bool isIntrinsicFunction = IntrinsicFunctions.Exists(expression.StartsWith); + if (!isIntrinsicFunction) return expression; + + int firstOpeningBracketIndex = expression.IndexOf('('); + + string intrinsicFunction = expression.Split('(')[0]; + string restOfExpression = expression.Substring(firstOpeningBracketIndex + 1); + + int lastClosingBracketIndex = restOfExpression.LastIndexOf(')'); + string argument = restOfExpression.Remove(lastClosingBracketIndex, 1); + + // !!! Recursion + argument = TranslateIntrinsicFunctions(argument); + + switch (intrinsicFunction) + { + case "Len": return $"{argument}.Length"; + case "Char": + { + var parts = argument.Split(",", 2); + return $"{parts[0]}.ElementAt({parts[1]})"; + } + case "Random": return $"new Random().Next(0, {argument})"; + case "Size": return $"{argument}.Length"; + } + + string functionReplacement = intrinsicFunction switch + { + // Maths + "Abs" => "Math.Abs", + "Arcsin" => "Math.Asin", + "Arccos" => "Math.Acos", + "Arctan" => "Math.Atan", + "Cos" => "Math.Cos", + "Int" => "Math.Floor", + "Ln" => "Math.Log", + "Log" => "Math.Log", + "Log10" => "Math.Log10", + "Sgn" => "Math.Sign", + "Sin" => "Math.Sin", + "Sqrt" => "Math.Sqrt", + "Tan" => "Math.Tan", + + // Types + "ToChar" => "(char)", + "ToCode" => "(int)", + "ToFixed" => "Math.Round", + "ToInteger" => "Convert.ToInt32", + "ToReal" => "Convert.ToDouble", + "ToString" => "Convert.ToString", + _ => intrinsicFunction + }; + + return $"{functionReplacement}({argument})"; + } } } \ No newline at end of file diff --git a/Core/CodeConversionNS/PseudocodeConverter.cs b/Core/CodeConversionNS/PseudocodeConverter.cs index 26bd9e3..602098b 100644 --- a/Core/CodeConversionNS/PseudocodeConverter.cs +++ b/Core/CodeConversionNS/PseudocodeConverter.cs @@ -184,5 +184,7 @@ namespace Core.CodeConversionNS } protected override string TranslateType(string type) => type; + + protected override string TranslateIntrinsicFunctions(string expression) => expression; } } diff --git a/Core/CodeConversionNS/PythonConverter.cs b/Core/CodeConversionNS/PythonConverter.cs index 13fe860..3180460 100644 --- a/Core/CodeConversionNS/PythonConverter.cs +++ b/Core/CodeConversionNS/PythonConverter.cs @@ -6,7 +6,12 @@ namespace Core.CodeConversionNS { public override string FileExtension => ".py"; - protected override void GenerateProgramShellStart() { } + protected override void GenerateProgramShellStart() + { + AddLine("import math", 0); + AddLine("", 0); + AddLine("", 0); + } protected override void GenerateProgramInsides(List<XElement>? functions, List<XElement>? structures) { @@ -26,7 +31,7 @@ namespace Core.CodeConversionNS string expression = element.GetSafeAttribute("expression").Value; variable = variable.Replace("this.", "self."); - AddLine($"{variable} = {expression}", indent); + AddLine($"{variable} = {TranslateIntrinsicFunctions(expression)}", indent); } protected override void TranslateBreak(int indent) @@ -85,7 +90,7 @@ namespace Core.CodeConversionNS XElement thenBlock = element.GetSafeElement("then"); XElement elseBlock = element.GetSafeElement("else"); - AddLine($"if {expression}:", indent); + AddLine($"if {TranslateIntrinsicFunctions(expression)}:", indent); TranslateBlock(thenBlock, indent + 1); AddLine("else:", indent); TranslateBlock(elseBlock, indent + 1); @@ -103,14 +108,14 @@ namespace Core.CodeConversionNS string newLine = element.GetSafeAttribute("newline").Value; string end = newLine == "True" ? "\\n" : ""; - AddLine($"print({expression}, end=\"{end}\")", indent); + AddLine($"print({TranslateIntrinsicFunctions(expression)}, end=\"{end}\")", indent); } protected override void TranslateWhile(XElement element, int indent) { string expression = element.GetSafeAttribute("expression").Value; - AddLine($"while {expression}:", indent); + AddLine($"while {TranslateIntrinsicFunctions(expression)}:", indent); TranslateBlock(element, indent + 1); } @@ -197,5 +202,68 @@ namespace Core.CodeConversionNS } protected override string TranslateType(string type) => ""; + + protected override string TranslateIntrinsicFunctions(string expression) + { + bool isIntrinsicFunction = IntrinsicFunctions.Exists(expression.StartsWith); + if (!isIntrinsicFunction) return expression; + + int firstOpeningBracketIndex = expression.IndexOf('('); + + string intrinsicFunction = expression.Split('(')[0]; + string restOfExpression = expression.Substring(firstOpeningBracketIndex + 1); + + int lastClosingBracketIndex = restOfExpression.LastIndexOf(')'); + string argument = restOfExpression.Remove(lastClosingBracketIndex, 1); + + // !!! Recursion + argument = TranslateIntrinsicFunctions(argument); + + switch (intrinsicFunction) + { + case "Char": + { + var parts = argument.Split(",", 2); + return $"{parts[0]}[{parts[1]}]"; + } + case "Random": return $"random.randint(0, {argument} - 1)"; + } + + string functionReplacement = intrinsicFunction switch + { + // Maths + "Abs" => "abs", + "Arcsin" => "asin", + "Arccos" => "acos", + "Arctan" => "atan", + "Cos" => "cos", + "Int" => "math.floor", + "Ln" => "math.log", + "Log" => "math.log", + "Log10" => "math.log10", + "Sgn" => "math.sign", + "Sin" => "sin", + "Sqrt" => "math.sqrt", + "Tan" => "tan", + + // Strings + "Len" => "len", + + // Types + "ToChar" => "(char)", + "ToCode" => "(int)", + "ToFixed" => "round", + "ToInteger" => "int", + "ToReal" => "float", + "ToString" => "str", + + // Others + "Size" => "len", + _ => intrinsicFunction + }; + + return $"{functionReplacement}({argument})"; + + } } } diff --git a/test.cs b/test.cs index 1e3006d..474945a 100644 --- a/test.cs +++ b/test.cs @@ -50,6 +50,22 @@ public class Program return b; } + public static void IntrinsicFunctionCalls() + { + double a; + double b; + double c; + string str; + a = 4.56579; + b = Math.Floor(a); + c = Convert.ToDouble(Math.Round(a, 2)); + str = Math.Round(a,4); + Console.WriteLine(a); + Console.WriteLine(b); + Console.WriteLine(c); + Console.WriteLine(str); + } + public struct Person { public int vek; public Person( diff --git a/test.fcode b/test.fcode index 28db4ee..10a09ff 100644 --- a/test.fcode +++ b/test.fcode @@ -34,6 +34,21 @@ Function b Return Integer b End +Function IntrinsicFunctionCalls + Declare Real a, b, c + + Declare String str + + Assign a = 4.56579 + Assign b = Int(a) + Assign c = ToReal(ToFixed(a, 2)) + Assign str = ToFixed(a,4) + Output a + Output b + Output c + Output str +End + Structure Person ( Integer vek ) @@ -53,13 +68,13 @@ Structure Car ( Function setBrand ( String brand ) - Assign this.brand = Audi + Assign this.brand = brand End Function setWheels ( Integer wheel ) - Assign this.wheels = 5 + Assign this.wheels = wheel End End diff --git a/test.fprg b/test.fprg index f5b4f32..311c978 100644 --- a/test.fprg +++ b/test.fprg @@ -52,6 +52,21 @@ <assign variable="b" expression="5"/> </body> </function> + <function name="IntrinsicFunctionCalls" type="None" variable=""> + <parameters/> + <body> + <declare name="a, b, c" type="Real" /> + <declare name="str" type="String" /> + <assign variable="a" expression="4.56579"/> + <assign variable="b" expression="Int(a)"/> + <assign variable="c" expression="ToReal(ToFixed(a, 2))"/> + <assign variable="str" expression="ToFixed(a,4)"/> + <output expression="a" newline="True"/> + <output expression="b" newline="True"/> + <output expression="c" newline="True"/> + <output expression="str" newline="True"/> + </body> + </function> <structure name="Person"> <parameters> <parameter name="vek" type="Integer"/> diff --git a/test.py b/test.py index c5967a0..328abae 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,6 @@ +import math + + def main(): number = None sum = None @@ -30,6 +33,22 @@ def b(): return b +def IntrinsicFunctionCalls(): + a = None + b = None + c = None + str = None + a = 4.56579 + b = math.floor(a) + c = float(round(a, 2)) + str = round(a,4) + print(a, end="\n") + print(b, end="\n") + print(c, end="\n") + print(str, end="\n") + return + + class Person: def __init__( self, vek -- GitLab From b9f55827730c543bd2fc608ad7e8febb09f0f721 Mon Sep 17 00:00:00 2001 From: Duc Long Hoang <duclong@students.zcu.cz> Date: Sun, 21 Apr 2024 01:58:21 +0200 Subject: [PATCH 7/7] change comment --- Core/CodeConversionNS/ACodeConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/CodeConversionNS/ACodeConverter.cs b/Core/CodeConversionNS/ACodeConverter.cs index 74afb7d..5ea63c2 100644 --- a/Core/CodeConversionNS/ACodeConverter.cs +++ b/Core/CodeConversionNS/ACodeConverter.cs @@ -126,7 +126,7 @@ namespace Core.CodeConversionNS "function" => () => TranslateFunction(element, indent), "parameters" => () => TranslateParameters(element, indent), "structure" => () => TranslateStructure(element, indent), - _ => () => Console.WriteLine($"Unknown command=> () => {statement}") + _ => () => Console.WriteLine($"Unknown statement: {statement}") }; action.Invoke(); } -- GitLab