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 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 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 tokens, int offset, System.Func 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 GetSeparatorsInBrackets( List tokens, int offset, string seperator = "," ) { var openTypes = new List(){ "(","[","{" }; var closingTypes = new List(){ ")","]","}" }; var stack = new List(); var separators = new List(); 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 tokens, int offset ) { var openTypes = new List(){ "(","[","{" }; var closingTypes = new List(){ ")","]","}" }; 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 tokens, int offset, System.Func 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; } } }