Fixed appending characters,

Candidate for closing #2
This commit is contained in:
Brychan Dempsey 2021-03-15 16:42:37 +13:00
parent 63a53a6436
commit ff4eaa0997

View File

@ -289,7 +289,7 @@ namespace Assignment_1
}
string identifier;
long identifierEndPos = FindIdentifier(source, out identifier);
if (identifierEndPos <= source.Position + 1 || identifier.Trim().Length == 0)
if (identifierEndPos < source.Position || identifier.Trim().Length == 0)
{
WriteDebugLine(lineStart, "set ".Length, "expected an identifier", source);
return false;
@ -402,40 +402,30 @@ namespace Assignment_1
// 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 = "";
while (s.Position < s.Length && !IsNextEoS(s))
{
}
// must contain at least one value, so parse the next word
string result;
long wordEnd = FindValue(s, out result);
int sequenceCount = 0;
// If the word after the word we just parsed is the concatenation operator ('+'),
// then there may be more we can parse afterwards.
// Ensure we aren't at the end of the stream; the next value isn't the EoS, and that we haven't
// parsed two values in a row
while (s.Position < s.Length && !IsNextEoS(s) && sequenceCount < 2)
{
long currStart = s.Position;
if (IsNextEoS(s, '+'))
{
// next char is an append; skip
sequenceCount = 0;
s.Position = FindNextWord(s, out _);
}
else
{
sequenceCount++;
string tValue;
s.Position = FindValue(s, out tValue);
result += tValue;
string value;
long firstPos = s.Position;
long val = FindValue(s, out value);
if (val == -1)
{
Console.WriteLine("Could not parse value");
}
s.Position = val;
result += value;
}
}
expression = result;
return wordEnd;
return s.Position;
}
/// <summary>
/// Checks ahead to see if the next non-whitespace character is the EoS indicator (';')
@ -445,16 +435,17 @@ namespace Assignment_1
/// <returns>true if the next char is <paramref name="EoSChar"/>, else false</returns>
static bool IsNextEoS(Stream s, char EoSChar = ';')
{
long pos = s.Position;
char readChar = PeekChar(s);
while (readChar != -1 && char.IsWhiteSpace(readChar))
while (readChar != 0 && char.IsWhiteSpace(readChar))
{
readChar = PeekChar(s);
readChar = ReadChar(s);
}
s.Position = pos;
if (readChar == EoSChar) return true;
else return false;
}
// Most atomic unit is 'value':
/// <summary>
/// Finds the next value in the stream
/// </summary>
@ -464,16 +455,18 @@ namespace Assignment_1
long FindValue(Stream s, out string returnedValue)
{
SkipWhitespace(s);
int result = s.ReadByte();
char result = PeekChar(s);
if (result == '\"')
{
// The first char is a ", i.e. the start of a literal - search as if it were a literal.
return FindLiteral(s, out returnedValue);
}
else
{
s.Position--;
string keyValue;
long t = FindExistingIdentifier(s, out keyValue);
// Set the key value to result + this read string
//keyValue = result + keyValue;
if (!Symbols.ContainsKey(keyValue))
{
@ -495,20 +488,30 @@ namespace Assignment_1
{
string identifier;
long wordEnd = FindNextWord(s, out identifier);
if (identifier.EndsWith(';') && identifier.Length > 1)
if (identifier.Length > 1 && identifier.EndsWith(';'))
{
// Remove the trailing semicolon from the parse & backtrack the identifier length one spot
identifier = identifier.TrimEnd(';');
wordEnd--;
s.Position--;
}
// Lookup the value in the symbol table
returnedKey = identifier;
return wordEnd;
}
/// <summary>
/// Finds the end of the complete literal definition, returning the stream to the original position
/// </summary>
/// <param name="s"></param>
/// <param name="returnedLiteral"></param>
/// <returns></returns>
long FindLiteral(Stream s, out string returnedLiteral)
{
long pos = s.Position;
// Is a literal. Now we must parse until we find the end of the literal
// Remove the first char, if it is a literal definition.
if (PeekChar(s) == '\"') ReadChar(s);
string resultLiteral;
long resultPosition = FindNextOccurance(s, (c, s) =>
{
@ -535,6 +538,7 @@ namespace Assignment_1
{
returnedLiteral = "";
}
s.Position = pos;
return resultPosition;
}
#endregion
@ -562,18 +566,35 @@ namespace Assignment_1
/// <returns></returns>
static long FindNextWord(Stream s, out string nextWord)
{
// Find the next occurance of a whitespace character
long originalPos = s.Position;
string tempstring;
long nextWSOccurance = FindNextOccurance(s, (c, s) => Char.IsWhiteSpace(c), out tempstring);
while (tempstring.Length == 0 && s.Position < s.Length)
StringBuilder newWord = new StringBuilder();
// Record our current position
long start = s.Position;
// Check if the character at the current pos is whitespace, if so, keep advancing until it isn't
char currentChar = ReadChar(s);
while (s.Position < s.Length && char.IsWhiteSpace(currentChar))
{
nextWSOccurance = FindNextOccurance(s, (c, s) => Char.IsWhiteSpace(c), out tempstring);
s.Position++;
currentChar = ReadChar(s);
}
nextWord = tempstring;
s.Position = originalPos;
return nextWSOccurance;
// Add the last read value to the SB
newWord.Append(currentChar);
// Start a second loop, this time checking we're not a whitespace char
while (s.Position < s.Length)
{
currentChar = ReadChar(s);
if (char.IsWhiteSpace(currentChar))
{
break;
}
else
{
newWord.Append(currentChar);
}
}
nextWord = newWord.ToString();
long endPos = s.Position;
s.Position = start;
return endPos;
}
@ -686,7 +707,7 @@ namespace Assignment_1
char c = PeekChar(s);
while (s.Position < s.Length && char.IsWhiteSpace(c))
{
s.Position++;
ReadChar(s); // move by the size of that character
c = PeekChar(s);
}
}