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; string identifier;
long identifierEndPos = FindIdentifier(source, out 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); WriteDebugLine(lineStart, "set ".Length, "expected an identifier", source);
return false; return false;
@ -402,40 +402,30 @@ namespace Assignment_1
// Variable symbols should be evaluated immediately. // Variable symbols should be evaluated immediately.
// Start by ensuring we don't try reading past the end of the stream // Start by ensuring we don't try reading past the end of the stream
// Also check for the EoS // Also check for the EoS
long realStart = s.Position;
string result = ""; string result = "";
while (s.Position < s.Length && !IsNextEoS(s)) while (s.Position < s.Length && !IsNextEoS(s))
{ {
long currStart = s.Position;
}
// 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)
{
if (IsNextEoS(s, '+')) if (IsNextEoS(s, '+'))
{ {
// next char is an append; skip
sequenceCount = 0;
s.Position = FindNextWord(s, out _); s.Position = FindNextWord(s, out _);
} }
else else
{ {
sequenceCount++; string value;
string tValue; long firstPos = s.Position;
s.Position = FindValue(s, out tValue); long val = FindValue(s, out value);
result += tValue; if (val == -1)
{
Console.WriteLine("Could not parse value");
}
s.Position = val;
result += value;
} }
} }
expression = result; expression = result;
return wordEnd; 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 (';')
@ -445,16 +435,17 @@ namespace Assignment_1
/// <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 = ';')
{ {
long pos = s.Position;
char readChar = PeekChar(s); 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; if (readChar == EoSChar) return true;
else return false; else return false;
} }
// Most atomic unit is 'value':
/// <summary> /// <summary>
/// Finds the next value in the stream /// Finds the next value in the stream
/// </summary> /// </summary>
@ -464,16 +455,18 @@ namespace Assignment_1
long FindValue(Stream s, out string returnedValue) long FindValue(Stream s, out string returnedValue)
{ {
SkipWhitespace(s); SkipWhitespace(s);
int result = s.ReadByte(); char result = PeekChar(s);
if (result == '\"') 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); return FindLiteral(s, out returnedValue);
} }
else else
{ {
s.Position--;
string keyValue; string keyValue;
long t = FindExistingIdentifier(s, out keyValue); long t = FindExistingIdentifier(s, out keyValue);
// Set the key value to result + this read string
//keyValue = result + keyValue;
if (!Symbols.ContainsKey(keyValue)) if (!Symbols.ContainsKey(keyValue))
{ {
@ -495,20 +488,30 @@ namespace Assignment_1
{ {
string identifier; string identifier;
long wordEnd = FindNextWord(s, out 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 // Remove the trailing semicolon from the parse & backtrack the identifier length one spot
identifier = identifier.TrimEnd(';'); identifier = identifier.TrimEnd(';');
wordEnd--; wordEnd--;
s.Position--;
} }
// Lookup the value in the symbol table // Lookup the value in the symbol table
returnedKey = identifier; returnedKey = identifier;
return wordEnd; 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 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 // 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; string resultLiteral;
long resultPosition = FindNextOccurance(s, (c, s) => long resultPosition = FindNextOccurance(s, (c, s) =>
{ {
@ -535,6 +538,7 @@ namespace Assignment_1
{ {
returnedLiteral = ""; returnedLiteral = "";
} }
s.Position = pos;
return resultPosition; return resultPosition;
} }
#endregion #endregion
@ -562,18 +566,35 @@ namespace Assignment_1
/// <returns></returns> /// <returns></returns>
static long FindNextWord(Stream s, out string nextWord) static long FindNextWord(Stream s, out string nextWord)
{ {
// Find the next occurance of a whitespace character StringBuilder newWord = new StringBuilder();
long originalPos = s.Position; // Record our current position
string tempstring; long start = s.Position;
long nextWSOccurance = FindNextOccurance(s, (c, s) => Char.IsWhiteSpace(c), out tempstring); // Check if the character at the current pos is whitespace, if so, keep advancing until it isn't
while (tempstring.Length == 0 && s.Position < s.Length) char currentChar = ReadChar(s);
while (s.Position < s.Length && char.IsWhiteSpace(currentChar))
{ {
nextWSOccurance = FindNextOccurance(s, (c, s) => Char.IsWhiteSpace(c), out tempstring); currentChar = ReadChar(s);
s.Position++;
} }
nextWord = tempstring; // Add the last read value to the SB
s.Position = originalPos; newWord.Append(currentChar);
return nextWSOccurance; // 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); char c = PeekChar(s);
while (s.Position < s.Length && char.IsWhiteSpace(c)) while (s.Position < s.Length && char.IsWhiteSpace(c))
{ {
s.Position++; ReadChar(s); // move by the size of that character
c = PeekChar(s); c = PeekChar(s);
} }
} }