diff --git a/Assignment 1/Program.cs b/Assignment 1/Program.cs index 778c86e..7109de1 100644 --- a/Assignment 1/Program.cs +++ b/Assignment 1/Program.cs @@ -7,6 +7,7 @@ namespace Assignment_1 { class Program { + [Flags] enum VariableFlags { Empty = 0, @@ -90,8 +91,7 @@ namespace Assignment_1 // parse the statement or list of statements; // This is done by reading the next word SkipWhitespace(source); - string word = ""; - long position = FindNextWord(source, out word); + long position = FindNextWord(source, out string word); object statementType; if (Enum.TryParse(typeof(statements), word, out statementType)) { @@ -134,40 +134,78 @@ namespace Assignment_1 } #region Function Handling - bool Append(Stream source) + bool Append(Stream source, long lineStart = -1) { + // If it wasn't explicitly set, assume line starts the length of 'append ' before the current position + if (lineStart == -1) + { + lineStart = source.Position - "append ".Length; + } string key; - long advance = FindIdentifier(source, out key); - if (advance < 0) + long keyEndPos = FindIdentifier(source, out key); + if (keyEndPos < 0 || !Symbols.ContainsKey(key)) { // Error on finding object + if (lineStart != -1) + { + source.Position = lineStart; + } + string fullLine = GetNextLine(source); // Grab a copy of the line to show the user + // append x + string errorMSG = " ^ could not identify object"; + Console.WriteLine(fullLine); + Console.WriteLine(errorMSG); + source.SetLength(source.Position); return false; } else { - source.Position = advance; + source.Position = keyEndPos; } string value; - advance = FindValue(source, out value); - if (advance < 0) + long valuePos = FindValue(source, out value); + if (valuePos < 0) { - // Error on parsing value + // Error on finding object + source.Position = lineStart; + string fullLine = GetNextLine(source); // Grab a copy of the line to show the user + // append x + string errorMSG = new string(' ', (keyEndPos - source.Position) > 0 ? (int)(keyEndPos - source.Position) : "append".Length) + "^ could not evaluate value"; + Console.WriteLine(fullLine); + Console.WriteLine(errorMSG); + // Value didn't parse, set stream length to current length (removes excess characters from the stream + // so the next command is parsed correctly) + source.SetLength(source.Position); return false; } else { - source.Position = advance; + source.Position = valuePos; } string eol; FindNextWord(source, out eol); - if (eol[0] != ';') + if (eol.Length == 0 || eol[0] != ';') { - // Expected end-of-statement/end-of-line (;) + // reset our position to the start of this line + source.Position = lineStart; + string fullLine = GetNextLine(source); // Grab a copy of the line to show the user + // Align the message carat to the point which could not be parsed + string errorMSG = new string(' ', (valuePos - source.Position) > 0 ? (int)(valuePos - source.Position) : "append".Length) + "^ expected a semicolon"; + Console.WriteLine(fullLine); + Console.WriteLine(errorMSG); + source.SetLength(source.Position); return false; } - if (Symbols[key].Item2 == VariableFlags.Reserved) + if (Symbols[key].Item2.HasFlag(VariableFlags.Reserved)) { - // Can't assign to reserved items + // reset our position to the start of this line + source.Position = lineStart; + string fullLine = GetNextLine(source); // Grab a copy of the line to show the user + // Align the message carat to the point which could not be parsed + string errorMSG = new string(' ', (keyEndPos - (key.Length + 1) - source.Position) > 0 ? (int)(keyEndPos-(key.Length + 1) - source.Position) : "append".Length) + "^ cannot assign a value to a reserved constant"; + Console.WriteLine(fullLine); + Console.WriteLine(errorMSG); + source.SetLength(source.Position); return false; } Symbols[key] = new Tuple(Symbols[key].Item1 + value, Symbols[key].Item2); @@ -352,7 +390,14 @@ namespace Assignment_1 { s.Position--; string keyValue; + long t = FindExistingIdentifier(s, out keyValue); + + if (!Symbols.ContainsKey(keyValue)) + { + returnedValue = ""; + return -1; + } returnedValue = Symbols[keyValue].Item1; return t;