Code/Tokenisation/ValueTokenExtractor.cs
using System;
using System.Linq;
namespace Expressive.Tokenisation
{
internal class ValueTokenExtractor : ITokenExtractor
{
private readonly string value;
public ValueTokenExtractor(string value)
{
this.value = value ?? throw new ArgumentNullException(nameof(value));
}
public Token ExtractToken(string expression, int currentIndex, Context context)
{
var character = expression[currentIndex];
var expressionLength = expression.Length;
var initialToken = this.value.First();
if (string.Equals(character.ToString(), initialToken.ToString(), context.ParsingStringComparison) &&
CanExtractValue(expression, expressionLength, currentIndex, this.value, context))
{
return new Token(this.value, currentIndex);
}
return null;
}
private static bool CanExtractValue(string expression, int expressionLength, int index, string expectedValue, Context context)
{
return string.Equals(expectedValue, ExtractValue(expression, expressionLength, index, expectedValue, context), context.ParsingStringComparison);
}
private static string ExtractValue(string expression, int expressionLength, int index, string expectedValue, Context context)
{
string result = null;
var valueLength = expectedValue.Length;
if (expressionLength >= index + valueLength)
{
var valueString = expression.Substring(index, valueLength);
bool isValidValue = true;
if (expressionLength > index + valueLength)
{
// If the next character is not a continuation of the word then we are valid.
isValidValue = !char.IsLetterOrDigit(expression[index + valueLength]) ||
string.Equals(expectedValue, Context.ParameterSeparator.ToString(), context.ParsingStringComparison); // TODO: perhaps the parameter separator handling should be done inside a specific extractor...
}
if (string.Equals(valueString, expectedValue, context.ParsingStringComparison) &&
isValidValue)
{
result = valueString;
}
}
return result;
}
}
}