rj-action-library/Runtime/Text/Lexing/LexerEvent.cs

350 lines
7.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
namespace Rokojori
{
public class LexerEvent
{
string _type;
int _offset;
int _length;
string _match;
public string match => _match;
public LexerEvent( string type, int offset, int length )
{
Set( type, offset, length );
}
public string type { get { return _type; } }
public int offset { get { return _offset; } }
public int length { get { return _length; } }
string _mode = null;
public string mode
{
get
{
if ( _mode != null )
{
return _mode;
}
var modeDelimiterPosition = type.IndexOf( LexerMatcher.FullTypeDelimiter );
if ( modeDelimiterPosition == -1 )
{
_mode = "";
return _mode;
}
_mode = type.Substring( 0, modeDelimiterPosition );
return _mode;
}
}
public bool isError
{
get { return this.length == -1; }
}
public bool isDone
{
get { return this.length == -2; }
}
public void Set( string type, int offset, int length )
{
this._type = type;
this._offset = offset;
this._length = length;
}
public LexerEvent Copy()
{
return new LexerEvent( _type, _offset, _length );
}
public int end
{
get { return this._offset + _length; }
}
public override string ToString()
{
if ( match != null )
{
return "Token{ '" + type + "':'" + match + "' (" + offset + "-" + end + ") }";
}
return "Token{ '" + type + "' (" + offset + "-" + end + ") }";
}
public void GrabMatch( string source )
{
if ( _length < 0 )
{
return;
}
_match = source.Substring( offset, length );
}
public bool Is( string type, string match = null )
{
var typeCorrect = type == null || type == this.type;
if ( ! typeCorrect )
{
return false;
}
return match == null || match == this.match;
}
public bool Is( LexerMatcher matcher, string match = null )
{
return Is( matcher == null ? null : matcher.type, match );
}
public bool MatchIs( string match )
{
return match == this.match;
}
public bool MatchIsAny( params string[] matches )
{
for ( int i = 0; i < matches.Length; i++ )
{
if ( MatchIs( matches[ i ] ) )
{
return true;
}
}
return false;
}
public bool IsAny( LexerMatcher matcher, params string[] matches )
{
if ( matches == null || matches.Length == 0 )
{
return Is( matcher );
}
var correctType = matcher == null || matcher.type == type;
if ( ! correctType )
{
return false;
}
return MatchIsAny( matches );
}
public enum FindResultType
{
Found,
KeepSearching,
NotFound,
Error
}
public class FindResult
{
public FindResultType type = FindResultType.NotFound;
public int index;
public FindResult()
{ }
public FindResult( FindResultType type, int index )
{
this.type = type;
this.index = index;
}
}
public static FindResult Found( int index)
{
return new FindResult( FindResultType.Found, index );
}
public static FindResult KeepSearch( int index )
{
return new FindResult( FindResultType.KeepSearching, index );
}
public static FindResult NotFound( int index )
{
return new FindResult( FindResultType.NotFound, index );
}
public static FindResult Error( int index )
{
return new FindResult( FindResultType.NotFound, index );
}
public static string GetMatchFromRange( List<LexerEvent> tokens, int offset, int length = -1 )
{
if ( length == -1 )
{
length = tokens.Count - offset;
}
var match = new StringBuilder();
for ( int i = 0; i < length; i++ )
{
match.Append( tokens[ offset + i ].match );
}
return match.ToString();
}
public static int Find( List<LexerEvent> tokens, int offset, params string[] types )
{
for ( int i = offset; i < tokens.Count; i++ )
{
if ( Arrays.IndexOf( types, tokens[ i ].type ) != -1 )
{
return i;
}
}
return -1;
}
public static FindResult Find( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,FindResultType> evaluator )
{
var result = new FindResult();
for ( int i = offset; i < tokens.Count; i++ )
{
var tokenResult = evaluator( tokens[ i ] );
if ( tokenResult == FindResultType.Error ||
tokenResult == FindResultType.Found
)
{
result.type = tokenResult;
result.index = i;
return result;
}
}
return result;
}
public static List<int> GetSeparatorsInBrackets( List<LexerEvent> tokens, int offset, string seperator = "," )
{
var openTypes = new List<string>(){ "(","[","{" };
var closingTypes = new List<string>(){ ")","]","}" };
var stack = new List<string>();
var separators = new List<int>();
for ( int i = offset; i < tokens.Count; i++ )
{
if ( stack.Count == 1 && tokens[ i ].MatchIs( seperator ) )
{
separators.Add( i );
}
var match = tokens[ i ].match;
if ( openTypes.Contains( match ) )
{
stack.Add( match );
continue;
}
else if ( closingTypes.Contains( match ) )
{
var closingTypeIndex = closingTypes.IndexOf( match );
var expectedOpener = openTypes[ closingTypeIndex ];
if ( stack[ stack.Count - 1 ] != expectedOpener )
{
return null;
}
stack.RemoveAt( stack.Count - 1 );
}
}
return separators;
}
public static FindResult FindClosingBracket( List<LexerEvent> tokens, int offset )
{
var openTypes = new List<string>(){ "(","[","{" };
var closingTypes = new List<string>(){ ")","]","}" };
var token = tokens[ offset ];
var bracketIndex = openTypes.IndexOf( token.match );
if ( bracketIndex == -1 )
{
var result = new FindResult( FindResultType.NotFound, offset );
return result;
}
var opener = openTypes[ bracketIndex ];
var closer = closingTypes[ bracketIndex ];
var counter = ( LexerEvent le ) =>
{
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) )
{
return -1;
}
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) )
{
return 1;
}
return 0;
};
return FindCloser( tokens, offset, counter );
}
public static FindResult FindCloser( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,int> counter )
{
var result = new FindResult();
var currentValue = 0;
for ( int i = offset; i < tokens.Count; i++ )
{
var countResult = counter( tokens[ i ] );
currentValue += countResult;
if ( currentValue == 0 )
{
result.type = FindResultType.Found;
result.index = i;
return result;
}
}
return result;
}
}
}