Exemple #1
0
        public string Generate(MatcherEngineGenerator generator)
        {
            string version = AssemblyName.GetAssemblyName(GetType().Assembly.Location).Version.ToString();

            return($@"
/* Generated by Synfron.Staxe.Matcher v{version}*/

using Synfron.Staxe.Matcher.Data;
using System.Collections.Generic;
using System;
using System.Linq;
using Synfron.Staxe.Matcher.Input;
{(generator.LanguageMatcher.LogMatches ? "using System.Text;" : null)}

namespace Synfron.Staxe.Matcher
{{
    public class {GetSafeMethodName(Name)}MatchEngine : AbstractLanguageMatchEngine
    {{

        {GenerateMatch(generator)}

        <<Generated Methods>>
    }}
}}");
        }
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchWholeWord{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
            if (startOffset - 1 >= 0 && char.IsLetterOrDigit(text[startOffset - 1]))
            {{
                return (false, 0);
            }}

            (bool success, int offset) = {string.Format(_subPattern.Generate(generator), "text", "startOffset")};

            int next = startOffset + offset;
            if (success && next < text.Length && char.IsLetterOrDigit(text[next]))
            {{
                return (false, 0);
            }}
            return (success, offset);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchInsensitiveLiteral{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
            string literal = {$"\"{_literal.Replace(@"\", @"\\").Replace(@"""", @"\""").Replace("\n", @"\n").Replace("\t", @"\t")}\""};
            int length = literal.Length;
            if (startOffset + length > text.Length)
            {{
                return (false, 0);
            }}
            for (int i = 0; i < length; i++)
            {{
                if (char.ToLowerInvariant(text[i + startOffset]) != char.ToLowerInvariant(literal[i]))
                {{
                    return (false, 0);
                }}
            }}
            return (true, length);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #4
0
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchGroup{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                int      numPatterns = _subPatterns.Count;
                string[] parts       = new string[numPatterns];
                for (int i = 0; i < numPatterns; i++)
                {
                    parts[i] = $@"
                (success, subOffset) = {string.Format(_subPatterns[i].Generate(generator), "text", "offset")};
                if (!success)
                {{
                    return (false, 0);
                }}
                offset += subOffset;";
                }

                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{

            int offset = startOffset;
            bool success;
            int subOffset;
            {string.Join("\n", parts)}
            return (true, offset - startOffset);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchCountBounds{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
			int offset = startOffset;
			bool subSuccess = true;
			int subOffset;
			int matches = 0;
			for (; matches < {_upperBounds} && subSuccess; matches++)
			{{
				(subSuccess, subOffset) = {string.Format(_subPattern.Generate(generator), "text", "offset")};
				offset += subOffset;
            }}
			bool success = subSuccess || matches >= {_lowerBounds};
            return success ? (true, offset - startOffset) : (false, 0);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #6
0
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchOneOrMore{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
            int offset = startOffset;
            bool subSuccess = true;
            bool success = false;
            int subOffset;
            while (subSuccess)
            {{
                (subSuccess, subOffset) = {string.Format(_subPattern.Generate(generator), "text", "offset")};
                offset += subOffset;
                success |= subSuccess;
            }}
            return success ? (true, offset - startOffset) : (false, 0);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #7
0
        private string GenerateMatchPartByTextMatcher(MatcherEngineGenerator generator, PatternMatcher matcher)
        {
            string methodName = $"MatchPartByTextMatcher{GetSafeMethodName(matcher.Name)}";
            string method     = $"{methodName}(ref state, matchData)";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private bool {methodName}(ref State state, FragmentMatchData matchData)
        {{
            
            {(generator.LanguageMatcher.LogMatches ? $@"int currentId = ++state.Id;
            state.MatchLogBuilder.AppendLine($""{{new String('\t', currentId)}} {{state.CurrentIndex}}. Try: {HttpUtility.JavaScriptStringEncode(matcher.Name)}"");" : null)}
			StringMatchData partMatchData;
            bool success = {string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, matcher), "partMatchData", "true", "false")};
            if (success)
            {{
                matchData.Parts.Add(partMatchData);
                {(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{new String('\t', state.Id + 1)}} {{state.CurrentIndex}}. Matched: {{partMatchData.Text}}"");" : null)}
            }}

            {(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{new String('\t', currentId)}} {{state.CurrentIndex}}. {{(success ? ""Passed"" : ""Failed"")}}: {HttpUtility.JavaScriptStringEncode(matcher.Name)}"");
            state.Id = currentId - 1;" : null)}
            return success;
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #8
0
		internal override string Generate(MatcherEngineGenerator generator)
		{
			if (_patternMatcher == null)
			{
				_patternMatcher = PatternReader.Parse(_pattern);
			}
			return _patternMatcher.Generate(generator);
		}
Exemple #9
0
 internal override string Generate(MatcherEngineGenerator generator)
 {
     return($@"(() => {{
         Regex regex = new Regex({regex.ToString()});
         Match match = regex.Match({{0}}, {{1}});
         return (match?.Value, match?.Length ?? 0);
     }})()");
 }
Exemple #10
0
        private string GenerateMatchFragmentParts(MatcherEngineGenerator generator)
        {
            switch (PartsMatchMode)
            {
            case MatchMode.Ordered:
                return(GenerateMatchFragmentPartsOrderedMode(generator));

            case MatchMode.One:
                return(GenerateMatchFragmentPartsOneMode(generator));

            case MatchMode.Multiple:
            default:
                return(GenerateMatchFragmentPartsMultipleMode(generator));
            }
        }
Exemple #11
0
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchNot{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
            return text.Length > startOffset && !{string.Format(_subPattern.Generate(generator), "text", "startOffset")}.success ? (true, 0) : (false, 0);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
        internal override string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchCharBounds{_id}";
            string method     = $"{methodName}({{0}}, {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private (bool success, int offset) {methodName}(string text, int startOffset)
        {{
			int charVal = text[startOffset];
			return ({(int)_lowerBounds} <= charVal && {(int)_upperBounds} >= charVal) ? (true, 1) : (false, 0);
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #13
0
        private string GenerateMatchFragmentBounds(MatcherEngineGenerator generator, PatternMatcher matcher)
        {
            string methodName = $"MatchFragmentBounds{GetSafeMethodName(matcher.Name)}";
            string method     = $"{methodName}(ref state, {{0}}, out {{1}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private bool {methodName}(ref State state, bool readOnly, out StringMatchData matchData)
        {{
            bool success = {string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, matcher), "matchData", "true", "readOnly")};
            if ({(!Negate ? "!" : null)}success)
            {{
				state.FailureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex);
            }}
			{(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{new String('\t', state.Id + 1)}} {{state.CurrentIndex}}. {{(success ? ""Passed"" : ""Failed"")}} Bounds: {{""{HttpUtility.JavaScriptStringEncode(matcher.ToString())}""}}"");" : null)}
            return success;
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #14
0
        private string GenerateMatchFragmentPartsOneMode(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchFragmentPartsOneMode{GetSafeMethodName(Name)}";
            string method     = $"{methodName}(ref state, partMatcherData)";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private bool {methodName}(ref State state, FragmentMatchData matchData)
                {{
                    bool success = false;
                    int matchCount = 0;
                    {(PartsPadding != null ? $"{string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false")};" : null)}

                    {(Parts.Count > 0 ? $@"
                    success = {string.Join(" || ", Parts.Select(part => GenerateMatchFragmentPart(generator, part)))};
                    if (success)
                    {{
                        matchCount++;
                    }}" : null)}

                    {(PartsPadding != null ?
						$@"if (success)
                    {{
                        {string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false")};
                    }}" : null)}
            
                    success = {((MinMatchedParts ?? 1) <= 0).ToString().ToLower()} || matchCount > 0;
                    if ({(!Negate ? "!" : null)}success)
                    {{
						state.FailureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex);
                    }}
                    return success;
                }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #15
0
        public string Generate(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchFragment{GetSafeMethodName(Name)}";
            string method     = $"{methodName}(ref state, matchData)";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private bool {methodName}(ref State state, FragmentMatchData matchData)
        {{
            {(generator.LanguageMatcher.LogMatches ? $@"int currentId = ++state.Id;
            state.MatchLogBuilder.AppendLine($""{{new String('\t', currentId)}} {{state.CurrentIndex}}. Try: {GetEscapedName()}"");" : null)}
			bool success = false;
			FragmentMatchData partMatcherData = null;
			{(Cacheable ? $@"if (!state.MatchCache.TryGetValue(new ValueTuple<string, int>(""{GetEscapedName()}"", state.CurrentIndex), out partMatcherData))
			{{" : null)}
				int startIndex = state.CurrentIndex;
				int distinctIndex = state.DistinctIndex;
				partMatcherData = new FragmentMatchData
				{{
					Name = ""{GetEscapedName()}"",
					StartIndex = state.CurrentIndex{(ExpressionOrder != null ? $@",
					ExpressionOrder = {ExpressionOrder}" : null)}
				}};

				{(Start != null ? $"StringMatchData startMatchData;" : null)}
				{(End != null ? $"StringMatchData endMatchData;" : null)}
				success = ({(Start != null ? $"{string.Format(GenerateMatchFragmentBounds(generator, Start), DiscardBounds.ToString().ToLower(), "startMatchData")} && " : null)}{GenerateMatchFragmentParts(generator)}{(End != null ? $" && {string.Format(GenerateMatchFragmentBounds(generator, End), DiscardBounds.ToString().ToLower(), "endMatchData")}" : null)});
				
				
				if (success)
				{{
					{(!Negate ? $@"partMatcherData.Length = state.CurrentIndex - partMatcherData.StartIndex;
					partMatcherData.EndDistinctIndex = state.DistinctIndex;" : null)}
					{(Cacheable ? $@"state.MatchCache[new ValueTuple<string, int>(""{GetEscapedName()}"", startIndex)] = partMatcherData;" : null)}
					{(!IsNoise && ExpressionMode != ExpressionMode.None && !Negate ? $"ConvertToExpressionTree(partMatcherData, ExpressionMode.{ExpressionMode.ToString()});" : null)}
					{(BoundsAsParts && Start != null && !Negate ? $@"if (startMatchData != null)
					{{
						partMatcherData.Parts.Insert(0, startMatchData);
					}}" : null)}
					{(BoundsAsParts && End != null && !Negate ? $@"if (endMatchData != null)
					{{
						partMatcherData.Parts.Add(endMatchData);
					}}" : null)}
				}}
				else
				{{
					{(Cacheable ? $@"state.MatchCache[new ValueTuple<string, int>(""{GetEscapedName()}"", startIndex)] = null;" : null)}
					{(!Negate ? $@"state.CurrentIndex = startIndex;
					state.DistinctIndex = distinctIndex;" : null)}
				}}
				{(Negate ? $@"state.CurrentIndex = startIndex;
				state.DistinctIndex = distinctIndex;" : null)}
			{(Cacheable ? $@"}}" : null)}
			{(Cacheable && !Negate ? $@"else if (success = partMatcherData != null)
			{{
				state.CurrentIndex = partMatcherData.StartIndex + partMatcherData.Length;
				state.DistinctIndex = partMatcherData.EndDistinctIndex;
			}}" : null)}
            {(!Negate ? $@"if (success)
            {{
				{(!IsNoise && FallThrough ? "matchData.Parts.AddRange(partMatcherData.Parts);" : null)}
				{(!IsNoise && !FallThrough ? "matchData.Parts.Add(partMatcherData);" : null)}
				{(ClearCache ? "state.MatchCache.Clear();" : null)}
			}}" : null)}
            {(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{new String('\t', currentId)}} {{state.CurrentIndex}}. {{({(Negate ? "!" : null)}success ? ""Passed"" : ""Failed"")}}: {GetEscapedName()}"");
            state.Id = currentId - 1;" : null)}
            return {(Negate ? "!" : null)}success;
        }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
 internal override string Generate(MatcherEngineGenerator generator) => _subPattern.Generate(generator);
Exemple #17
0
 private string GenerateMatchFragmentPart(MatcherEngineGenerator generator, IMatcher part)
 {
     return(part is FragmentMatcher fragmentMatcher
                         ? fragmentMatcher.Generate(generator)
                         : GenerateMatchPartByTextMatcher(generator, (PatternMatcher)part));
 }
Exemple #18
0
        private string GenerateMatchFragmentPartsMultipleMode(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchFragmentPartsMultipleMode{GetSafeMethodName(Name)}";
            string method     = $"{methodName}(ref state, partMatcherData)";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                StringBuilder functionText = new StringBuilder();
                for (int partIndex = 0; partIndex < Parts.Count; partIndex++)
                {
                    functionText.AppendLine($@"individualSuccess = {GenerateMatchFragmentPart(generator, Parts[partIndex])};
                    subSuccess |= individualSuccess;
                    if (individualSuccess)
                    {{
                        matchCount++;
                        distinctIndex = state.DistinctIndex;
                        delimiterSuccess = {(PartsDelimiter != null ? string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsDelimiter), "range", PartsDelimiterRequired.ToString().ToLower(), "false") : "true")};
                        goto Break;
                    }}
                    ");
                }

                string code = $@"private bool {methodName}(ref State state, FragmentMatchData matchData)
                {{
                    bool overallSuccess = false;
                    bool subSuccess = false;
                    bool delimiterSuccess = false;
                    StringMatchData range = default;
                    int matchCount = 0;
                    int distinctIndex = state.DistinctIndex;
                    {(PartsPadding != null ? string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false") : null)};

                    do
                    {{
                        subSuccess = false;
                        bool individualSuccess;
                        {functionText.ToString()}

                        Break:
                        overallSuccess |= subSuccess;
                    }}
                    while (subSuccess && delimiterSuccess);
                    if (delimiterSuccess && range != null)
                    {{
                        state.CurrentIndex = range.StartIndex;
                        state.DistinctIndex = distinctIndex;
                    }}
                    {(PartsPadding != null ?
						$@"if (overallSuccess)
                    {{
                        {string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false")};
                    }}" : null)}
            
                    bool thresholdSuccess = {MinMatchedParts ?? 1} <= matchCount;
                    bool success = overallSuccess || thresholdSuccess;
                    if ({(!Negate ? "!" : null)}success)
                    {{
						state.FailureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex);
                    }}
                    return success;
                }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #19
0
        private string GenerateMatchFragmentPartsOrderedMode(MatcherEngineGenerator generator)
        {
            string methodName = $"MatchFragmentPartsOrderedMode{GetSafeMethodName(Name)}";
            string method     = $"{methodName}(ref state, partMatcherData)";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                StringBuilder functionText = new StringBuilder();
                for (int partIndex = 0; partIndex < Parts.Count; partIndex++)
                {
                    functionText.AppendLine($@"{(partIndex > 0 ? $@"distinctIndex = state.DistinctIndex;
                    partSuccess = {(PartsDelimiter != null ? string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsDelimiter), "stringMatchData", PartsDelimiterRequired.ToString().ToLower(), "false") : "true")};
                    success = partSuccess;
                    if (!success)
                    {{
                        goto Break;
                    }}" : null)}

                    success = {GenerateMatchFragmentPart(generator, Parts[partIndex])};
                if (!success)
                {{
                    if (stringMatchData != null)
                    {{
                        state.CurrentIndex = stringMatchData.StartIndex;
                        state.DistinctIndex = distinctIndex;
                    }}
                    goto Break;
                }}
                else
                {{
                    matchCount++;
                }}");
                }

                string code = $@"private bool {methodName}(ref State state, FragmentMatchData matchData)
                {{
                    bool success = true;
                    bool partSuccess;
                    int matchCount = 0;
                    StringMatchData stringMatchData = null;
                    int distinctIndex = state.DistinctIndex;
                    {(PartsPadding != null ? string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false") : null)};

                    {functionText.ToString()}

                    Break:
                    {(PartsPadding != null ?
						$@"if (success)
                    {{
                        {string.Format(generator.LanguageMatcher.GenerateMatchPattern(generator, PartsPadding), "_", "false", "false")};
                    }}" : null)}
            
                    success = success || {(MinMatchedParts ?? Parts.Count)} <= matchCount;
                    if ({(!Negate ? "!" : null)}success)
                    {{
						state.FailureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex);
                    }}
                    return success;
                }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #20
0
 internal abstract string Generate(MatcherEngineGenerator generator);
Exemple #21
0
 internal override string Generate(MatcherEngineGenerator generator)
 {
     return("MatchDigit({0}, {1})");
 }
 internal override string Generate(MatcherEngineGenerator generator)
 {
     return("MatchWhitespace({0}, {1})");
 }
Exemple #23
0
        public string GenerateMatchPattern(MatcherEngineGenerator generator, PatternMatcher pattern)
        {
            string methodName = $"MatchPattern{GetSafeMethodName(pattern.Name)}";
            string method     = $"{methodName}(ref state, out {{0}}, {{1}}, {{2}})";

            if (!generator.TryGetMethod(methodName, ref method))
            {
                generator.Add(methodName, method);
                string code = $@"private bool {methodName}(ref State state, out StringMatchData matchData, bool required, bool readOnly = false)
            {{
                bool success = false;
                {(generator.IndexingMode != IndexingMode.None ? $@"int distinctIndex = state.DistinctIndex;
                if (distinctIndex >= state.MaxDistinctIndex)
                {{" : null)}
                    int length;
                    int startOffset = state.CurrentIndex;
                    (success, length) = {GenerateRawMatchPattern(generator, pattern)};
					matchData = default;
					if (success)
					{{
						matchData = new StringMatchData
						{{
							Name = ""{HttpUtility.JavaScriptStringEncode(pattern.Name)}"",
							Text = state.Code.Substring(startOffset, length),
							StartIndex = startOffset,
							Length = length,
							IsNoise = {pattern.IsNoise.ToString().ToLower()},
							Mergable = {pattern.Mergable.ToString().ToLower()},
							Id = {pattern.Id}
						}};
						{(!pattern.IsNoise && generator.IndexingMode != IndexingMode.None ? $@"state.DistinctStringMatches.Add(matchData);" : null)}
						success = matchData != null;
						{(generator.IndexingMode == IndexingMode.Lazy ? $@"state.CheckFlags[{pattern.Id}] = distinctIndex + 1;" : null)}
						{(!pattern.IsNoise && generator.IndexingMode != IndexingMode.None ? $@"state.MaxDistinctIndex++;" : null)}
						if (!readOnly)
						{{
							{(!pattern.IsNoise && generator.IndexingMode != IndexingMode.None ? $@"state.DistinctIndex++;" : null)}
							state.CurrentIndex += matchData.Length;
						}}
					}}
					else if (!required)
					{{
						success = true;
					}}
					return success;
                {(generator.IndexingMode != IndexingMode.None ? $@"}}
                else
                {{
					matchData = state.DistinctStringMatches[distinctIndex];
                    if (matchData != null)
                    {{
						success = matchData.Id == {pattern.Id};
                    }}
                    else
                    {{
                        {(generator.IndexingMode == IndexingMode.Eager ? $@"if (state.CheckFlags[{pattern.Id}] < distinctIndex + 1)
                        {{" : null)}
                            int length;
                            int startOffset = state.CurrentIndex;
                            (success, length) = {GenerateRawMatchPattern(generator, pattern)};
                            if (success)
                            {{
								matchData = new StringMatchData
								{{
									Name = ""{GetSafeMethodName(pattern.Name)}"",
									Text = state.Code.Substring(startOffset, length),
									StartIndex = startOffset,
									Length = length,
									IsNoise = {pattern.IsNoise.ToString().ToLower()},
									Mergable = {pattern.Mergable.ToString().ToLower()},
									Id = {pattern.Id}
								}};
								{(!pattern.IsNoise ? $@"state.DistinctStringMatches[distinctIndex] = matchData;" : null)}
                            }}
                            {(generator.IndexingMode == IndexingMode.Eager ? $@"state.CheckFlags[{pattern.Id}] = distinctIndex + 1;
                        }}" : null)}
                    }}
					if (success && !readOnly)
					{{
						{(!pattern.IsNoise ? $@"state.DistinctIndex++;" : null)}
						state.CurrentIndex += matchData.Length;
					}}
					if (!required)
					{{
						success = true;
					}}
					return success;
                }}" : null)}
            }}";
                method = generator.Add(method, methodName, code);
            }
            return(method);
        }
Exemple #24
0
 private string GenerateRawMatchPattern(MatcherEngineGenerator generator, PatternMatcher pattern)
 {
     return(string.Format(pattern.Generate(generator), "state.Code", "state.CurrentIndex"));
 }
Exemple #25
0
        private string GenerateMatch(MatcherEngineGenerator generator)
        {
            return($@"
        public override MatcherResult Match(string code, string fragmentMatcher, bool matchFullText = true)
        {{
            FragmentMatchData matchData = new FragmentMatchData
            {{
                StartIndex = 0
            }};
            
			{(IndexingMode == IndexingMode.Lazy ? $"Span<int> checkFlags = stackalloc int[{Patterns.Count + 1}];" : null)}

            State state = new State()
            {{
                Code = code{(IndexingMode != IndexingMode.None ? @",
				DistinctStringMatches = new List<StringMatchData>(2000)" : null)}{(IndexingMode == IndexingMode.Lazy ? @",
				CheckFlags = checkFlags" : null)}{(Fragments.Any(fragment => fragment.Cacheable) ? @",
				MatchCache = new Dictionary<ValueTuple<string, int>, FragmentMatchData>()" : null)}{(LogMatches ? $@",
				MatchLogBuilder = new StringBuilder()" : null)}
            }};
            
			{(IndexingMode == IndexingMode.Eager ? "PreMatchPatterns(ref state);" : null)}

			bool success = false;
            switch (fragmentMatcher) 
            {{
                {string.Join("\n", Fragments.Where(matcher => !matcher.FallThrough && !matcher.IsNoise).Select(matcher => $@"
                case ""{HttpUtility.JavaScriptStringEncode(matcher.Name)}"":
                        success = {matcher.Generate(generator)};
                    break;
                "))}
            }}

			IMatchData resultMatchData = matchData.Parts.FirstOrDefault();
			int? failureIndex = success ? null : state.FailureIndex;

			if (success && matchFullText && state.CurrentIndex != state.Code.Length)
			{{
				success = false;
				failureIndex = state.CurrentIndex;
			}}

			return new MatcherResult(resultMatchData, success, state.CurrentIndex, failureIndex, state.MatchLogBuilder?.ToString());
        }}

        public override MatcherResult Match(string code, bool matchFullText = true)
        {{
            FragmentMatchData matchData = new FragmentMatchData
            {{
                StartIndex = 0
            }};
            
			{(IndexingMode == IndexingMode.Lazy ? $"Span<int> checkFlags = stackalloc int[{Patterns.Count + 1}];" : null)}

            State state = new State()
            {{
                Code = code{(IndexingMode != IndexingMode.None ? @",
				DistinctStringMatches = new List<StringMatchData>(2000)" : null)}{(IndexingMode == IndexingMode.Lazy ? @",
				CheckFlags = checkFlags" : null)}{(Fragments.Any(fragment => fragment.Cacheable) ? @",
				MatchCache = new Dictionary<ValueTuple<string, int>, FragmentMatchData>()" : null)}{(LogMatches ? $@",
				MatchLogBuilder = new StringBuilder()" : null)}
            }};
            
			{(IndexingMode == IndexingMode.Eager ? "PreMatchPatterns(ref state);" : null)}

            bool success = {StartingFragment.Generate(generator)};

			IMatchData resultMatchData = matchData?.Parts.FirstOrDefault();
			int? failureIndex = success ? null : state.FailureIndex;

			if (success && matchFullText && state.CurrentIndex != state.Code.Length)
			{{
				success = false;
				failureIndex = Math.Max(state.FailureIndex ?? 0, state.CurrentIndex);
			}}

			return new MatcherResult(resultMatchData, success, state.CurrentIndex, failureIndex, state.MatchLogBuilder?.ToString());
        }}

		{(IndexingMode == IndexingMode.Eager ? $@"private bool PreMatchPatterns(ref State state)
		{{
			int codeLength = state.Code.Length;
			bool success = true;
			bool previousNoise = false;
			StringMatchData matchData = null;
			int currentIndex = 0;
			while ((currentIndex = state.CurrentIndex) < codeLength)
			{{
				success = {string.Join(" ||\n", Patterns.Select(pattern => $@"{string.Format(GenerateMatchPattern(generator, pattern), "matchData", "true", "false")}"))};
				if (!success)
				{{
					break;
				}}
				else {{
					{(generator.LanguageMatcher.LogMatches ? $@"state.MatchLogBuilder.AppendLine($""{{currentIndex}}. Prematched {{matchData.Name}}: {{matchData.Text}}"");" : null)}
					if (matchData.IsNoise)
					{{
						previousNoise = true;
					}}
					else if (previousNoise)
					{{
						if (state.DistinctIndex > 1)
						{{
							StringMatchData previousMatchData = state.DistinctStringMatches[state.DistinctIndex - 2];
							if (previousMatchData.Name == matchData.Name && previousMatchData.Mergable)
							{{
								previousMatchData.Text += matchData.Text;
								previousMatchData.Length = state.CurrentIndex - previousMatchData.StartIndex;
								state.DistinctIndex--;
								state.MaxDistinctIndex--;
								state.DistinctStringMatches.RemoveAt(state.DistinctIndex);
							}}
						}}
						previousNoise = false;
					}}
				}}
			}}
			state.CurrentIndex = 0;
			{(IndexingMode != IndexingMode.None ? "state.DistinctIndex = 0;" : null)}
			return success;
		}}" : null)}"        );
        }
 private string GetGeneratedClass()
 {
     return(MatcherEngineGenerator.GenerateEngine(_languageMatcher));
 }