mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
159 lines
4.4 KiB
C#
159 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using ZoneCodeGenerator.Parsing.Matching;
|
|
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
|
using ZoneCodeGenerator.Utils;
|
|
|
|
namespace ZoneCodeGenerator.Parsing.Testing
|
|
{
|
|
abstract class AbstractTokenTest<TState> : ITokenTest<TState> where TState : IParserState<TState>
|
|
{
|
|
private TokenMatchingResult lastResult;
|
|
private int tagOffset;
|
|
private readonly Dictionary<string, int> matchOffset;
|
|
|
|
public int ConsumedTokenCount => lastResult?.ConsumedTokenCount ?? 0;
|
|
|
|
private readonly TokenMatcher matcherEntryPoint;
|
|
private readonly Dictionary<string, TokenMatcher> taggedMatchers;
|
|
|
|
protected AbstractTokenTest(TokenMatcher[] matcherEntryPoint)
|
|
{
|
|
this.matcherEntryPoint = new MatcherGroupAnd(matcherEntryPoint);
|
|
taggedMatchers = new Dictionary<string, TokenMatcher>();
|
|
|
|
lastResult = null;
|
|
tagOffset = 0;
|
|
matchOffset = new Dictionary<string, int>();
|
|
|
|
BuildTaggedMatcherList(matcherEntryPoint);
|
|
}
|
|
|
|
private void BuildTaggedMatcherList(IEnumerable<TokenMatcher> matchersWithTags)
|
|
{
|
|
foreach (var tokenMatcher in matchersWithTags)
|
|
{
|
|
if (!string.IsNullOrEmpty(tokenMatcher.Tag))
|
|
{
|
|
taggedMatchers[tokenMatcher.Tag] = tokenMatcher;
|
|
}
|
|
|
|
if (tokenMatcher is GroupMatcher groupMatcher)
|
|
{
|
|
BuildTaggedMatcherList(groupMatcher.Matchers);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
lastResult = null;
|
|
tagOffset = 0;
|
|
matchOffset.Clear();
|
|
}
|
|
|
|
protected void AddTaggedMatcher(params TokenMatcher[] taggedMatcher)
|
|
{
|
|
BuildTaggedMatcherList(taggedMatcher);
|
|
}
|
|
|
|
protected string PeekTag()
|
|
{
|
|
return lastResult?.MatchedTags.ElementAtOrDefault(tagOffset);
|
|
}
|
|
|
|
protected string NextTag()
|
|
{
|
|
return lastResult?.MatchedTags.ElementAtOrDefault(tagOffset++);
|
|
}
|
|
|
|
protected bool HasMatcherTokens(string matcherName)
|
|
{
|
|
return GetMatcherTokenCount(matcherName) > 0;
|
|
}
|
|
|
|
protected int GetMatcherTokenCount(string matcherName)
|
|
{
|
|
if (lastResult == null || !lastResult.NamedMatches.TryGetValue(matcherName, out var matches))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return matches.Count;
|
|
}
|
|
|
|
protected string PeekMatch(string matcherName)
|
|
{
|
|
if (!lastResult.NamedMatches.TryGetValue(matcherName, out var matches))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!matchOffset.TryGetValue(matcherName, out var offset))
|
|
{
|
|
offset = 0;
|
|
}
|
|
|
|
return matches.ElementAtOrDefault(offset);
|
|
}
|
|
|
|
protected string NextMatch(string matcherName)
|
|
{
|
|
if (!lastResult.NamedMatches.TryGetValue(matcherName, out var matches))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!matchOffset.TryGetValue(matcherName, out var offset))
|
|
{
|
|
offset = 0;
|
|
}
|
|
|
|
var result = matches.ElementAtOrDefault(offset++);
|
|
|
|
matchOffset[matcherName] = offset;
|
|
|
|
return result;
|
|
}
|
|
|
|
protected abstract void ProcessMatch(TState state);
|
|
|
|
public TokenTestResult PerformTest(TState state, ILexer lexer, bool verbose = false)
|
|
{
|
|
var context = new MatchingContext(lexer, taggedMatchers)
|
|
{
|
|
Verbose = verbose
|
|
};
|
|
|
|
if (context.Verbose)
|
|
{
|
|
Console.WriteLine($"Test {GetType().Name} start");
|
|
}
|
|
|
|
Reset();
|
|
lastResult = matcherEntryPoint.Test(context, 0);
|
|
|
|
if (!lastResult.Successful)
|
|
{
|
|
if (context.Verbose)
|
|
{
|
|
Console.WriteLine($"Test {GetType().Name} failed");
|
|
}
|
|
|
|
return TokenTestResult.NoMatch;
|
|
}
|
|
|
|
ProcessMatch(state);
|
|
|
|
if (context.Verbose)
|
|
{
|
|
Console.WriteLine($"Test {GetType().Name} successful");
|
|
}
|
|
|
|
return TokenTestResult.Match;
|
|
}
|
|
}
|
|
}
|