Full implementation of Append(), including error messages & semicolon requirement

This commit is contained in:
Brychan Dempsey 2021-03-12 11:00:29 +13:00
parent be780d54e2
commit 34ecfc0f46

View File

@ -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<string, VariableFlags>(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;