Condensed some code.
Improved docstrings where possible
This commit is contained in:
parent
c7858791f4
commit
087d8d0754
@ -11,6 +11,9 @@ namespace Assignment_1
|
|||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Flags to set object properties.
|
||||||
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
enum VariableFlags
|
enum VariableFlags
|
||||||
{
|
{
|
||||||
@ -21,23 +24,17 @@ namespace Assignment_1
|
|||||||
Undef = 8
|
Undef = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
static Dictionary<string, Tuple<string, VariableFlags>> Symbols = new()
|
||||||
/// This captures the end-point of each part of an expression (in the stream), to validate the syntax
|
{
|
||||||
/// Optionally also captures the parsed string for each expression.
|
|
||||||
///
|
|
||||||
/// For this program, a word is considered to be any non-whitespace value bounded by whitespace or the array boundary.
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
static Dictionary<string, Tuple<string, VariableFlags>> Symbols = new Dictionary<string, Tuple<string, VariableFlags>>
|
|
||||||
{
|
|
||||||
{ "SPACE", new Tuple<string, VariableFlags>(" ", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
{ "SPACE", new Tuple<string, VariableFlags>(" ", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
||||||
{ "TAB", new Tuple<string, VariableFlags>("\t", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
{ "TAB", new Tuple<string, VariableFlags>("\t", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
||||||
{ "NEWLINE", new Tuple<string, VariableFlags>("\n", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
{ "NEWLINE", new Tuple<string, VariableFlags>("\n", VariableFlags.Reserved | VariableFlags.NoPrint) },
|
||||||
{ "CARRIAGE_RETURN", new Tuple<string, VariableFlags>("\r", VariableFlags.Reserved | VariableFlags.NoPrint) }
|
{ "CARRIAGE_RETURN", new Tuple<string, VariableFlags>("\r", VariableFlags.Reserved | VariableFlags.NoPrint) }
|
||||||
};
|
};
|
||||||
|
/// <summary>
|
||||||
static List<char> ForbiddenChars = new List<char>
|
/// Characters that cannot appear in a normal string
|
||||||
|
/// </summary>
|
||||||
|
static readonly List<char> ForbiddenChars = new()
|
||||||
{
|
{
|
||||||
'$', '\\', '\"', '\''
|
'$', '\\', '\"', '\''
|
||||||
};
|
};
|
||||||
@ -100,18 +97,15 @@ namespace Assignment_1
|
|||||||
long pos = source.Position;
|
long pos = source.Position;
|
||||||
source.Write(Encoding.UTF8.GetBytes(s));
|
source.Write(Encoding.UTF8.GetBytes(s));
|
||||||
source.Position = pos;
|
source.Position = pos;
|
||||||
int g = 0;
|
|
||||||
}
|
}
|
||||||
// parse the statement or list of statements;
|
// parse the statement or list of statements;
|
||||||
// This is done by reading the next word
|
// This is done by reading the next word
|
||||||
SkipWhitespace(source);
|
SkipWhitespace(source);
|
||||||
long initPos = source.Position;
|
long initPos = source.Position;
|
||||||
long position = FindNextWord(source, out string word);
|
long position = FindNextWord(source, out string word);
|
||||||
|
|
||||||
object statementType;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(typeof(statements), word, out statementType))
|
if (Enum.TryParse(typeof(statements), word, out object statementType))
|
||||||
{
|
{
|
||||||
// By turning the result of the command into an action,
|
// By turning the result of the command into an action,
|
||||||
// we can defer processing the final result until the end of this control flow
|
// we can defer processing the final result until the end of this control flow
|
||||||
@ -183,7 +177,7 @@ namespace Assignment_1
|
|||||||
{
|
{
|
||||||
throw new ParserException("expected a semi-colon", 0, source.Position);
|
throw new ParserException("expected a semi-colon", 0, source.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -439,26 +433,17 @@ namespace Assignment_1
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
long FindExpression(Stream s, out string expression)
|
long FindExpression(Stream s, out string expression)
|
||||||
{
|
{
|
||||||
// Expressions are one or more occurances of a variable name or literal definition.
|
|
||||||
// To make logical sense, there needs to be an operator between them. Typically, for strings, this is
|
|
||||||
// the append operator: +
|
|
||||||
// Variable symbols should be evaluated immediately.
|
|
||||||
// Start by ensuring we don't try reading past the end of the stream
|
|
||||||
// Also check for the EoS
|
|
||||||
long realStart = s.Position;
|
|
||||||
string result = "";
|
string result = "";
|
||||||
|
// iterate through values until we reach either the end of the stream or the end-of-statement
|
||||||
while (s.Position < s.Length && !IsNextEoS(s))
|
while (s.Position < s.Length && !IsNextEoS(s))
|
||||||
{
|
{
|
||||||
long currStart = s.Position;
|
|
||||||
if (IsNextEoS(s, '+'))
|
if (IsNextEoS(s, '+'))
|
||||||
{
|
{
|
||||||
s.Position = FindNextWord(s, out _);
|
s.Position = FindNextWord(s, out _);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string value;
|
long val = FindValue(s, out string value);
|
||||||
long firstPos = s.Position;
|
|
||||||
long val = FindValue(s, out value);
|
|
||||||
if (val == -1)
|
if (val == -1)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Could not parse value");
|
Console.WriteLine("Could not parse value");
|
||||||
@ -506,8 +491,7 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string keyValue;
|
long t = FindExistingIdentifier(s, out string keyValue);
|
||||||
long t = FindExistingIdentifier(s, out keyValue);
|
|
||||||
// Set the key value to result + this read string
|
// Set the key value to result + this read string
|
||||||
//keyValue = result + keyValue;
|
//keyValue = result + keyValue;
|
||||||
|
|
||||||
@ -528,8 +512,7 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
long FindExistingIdentifier(Stream s, out string returnedKey)
|
long FindExistingIdentifier(Stream s, out string returnedKey)
|
||||||
{
|
{
|
||||||
string identifier;
|
long wordEnd = FindNextWord(s, out string identifier);
|
||||||
long wordEnd = FindNextWord(s, out identifier);
|
|
||||||
if (identifier.Length > 1 && identifier.EndsWith(';'))
|
if (identifier.Length > 1 && identifier.EndsWith(';'))
|
||||||
{
|
{
|
||||||
// Remove the trailing semicolon from the parse & backtrack the identifier length one spot
|
// Remove the trailing semicolon from the parse & backtrack the identifier length one spot
|
||||||
@ -608,10 +591,15 @@ namespace Assignment_1
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static long FindNextWord(Stream s, out string nextWord)
|
static long FindNextWord(Stream s, out string nextWord)
|
||||||
{
|
{
|
||||||
StringBuilder newWord = new StringBuilder();
|
StringBuilder newWord = new();
|
||||||
// Record our current position
|
// Record our current position
|
||||||
long start = s.Position;
|
long start = s.Position;
|
||||||
// Check if the character at the current pos is whitespace, if so, keep advancing until it isn't
|
// Check if the character at the current pos is whitespace, if so, keep advancing until it isn't.
|
||||||
|
// NB: Whitespace includes carriage returns or line feeds,
|
||||||
|
// so 'set\r\n
|
||||||
|
// var
|
||||||
|
// "expression";
|
||||||
|
// should be valid
|
||||||
char currentChar = ReadChar(s);
|
char currentChar = ReadChar(s);
|
||||||
while (s.Position < s.Length && char.IsWhiteSpace(currentChar))
|
while (s.Position < s.Length && char.IsWhiteSpace(currentChar))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user