Condensed /cleaned up some code
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
This commit is contained in:
parent
a37aa07ede
commit
340591e1a1
@ -6,10 +6,6 @@
|
|||||||
<RootNamespace>Assignment_1</RootNamespace>
|
<RootNamespace>Assignment_1</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Examples\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||||
<Exec Command="xcopy "$(ProjectDir)\Examples\*.txt" "$(OutDir)" /Y /I" />
|
<Exec Command="xcopy "$(ProjectDir)\Examples\*.txt" "$(OutDir)" /Y /I" />
|
||||||
</Target>
|
</Target>
|
||||||
|
3
Assignment 1/Examples/test1.txt
Normal file
3
Assignment 1/Examples/test1.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
set apple "Apple trees are small.";
|
||||||
|
reverse apple;
|
||||||
|
print apple;
|
@ -22,6 +22,8 @@ namespace Assignment_1
|
|||||||
NoPrint = 2,
|
NoPrint = 2,
|
||||||
Static = 4
|
Static = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Max display width for tables etc.
|
||||||
static readonly int ConsoleWidthLimit = 80;
|
static readonly int ConsoleWidthLimit = 80;
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
@ -42,7 +44,8 @@ namespace Assignment_1
|
|||||||
if (Console.IsInputRedirected || loadedFromFile)
|
if (Console.IsInputRedirected || loadedFromFile)
|
||||||
{
|
{
|
||||||
// To simplify reading, we read all input bytes from the piped input to the stream.
|
// To simplify reading, we read all input bytes from the piped input to the stream.
|
||||||
// Not the best way to do it; we don't need to keep any data that has already been read and parsed successfully.
|
// Not the best way to do it; we don't need to keep any data that has already been read and parsed successfully,
|
||||||
|
// and we could avoid copying the supplied stream. But keeps interactivity with the console simple
|
||||||
sourceStream.Write(Encoding.UTF8.GetBytes(Console.In.ReadToEnd()));
|
sourceStream.Write(Encoding.UTF8.GetBytes(Console.In.ReadToEnd()));
|
||||||
Console.In.Dispose();
|
Console.In.Dispose();
|
||||||
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
|
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
|
||||||
@ -75,7 +78,6 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Need the logic to prep the next source stream
|
|
||||||
ck = new ConsoleKeyInfo();
|
ck = new ConsoleKeyInfo();
|
||||||
while (ck.Key != ConsoleKey.Y && ck.Key != ConsoleKey.N)
|
while (ck.Key != ConsoleKey.Y && ck.Key != ConsoleKey.N)
|
||||||
{
|
{
|
||||||
@ -131,7 +133,6 @@ namespace Assignment_1
|
|||||||
set,
|
set,
|
||||||
reverse,
|
reverse,
|
||||||
h,
|
h,
|
||||||
writeout
|
|
||||||
}
|
}
|
||||||
public void StartParsing(Stream source, bool dynamicInput = false)
|
public void StartParsing(Stream source, bool dynamicInput = false)
|
||||||
{
|
{
|
||||||
@ -155,8 +156,6 @@ namespace Assignment_1
|
|||||||
source.Position = pos;
|
source.Position = pos;
|
||||||
|
|
||||||
}
|
}
|
||||||
// parse the statement or list of statements;
|
|
||||||
// This is done by reading the next word
|
|
||||||
if (!cont)
|
if (!cont)
|
||||||
{
|
{
|
||||||
initPos = source.Position;
|
initPos = source.Position;
|
||||||
@ -213,22 +212,19 @@ namespace Assignment_1
|
|||||||
case Statements.reverse:
|
case Statements.reverse:
|
||||||
result = Reverse(source);
|
result = Reverse(source);
|
||||||
break;
|
break;
|
||||||
// These are additional helper functions. Thier input gets excluded from the MemoryStream
|
|
||||||
case Statements.h:
|
case Statements.h:
|
||||||
Console.WriteLine("Commands are: ");
|
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
|
// Stream ignores this command
|
||||||
source.Position = initPos;
|
source.Position = initPos;
|
||||||
source.SetLength(initPos);
|
source.SetLength(initPos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Do a check semicolons etc
|
|
||||||
if (IsNextEoS(source))
|
if (IsNextEoS(source))
|
||||||
{
|
{
|
||||||
// Increment the source pos past the semi-colon
|
|
||||||
cont = false;
|
cont = false;
|
||||||
source.Position++;
|
source.Position++;
|
||||||
SkipWhitespace(source);
|
SkipWhitespace(source);
|
||||||
@ -236,8 +232,7 @@ namespace Assignment_1
|
|||||||
else isLineFinished = false;
|
else isLineFinished = false;
|
||||||
if (dynamicInput && isLineFinished)
|
if (dynamicInput && isLineFinished)
|
||||||
{
|
{
|
||||||
// Nicely format the output stream, so we may print it cleanly
|
source.WriteByte((byte)'\n'); // put the next statement on a newline so the exported list of commands is clean
|
||||||
source.WriteByte((byte)'\n');
|
|
||||||
}
|
}
|
||||||
result();
|
result();
|
||||||
if (((Statements)statementType).Equals(Statements.exit))
|
if (((Statements)statementType).Equals(Statements.exit))
|
||||||
@ -247,17 +242,19 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
else if (source.Position != lastLinePos)
|
else if (source.Position != lastLinePos)
|
||||||
{
|
{
|
||||||
// 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
|
// If the semicolon is missing *once*, assume we need more data.
|
||||||
lastLinePos = source.Position;
|
lastLinePos = source.Position;
|
||||||
cont = true;
|
cont = true;
|
||||||
source.WriteByte((byte)' ');
|
|
||||||
Console.Write(">");
|
Console.Write(">");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if ((Statements)statementType != Statements.h)
|
||||||
{
|
{
|
||||||
throw new ParserException("expected a semi-colon", 0, source.Position);
|
throw new ParserException("expected a semi-colon", 0, source.Position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ParserException("Failed parsing statement", 0, source.Position);
|
throw new ParserException("Failed parsing statement", 0, source.Position);
|
||||||
@ -289,15 +286,11 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Function Handling
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the next expression in the source meets the requirements of being a key,
|
/// Checks if the next expression in the source meets the requirements of being a key,
|
||||||
/// and optionally verify that key exists.
|
/// and optionally verify that key exists. Acoids overidding the value of constants, and
|
||||||
/// Also contracts the key is not reserved or constant
|
/// ensures all characters are valid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source"></param>
|
|
||||||
/// <param name="checkExist"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string ValidateKey(Stream source, bool checkExist)
|
private string ValidateKey(Stream source, bool checkExist)
|
||||||
{
|
{
|
||||||
long keyEndPos = FindIdentifier(source, out string key);
|
long keyEndPos = FindIdentifier(source, out string key);
|
||||||
@ -315,7 +308,7 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int indx = Array.FindIndex(key.ToCharArray(), (c) => (c > 122 || c > 90 && c < 97 && c != '_' || c > 57 && c < 65 || c < 48)); // If the overall result is good, move until one isn't
|
int indx = Array.FindIndex(key.ToCharArray(), (c) => (c > 122 || c > 90 && c < 97 && c != '_' || c > 57 && c < 65 || c < 48));
|
||||||
if (indx > -1)
|
if (indx > -1)
|
||||||
{
|
{
|
||||||
throw new ParserException(string.Format("Character \'{0}\' is not valid for an identifier",key[indx]), 0, keyEndPos-key.Length + indx);
|
throw new ParserException(string.Format("Character \'{0}\' is not valid for an identifier",key[indx]), 0, keyEndPos-key.Length + indx);
|
||||||
@ -328,8 +321,6 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the next expression meets the requirements of being a value
|
/// Checks if the next expression meets the requirements of being a value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string ValidateValue(Stream source)
|
private string ValidateValue(Stream source)
|
||||||
{
|
{
|
||||||
long valuePos = FindExpression(source, out string value);
|
long valuePos = FindExpression(source, out string value);
|
||||||
@ -345,11 +336,9 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the 'append x y [ + z];' case &
|
/// Handles the 'append x y [ + z];' case <br />
|
||||||
/// And the 'set x y [ + z];' case
|
/// And the 'set x y [ + z];' case
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source"></param>
|
|
||||||
/// <returns>An Action that will add the key to the dictionary</returns>
|
|
||||||
Action AppendSet(Stream source, bool appendMode = true)
|
Action AppendSet(Stream source, bool appendMode = true)
|
||||||
{
|
{
|
||||||
string key = ValidateKey(source, appendMode);
|
string key = ValidateKey(source, appendMode);
|
||||||
@ -370,6 +359,7 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates and prints a nicely formatted table of all values
|
/// Creates and prints a nicely formatted table of all values
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -413,6 +403,9 @@ namespace Assignment_1
|
|||||||
consoleOutput.Append(string.Format("└" + new string('─', keyWidth) + "┴" + new string('─', valueWidth) + "┴" + new string('─', flagWidth) + "┘\n"));
|
consoleOutput.Append(string.Format("└" + new string('─', keyWidth) + "┴" + new string('─', valueWidth) + "┴" + new string('─', flagWidth) + "┘\n"));
|
||||||
return () => Console.WriteLine(consoleOutput.ToString());
|
return () => Console.WriteLine(consoleOutput.ToString());
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Exit Application logic
|
||||||
|
/// </summary>
|
||||||
Action Exit(Stream source, long initialStreamLength, bool isDynamicInput=false)
|
Action Exit(Stream source, long initialStreamLength, bool isDynamicInput=false)
|
||||||
{
|
{
|
||||||
void exitAction()
|
void exitAction()
|
||||||
@ -445,6 +438,14 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
return exitAction;
|
return exitAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prints the expression to the console:<br />
|
||||||
|
/// 0: print the value <br />
|
||||||
|
/// 1: print the length <br />
|
||||||
|
/// 2: print the word count <br />
|
||||||
|
/// 3: print the words in the value <br />
|
||||||
|
/// </summary>
|
||||||
Action Print(Stream source, int mode = 0)
|
Action Print(Stream source, int mode = 0)
|
||||||
{
|
{
|
||||||
StringBuilder outputString = new StringBuilder();
|
StringBuilder outputString = new StringBuilder();
|
||||||
@ -478,7 +479,9 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
return () => Console.WriteLine(outputString.ToString());
|
return () => Console.WriteLine(outputString.ToString());
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Reverses the word-order of the symbol (in-place).
|
||||||
|
/// </summary>
|
||||||
Action Reverse(Stream source)
|
Action Reverse(Stream source)
|
||||||
{
|
{
|
||||||
string key = ValidateKey(source, true);
|
string key = ValidateKey(source, true);
|
||||||
@ -495,14 +498,10 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes the debug info to the screen in the form:<br/>
|
/// Writes the debug info to the screen in the form: <br/>
|
||||||
/// line read from stream (lineStart) to line end<br/>
|
/// line read from stream (lineStart) to line end <br/>
|
||||||
/// <whitespace@caratPos> ^ <errorMessage>
|
/// <whitespace@caratPos> ^ <errorMessage>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lineStart"></param>
|
|
||||||
/// <param name="caratPos"></param>
|
|
||||||
/// <param name="errorMessage"></param>
|
|
||||||
/// <param name="source"></param>
|
|
||||||
static void WriteDebugLine(long lineStart, long caratPos, string errorMessage, Stream source)
|
static void WriteDebugLine(long lineStart, long caratPos, string errorMessage, Stream source)
|
||||||
{
|
{
|
||||||
source.Position = lineStart;
|
source.Position = lineStart;
|
||||||
@ -513,18 +512,13 @@ namespace Assignment_1
|
|||||||
source.Position = lineStart;
|
source.Position = lineStart;
|
||||||
source.SetLength(source.Position);
|
source.SetLength(source.Position);
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
#region Data Handling
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses & evaluates the expression from the stream, moving the stream to the end of the last value
|
/// Parses & evaluates the expression from the stream, moving the stream to the end of the last value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="expression"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
long FindExpression(Stream s, out string expression)
|
long FindExpression(Stream s, out string expression)
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
// iterate through values until we reach either the end of the stream or the end-of-statement
|
|
||||||
bool IsAppendSet = true;
|
bool IsAppendSet = true;
|
||||||
while (s.Position < s.Length && !IsNextEoS(s))
|
while (s.Position < s.Length && !IsNextEoS(s))
|
||||||
{
|
{
|
||||||
@ -550,17 +544,14 @@ namespace Assignment_1
|
|||||||
{
|
{
|
||||||
throw new ParserException("Append operator not set", 0, s.Position);
|
throw new ParserException("Append operator not set", 0, s.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expression = result;
|
expression = result;
|
||||||
return s.Position;
|
return s.Position;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks ahead to see if the next non-whitespace character is the EoS indicator (';')
|
/// Checks ahead to see if the next non-whitespace character is the EoS indicator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="EoSChar"></param>
|
|
||||||
/// <returns>true if the next char is <paramref name="EoSChar"/>, else false</returns>
|
/// <returns>true if the next char is <paramref name="EoSChar"/>, else false</returns>
|
||||||
static bool IsNextEoS(Stream s, char EoSChar = ';')
|
static bool IsNextEoS(Stream s, char EoSChar = ';')
|
||||||
{
|
{
|
||||||
@ -576,11 +567,8 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the next value in the stream
|
/// Finds the next value expression in the stream
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="returnedValue"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
long FindValue(Stream s, out string returnedValue)
|
long FindValue(Stream s, out string returnedValue)
|
||||||
{
|
{
|
||||||
SkipWhitespace(s);
|
SkipWhitespace(s);
|
||||||
@ -593,16 +581,12 @@ namespace Assignment_1
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
long t = FindExistingIdentifier(s, out string keyValue);
|
long t = FindExistingIdentifier(s, out string keyValue);
|
||||||
// Set the key value to result + this read string
|
|
||||||
//keyValue = result + keyValue;
|
|
||||||
|
|
||||||
if (!Symbols.ContainsKey(keyValue))
|
if (!Symbols.ContainsKey(keyValue))
|
||||||
{
|
{
|
||||||
throw new ParserException("Could not find key: " + keyValue, 0, s.Position);
|
throw new ParserException("Could not find key: " + keyValue, 0, s.Position);
|
||||||
}
|
}
|
||||||
returnedValue = Symbols[keyValue].Item1;
|
returnedValue = Symbols[keyValue].Item1;
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,7 +605,6 @@ namespace Assignment_1
|
|||||||
wordEnd--;
|
wordEnd--;
|
||||||
s.Position--;
|
s.Position--;
|
||||||
}
|
}
|
||||||
// Lookup the value in the symbol table
|
|
||||||
returnedKey = identifier;
|
returnedKey = identifier;
|
||||||
return wordEnd;
|
return wordEnd;
|
||||||
}
|
}
|
||||||
@ -629,9 +612,6 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the end of the complete literal definition, returning the stream to the original position
|
/// Finds the end of the complete literal definition, returning the stream to the original position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="returnedLiteral"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static long FindLiteral(Stream s, out string returnedLiteral)
|
static long FindLiteral(Stream s, out string returnedLiteral)
|
||||||
{
|
{
|
||||||
long pos = s.Position;
|
long pos = s.Position;
|
||||||
@ -642,14 +622,16 @@ namespace Assignment_1
|
|||||||
{
|
{
|
||||||
if (c == '\"')
|
if (c == '\"')
|
||||||
{
|
{
|
||||||
long pos = s.Position--;
|
s.Position--;
|
||||||
if (ReadChar(s) == '\\')
|
if (PreviousChar(s) == '\\')
|
||||||
{
|
{
|
||||||
// TODO: handle the \\ escape
|
// TODO: handle the \\ escape
|
||||||
|
s.Position++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
s.Position++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,7 +639,7 @@ namespace Assignment_1
|
|||||||
}, out string resultLiteral);
|
}, out string resultLiteral);
|
||||||
if (resultPosition > -1)
|
if (resultPosition > -1)
|
||||||
{
|
{
|
||||||
returnedLiteral = resultLiteral;
|
returnedLiteral = resultLiteral.Replace("\\\"", "\"");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -666,16 +648,11 @@ namespace Assignment_1
|
|||||||
s.Position = pos;
|
s.Position = pos;
|
||||||
return resultPosition;
|
return resultPosition;
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region HelperFunctions
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the memory stream as a UTF-8 encoded string until the next occurance of '\n' or '\r\n' (consuming, and excluded)
|
/// Reads the memory stream as a UTF-8 encoded string until the next occurance of '\n' or '\r\n' (consuming, and excluded)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static string GetNextLine(Stream s)
|
static string GetNextLine(Stream s)
|
||||||
{
|
{
|
||||||
FindNextOccurance(s, '\n', out string nextLine);
|
FindNextOccurance(s, '\n', out string nextLine);
|
||||||
@ -685,26 +662,15 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the end-boundary of the next word in the stream, and returns the stream to the original position
|
/// Finds the end-boundary of the next word in the stream, and returns the stream to the original position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="nextWord"></param>
|
|
||||||
/// <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 StringBuilder();
|
||||||
// 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.
|
|
||||||
// NB: Whitespace includes carriage returns and 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))
|
||||||
{
|
{
|
||||||
currentChar = ReadChar(s);
|
currentChar = ReadChar(s);
|
||||||
}
|
}
|
||||||
// Add the last read value to the SB
|
|
||||||
newWord.Append(currentChar);
|
newWord.Append(currentChar);
|
||||||
// Start a second loop, this time checking we're not a whitespace char
|
// Start a second loop, this time checking we're not a whitespace char
|
||||||
while (s.Position < s.Length)
|
while (s.Position < s.Length)
|
||||||
@ -731,10 +697,6 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds and returns the position of the next occurance of the Func returning true.
|
/// Finds and returns the position of the next occurance of the Func returning true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="p">A 'predicate'-like Func</param>
|
|
||||||
/// <param name="result">Returns the string captured while searching for the next char</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static long FindNextOccurance(Stream s, Func<char, Stream, bool> p, out string result)
|
static long FindNextOccurance(Stream s, Func<char, Stream, bool> p, out string result)
|
||||||
{
|
{
|
||||||
long start = s.Position;
|
long start = s.Position;
|
||||||
@ -764,21 +726,16 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the next position of the character
|
/// Finds the next position of the supplied character
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <param name="c"></param>
|
|
||||||
/// <param name="result">Captures the string read in searching for the character</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static long FindNextOccurance(Stream s, char c, out string result)
|
static long FindNextOccurance(Stream s, char c, out string result)
|
||||||
{
|
{
|
||||||
return FindNextOccurance(s, (streamChar, s) => streamChar == c, out result);
|
return FindNextOccurance(s, (streamChar, s) => streamChar == c, out result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the next UTF-8 encoded character in the stream, and advances the stream by the amount of characters read
|
/// Reads the next UTF-8 encoded character in the stream, and advances the stream by the amount of characters read
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static char ReadChar(Stream s)
|
static char ReadChar(Stream s)
|
||||||
{
|
{
|
||||||
// As UTF-8 allows codepoints to span multiple bytes, reading a single byte as a character will not always give the expected
|
// As UTF-8 allows codepoints to span multiple bytes, reading a single byte as a character will not always give the expected
|
||||||
@ -815,11 +772,10 @@ namespace Assignment_1
|
|||||||
string converted = Encoding.UTF8.GetString(charBytes);
|
string converted = Encoding.UTF8.GetString(charBytes);
|
||||||
return converted[0];
|
return converted[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the next character in the stream, and returns the position to the original position
|
/// Reads the next character in the stream, and returns the position to the original position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static char PeekChar(Stream s)
|
static char PeekChar(Stream s)
|
||||||
{
|
{
|
||||||
long curr = s.Position;
|
long curr = s.Position;
|
||||||
@ -831,8 +787,6 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the previous char
|
/// Reads the previous char
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
static char PreviousChar(Stream s)
|
static char PreviousChar(Stream s)
|
||||||
{
|
{
|
||||||
Stack<byte> charBytes = new Stack<byte>(4);
|
Stack<byte> charBytes = new Stack<byte>(4);
|
||||||
@ -855,13 +809,12 @@ namespace Assignment_1
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Skips whitespace characters
|
/// Skips whitespace characters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
|
||||||
static void SkipWhitespace(Stream s)
|
static void SkipWhitespace(Stream s)
|
||||||
{
|
{
|
||||||
char c = PeekChar(s);
|
char c = PeekChar(s);
|
||||||
while (s.Position < s.Length && char.IsWhiteSpace(c))
|
while (s.Position < s.Length && char.IsWhiteSpace(c))
|
||||||
{
|
{
|
||||||
ReadChar(s); // move by the size of that character
|
ReadChar(s);
|
||||||
c = PeekChar(s);
|
c = PeekChar(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -889,7 +842,7 @@ namespace Assignment_1
|
|||||||
}
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
public class ParserException : Exception
|
public class ParserException : Exception
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user