UnityExplorer/src/Console/Lexer/InputLexer.cs

201 lines
5.3 KiB
C#
Raw Normal View History

using System.Collections.Generic;
2020-11-05 17:33:04 +11:00
namespace UnityExplorer.Console.Lexer
{
public struct LexerMatchInfo
{
public int startIndex;
public int endIndex;
public string htmlColor;
}
public enum SpecialCharacterPosition
{
Start,
End,
};
public class InputLexer
{
private string inputString = null;
private Matcher[] matchers = null;
private readonly HashSet<char> specialStartSymbols = new HashSet<char>();
private readonly HashSet<char> specialEndSymbols = new HashSet<char>();
private int currentIndex = 0;
private int currentLookaheadIndex = 0;
private char current = ' ';
public char Previous { get; private set; } = ' ';
public bool EndOfStream
{
get { return currentLookaheadIndex >= inputString.Length; }
}
public void UseMatchers(char[] delimiters, Matcher[] matchers)
{
this.matchers = matchers;
specialStartSymbols.Clear();
specialEndSymbols.Clear();
if (delimiters != null)
{
foreach (char character in delimiters)
{
if (!specialStartSymbols.Contains(character))
{
specialStartSymbols.Add(character);
}
if (!specialEndSymbols.Contains(character))
{
specialEndSymbols.Add(character);
}
}
}
if (matchers != null)
{
foreach (Matcher lexer in matchers)
{
2020-10-26 01:07:59 +11:00
foreach (char special in lexer.StartChars)
{
if (!specialStartSymbols.Contains(special))
{
specialStartSymbols.Add(special);
}
}
2020-10-26 01:07:59 +11:00
foreach (char special in lexer.EndChars)
{
if (!specialEndSymbols.Contains(special))
{
specialEndSymbols.Add(special);
}
}
}
}
}
2020-10-26 01:07:59 +11:00
public IEnumerable<LexerMatchInfo> LexInputString(string input)
{
if (input == null || matchers == null || matchers.Length == 0)
{
yield break;
}
inputString = input;
current = ' ';
Previous = ' ';
currentIndex = 0;
currentLookaheadIndex = 0;
while (!EndOfStream)
{
bool didMatchLexer = false;
ReadWhiteSpace();
foreach (Matcher matcher in matchers)
{
int startIndex = currentIndex;
bool isMatched = matcher.IsMatch(this);
if (isMatched)
{
int endIndex = currentIndex;
didMatchLexer = true;
2020-10-26 01:07:59 +11:00
yield return new LexerMatchInfo
{
startIndex = startIndex,
endIndex = endIndex,
2020-10-26 01:07:59 +11:00
htmlColor = matcher.HexColor,
};
break;
}
}
if (!didMatchLexer)
{
ReadNext();
Commit();
}
}
}
public char ReadNext()
{
if (EndOfStream)
{
return '\0';
}
Previous = current;
current = inputString[currentLookaheadIndex];
currentLookaheadIndex++;
return current;
}
public void Rollback(int amount = -1)
{
if (amount == -1)
{
currentLookaheadIndex = currentIndex;
}
else
{
if (currentLookaheadIndex > currentIndex)
{
currentLookaheadIndex -= amount;
}
}
int previousIndex = currentLookaheadIndex - 1;
if (previousIndex >= inputString.Length)
{
Previous = inputString[inputString.Length - 1];
}
else if (previousIndex >= 0)
{
Previous = inputString[previousIndex];
}
else
{
Previous = ' ';
}
}
public void Commit()
{
currentIndex = currentLookaheadIndex;
}
public bool IsSpecialSymbol(char character, SpecialCharacterPosition position = SpecialCharacterPosition.Start)
{
if (position == SpecialCharacterPosition.Start)
{
return specialStartSymbols.Contains(character);
}
return specialEndSymbols.Contains(character);
}
private void ReadWhiteSpace()
{
while (char.IsWhiteSpace(ReadNext()) == true)
{
Commit();
}
Rollback();
}
}
}