diff --git a/Assignment 1/Program.cs b/Assignment 1/Program.cs index bb95ec8..37cb5dc 100644 --- a/Assignment 1/Program.cs +++ b/Assignment 1/Program.cs @@ -6,6 +6,7 @@ using System.Text; using System.Collections.ObjectModel; using System.Runtime.Serialization; using System.Runtime.InteropServices; +using System.Threading; namespace Assignment_1 { @@ -28,7 +29,10 @@ namespace Assignment_1 /// static readonly List ForbiddenChars = new() { - '$', '\\', '\"', '\'' + '$', + '\\', + '\"', + '\'' }; static bool nonStrict = false; @@ -40,7 +44,7 @@ namespace Assignment_1 Console.WriteLine("│ Submitted by Brychan Dempsey, 14299890 │"); Console.WriteLine("└──────────────────────────────────────────┘"); // Parse the source from the memory stream - MemoryStream sourceStream = new MemoryStream(1024); + MemoryStream sourceStream = new(1024); Parser parser = new(); bool dynamicInput = false; foreach (var arg in args) @@ -67,9 +71,22 @@ namespace Assignment_1 dynamicInput = true; } parser.StartParsing(sourceStream, dynamicInput); - + Console.WriteLine("\nProgram parsing complete."); + if (dynamicInput == false) + { + Thread.Sleep(2000); + Environment.Exit(0); + } + Console.WriteLine("Would you like to parse more programs?"); + string answer = Console.ReadLine(); + if (answer.ToLower() == "no") + { + Environment.Exit(0); + } + Console.WriteLine("Not yet implemented"); Console.ReadLine(); } + public class Parser { Dictionary> Symbols = new() @@ -80,7 +97,7 @@ namespace Assignment_1 { "CARRIAGE_RETURN", new Tuple("\r", VariableFlags.Reserved | VariableFlags.NoPrint) } }; - public enum statements + public enum Statements { exit, append, @@ -119,7 +136,7 @@ namespace Assignment_1 long pos = source.Position; source.Write(Encoding.UTF8.GetBytes(s)); source.Position = pos; - + } // parse the statement or list of statements; // This is done by reading the next word @@ -135,7 +152,7 @@ namespace Assignment_1 long position = FindNextWord(source, out string word); try { - if (Enum.TryParse(typeof(statements), word, out object statementType)) + if (Enum.TryParse(typeof(Statements), word, out object statementType)) { // By turning the result of the command into an action, // we can defer processing the final result until the end of this control flow @@ -144,15 +161,15 @@ namespace Assignment_1 // In some ways, it makes more sense. The action is determined by the interpreter's result Action result = () => { }; source.Position = position; - switch ((statements)statementType) + switch ((Statements)statementType) { - case statements.exit: + case Statements.exit: result = Exit(source, initSourceLength); break; - case statements.append: + case Statements.append: result = AppendSet(source); break; - case statements.list: + case Statements.list: long pos = FindNextWord(source, out string nextWord); if (nextWord == "all") { @@ -164,36 +181,36 @@ namespace Assignment_1 result = List(); } break; - case statements.print: + case Statements.print: result = Print(source, 0); break; - case statements.printlength: + case Statements.printlength: result = Print(source, 1); break; - case statements.printwordcount: + case Statements.printwordcount: result = Print(source, 2); break; - case statements.printwords: + case Statements.printwords: result = Print(source, 3); break; - case statements.set: + case Statements.set: result = AppendSet(source, false); break; - case statements.reverse: + case Statements.reverse: result = Reverse(source); break; // These are additional helper functions. Thier input gets excluded from the MemoryStream - case statements.h: + case Statements.h: Console.WriteLine("Commands are: "); - foreach (var item in Enum.GetValues(typeof(statements))) + foreach (var item in Enum.GetValues(typeof(Statements))) { - Console.WriteLine("\t{0}", ((statements)item).ToString()); + Console.WriteLine("\t{0}", ((Statements)item).ToString()); } // Ignore these as actual commands source.Position = initPos; source.SetLength(initPos); break; - case statements.writeout: + case Statements.writeout: // Writes the full command history to the stream. Console.WriteLine("Writing input commands to {0}..."); source.Position = initPos; @@ -212,8 +229,12 @@ namespace Assignment_1 source.WriteByte((byte)'\n'); } result(); + if (((Statements)statementType).Equals(Statements.exit)) + { + return; + } } - else if(source.Position != lastLinePos-1) + else if (source.Position != lastLinePos - 1) { // In the case that we expect some more data, we must keep tabs of our current line, and keep accumulating data until we're finished lastLinePos = source.Position; @@ -319,7 +340,7 @@ namespace Assignment_1 /// /// /// An Action that will add the key to the dictionary - Action AppendSet(Stream source, bool appendMode=true) + Action AppendSet(Stream source, bool appendMode = true) { string key = ValidateKey(source, appendMode); string value = ValidateValue(source); @@ -366,7 +387,7 @@ namespace Assignment_1 consoleOutput.Append(string.Format("├" + new string('─', keyWidth) + "┼" + new string('─', valueWidth) + "┼" + new string('─', flagWidth) + "┤\n")); for (int i = 0; i < eligibleKeys.Count; i++) { - string entryFormat = "│{0," + -1*keyWidth + "}│{1," + -1*valueWidth + "}│{2," + -1*flagWidth + "}│\n"; + string entryFormat = "│{0," + -1 * keyWidth + "}│{1," + -1 * valueWidth + "}│{2," + -1 * flagWidth + "}│\n"; consoleOutput.Append(string.Format(entryFormat, eligibleKeys[i], Symbols[eligibleKeys[i]].Item1.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t"), Convert.ToString((byte)Symbols[eligibleKeys[i]].Item2, 2).PadLeft(8, '0'))); if (i + 1 < eligibleKeys.Count) @@ -396,26 +417,24 @@ namespace Assignment_1 { Console.WriteLine("Enter an output file (default {0}):", Environment.CurrentDirectory); string path = Console.ReadLine(); - if (path == "") + if (path != "") { - Environment.Exit(0); + path = Path.Combine(Environment.CurrentDirectory, path); + // insert the final closing bracket + source.WriteByte((byte)'}'); + source.Position = 0; + using (FileStream fs = File.OpenWrite(path)) + { + source.CopyTo(fs); + } + source.Close(); } - path = Path.Combine(Environment.CurrentDirectory, path); - // insert the final closing bracket - source.WriteByte((byte)'}'); - source.Position = 0; - using (FileStream fs = File.OpenWrite(path)) - { - source.CopyTo(fs); - } - source.Close(); } } - Environment.Exit(0); - }; + }; return exitAction; } - Action Print(Stream source, int mode=0) + Action Print(Stream source, int mode = 0) { StringBuilder outputString = new StringBuilder(); string expression = ValidateValue(source); @@ -430,7 +449,7 @@ namespace Assignment_1 } else if (mode >= 2) { - + string[] words = expression.Split(' '); if (mode == 3) { @@ -444,7 +463,7 @@ namespace Assignment_1 { outputString.Append(word + Environment.NewLine); } - } + } } return () => Console.WriteLine(outputString.ToString()); } @@ -455,12 +474,12 @@ namespace Assignment_1 string ToReverse = Symbols[key].Item1; string[] words = ToReverse.Split(' '); StringBuilder reversed = new StringBuilder(); - for (int i = words.Length-1; i >= 0; i--) + for (int i = words.Length - 1; i >= 0; i--) { reversed.Append(words[i]); reversed.Append(' '); } - + return () => Symbols[key] = new Tuple(reversed.ToString(), Symbols[key].Item2); } @@ -477,7 +496,7 @@ namespace Assignment_1 { source.Position = lineStart; string fullLine = GetNextLine(source); - string errorMSG = new string (' ', (caratPos - lineStart) >= 0 ? (int)(caratPos - lineStart):0) + "^ " + errorMessage; + string errorMSG = new string(' ', (caratPos - lineStart) >= 0 ? (int)(caratPos - lineStart) : 0) + "^ " + errorMessage; Console.WriteLine(fullLine); Console.WriteLine(errorMSG); source.SetLength(source.Position); @@ -561,7 +580,7 @@ namespace Assignment_1 } returnedValue = Symbols[keyValue].Item1; return t; - + } } @@ -827,7 +846,7 @@ namespace Assignment_1 } } - static string CenterString(string source, int totalPadding, char paddingChar=' ') + static string CenterString(string source, int totalPadding, char paddingChar = ' ') { if (source.Length >= totalPadding) return source; int rightHalf = (int)Math.Ceiling(source.Length / 2.0);