53 lines
1.4 KiB
C#
53 lines
1.4 KiB
C#
|
|
namespace GParse;
|
|
|
|
public class QuoteAwareParser(string delimiter, string openQuote, string closeQuote) : ITextParser
|
|
{
|
|
public IEnumerable<string> Parse(ITextInputProvider textInputProvider) => Parse(textInputProvider.GetText());
|
|
|
|
public IEnumerable<string> Parse(string text)
|
|
{
|
|
if (delimiter == openQuote || delimiter == closeQuote)
|
|
throw new ArgumentException("Delimiter cannot be the same as the quotes.");
|
|
|
|
int size = text.Length;
|
|
int delimiterSize = delimiter.Length;
|
|
int openQuoteSize = openQuote.Length;
|
|
int closeQuoteSize = closeQuote.Length;
|
|
int index = 0;
|
|
bool inQuote = false;
|
|
int tokenStartIndex = 0;
|
|
|
|
while (index <= size - 1)
|
|
{
|
|
if (!inQuote && (text.SafeSubstring(index, openQuoteSize) == openQuote))
|
|
{
|
|
// Enter quotes.
|
|
inQuote = true;
|
|
index += openQuoteSize - 1;
|
|
}
|
|
else if (inQuote && (text.SafeSubstring(index, closeQuoteSize) == closeQuote))
|
|
{
|
|
inQuote = false;
|
|
index += closeQuoteSize - 1;
|
|
}
|
|
else if (!inQuote && (text.SafeSubstring(index, delimiterSize) == delimiter))
|
|
{
|
|
string token = text.SafeSubstring(tokenStartIndex, index - tokenStartIndex);
|
|
yield return token;
|
|
|
|
tokenStartIndex = index + delimiterSize;
|
|
index += delimiterSize - 1;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
|
|
if (inQuote)
|
|
throw new ParseException("Unterminated quotation in input string.");
|
|
|
|
string lastToken = text.SafeSubstring(tokenStartIndex, index - tokenStartIndex);
|
|
yield return lastToken;
|
|
}
|
|
}
|