/// <summary>
        /// If a matcher in the sequence doesn't match, then it doesn't match
        /// </summary>
        /// <param name="context"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        public override MatchResult Matches(MatchContext context, TokenEntity startToken, PatternMatcher nextPatternMatcher)
        {
            var tokenEntity = startToken;
            // try to match each element in the sequence.
            int start = startToken?.Start ?? 0;
            int end   = 0;

            for (int iPattern = 0; iPattern < PatternMatchers.Count; iPattern++)
            {
                var matchResult    = new MatchResult(false, this, tokenEntity);
                var patternMatcher = PatternMatchers[iPattern];
                if (patternMatcher.ContainsWildcard())
                {
                    // look ahead to non wild card
                    nextPatternMatcher = PatternMatchers.Skip(iPattern).Where(pm => !pm.ContainsWildcard()).FirstOrDefault();

                    // run wildcard pattern matcher
                    matchResult = patternMatcher.Matches(context, tokenEntity, nextPatternMatcher);

                    // if the match was not the wildcard pattern, then advance to that.
                    if (matchResult.NextPatternMatch != null)
                    {
                        Debug.Assert(matchResult.NextPatternMatch.PatternMatcher == nextPatternMatcher);
                        matchResult = matchResult.NextPatternMatch;
                        iPattern    = PatternMatchers.IndexOf(matchResult.PatternMatcher);
                        Debug.Assert(iPattern >= 0);
                    }
                }
                else
                {
                    matchResult = patternMatcher.Matches(context, tokenEntity, nextPatternMatcher);
                }

                // if the element did not match, then sequence is bad, return failure
                if (matchResult.Matched == false)
                {
                    return(new MatchResult(false, this, tokenEntity));
                }

                tokenEntity = matchResult.NextToken;
                end         = Math.Max(matchResult.End, end);
            }

            return(new MatchResult(true, this, tokenEntity, start, end));
        }
Beispiel #2
0
 /// <summary>
 /// Match and add entity as appropriate.
 /// </summary>
 /// <param name="matchContext">match context.</param>
 /// <param name="tokenEntity">token entity</param>
 /// <returns>matchresult</returns>
 public abstract MatchResult Matches(MatchContext matchContext, TokenEntity tokenEntity, PatternMatcher nextPatternMatcher);
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="pattern">pattern to parse</param>
        /// <returns></returns>
        public PatternMatcher Parse(string pattern, bool defaultFuzzyMatch = false, Ordinality ordinality = Ordinality.One, int maxMatches = 16)
        {
            OrdinalityPatternMatcher ordinalityPatternMatcher = new OrdinalityPatternMatcher(ordinality, maxMatches);
            SequencePatternMatcher   sequence = new SequencePatternMatcher();
            StringBuilder            sb       = new StringBuilder();
            var fuzzyMatch = defaultFuzzyMatch;
            var chars      = pattern.GetEnumerator();

            while (chars.MoveNext())
            {
                char ch = chars.Current;
                bool repeatChar;
                do
                {
                    repeatChar = false;

                    switch (ch)
                    {
                    case '(':
                        Ordinality modifierOrdinality = Ordinality.One;
                        AddTextToSequence(sequence, sb, fuzzyMatch);

                        var subText = GetPatternGroup(chars).Trim();

                        bool inModifiers = true;
                        while (inModifiers && chars.MoveNext())
                        {
                            ch = chars.Current;
                            switch (ch)
                            {
                            case '~':
                                fuzzyMatch = !defaultFuzzyMatch;
                                break;

                            case '?':
                                modifierOrdinality = Ordinality.ZeroOrOne;
                                break;

                            case '+':
                                modifierOrdinality = Ordinality.OneOrMore;
                                break;

                            case '*':
                                modifierOrdinality = Ordinality.ZeroOrMore;
                                break;

                            default:
                                if (byte.TryParse(ch.ToString(), out byte num))
                                {
                                    maxMatches = num;
                                }
                                else
                                {
                                    var patternMatcher = Parse(subText, fuzzyMatch, modifierOrdinality, maxMatches);
                                    sequence.PatternMatchers.Add(patternMatcher);

                                    // break out of modifier loop
                                    inModifiers = false;
                                    repeatChar  = true;
                                }
                                break;
                            }
                        }
                        if (inModifiers)
                        {
                            // paren was end of string.
                            var patternMatcher = Parse(subText, fuzzyMatch, modifierOrdinality, maxMatches);
                            sequence.PatternMatchers.Add(patternMatcher);
                        }
                        maxMatches = 16;
                        fuzzyMatch = defaultFuzzyMatch;
                        break;

                    case '|':
                    {
                        AddTextToSequence(sequence, sb, fuzzyMatch);
                        if (sequence.PatternMatchers.Count == 1)
                        {
                            ordinalityPatternMatcher.PatternMatchers.Add(sequence.PatternMatchers.Single());
                        }
                        else
                        {
                            ordinalityPatternMatcher.PatternMatchers.Add(sequence);
                        }
                        sequence = new SequencePatternMatcher();
                    }
                    break;

                    default:
                        sb.Append(ch);
                        break;
                    }
                } while (repeatChar);
            }

            AddTextToSequence(sequence, sb, fuzzyMatch);

            if (sequence.PatternMatchers.Any())
            {
                if (sequence.PatternMatchers.Count == 1)
                {
                    ordinalityPatternMatcher.PatternMatchers.Add(sequence.PatternMatchers.Single());
                }
                else
                {
                    ordinalityPatternMatcher.PatternMatchers.Add(sequence);
                }
            }

            // if this is a oneOf, maxMatches with a single pattern matcher, just the inner patternmatcher.
            PatternMatcher result = ordinalityPatternMatcher;

            if (ordinalityPatternMatcher.PatternMatchers.Count == 1 && ordinalityPatternMatcher.Ordinality == Ordinality.One)
            {
                result = ordinalityPatternMatcher.PatternMatchers.Single();
            }

            // if it is a sequence with only one patternMatcher, just the inner patternmatcher
            if (result is SequencePatternMatcher spm && spm.PatternMatchers.Count == 1)
            {
                result = spm.PatternMatchers.Single();
            }

            return(result);
        }
Beispiel #4
0
        /// <summary>
        /// If a matcher in the sequence doesn't match, then it doesn't match
        /// </summary>
        /// <param name="context"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        public override MatchResult Matches(MatchContext context, TokenEntity startToken, PatternMatcher nextPatternMatcher)
        {
            var tokenEntity = startToken;
            int start       = startToken?.Start ?? 0;
            int end         = 0;
            int minMatches  = 1;
            int maxMatches  = this.MaxMatches;

            switch (Ordinality)
            {
            case Ordinality.One:
                maxMatches = 1;
                break;

            case Ordinality.OneOrMore:
                break;

            case Ordinality.ZeroOrMore:
                minMatches = 0;
                break;

            case Ordinality.ZeroOrOne:
                minMatches = 0;
                maxMatches = 1;
                break;
            }

            int         matched     = 0;
            MatchResult matchResult = null;
            bool        found;

            do
            {
                found = false;
                for (int iPattern = 0; iPattern < PatternMatchers.Count; iPattern++)
                {
                    var patternMatcher = PatternMatchers[iPattern];
                    var result         = patternMatcher.Matches(context, tokenEntity, nextPatternMatcher);

                    if (result.Matched)
                    {
                        found = true;
                        matched++;
                        matchResult = result;
                        end         = Math.Max(result.End, end);
                        tokenEntity = matchResult.NextToken;
                        if (matched == maxMatches)
                        {
                            // then we are done;
                            return(new MatchResult(true, this, tokenEntity, start, end)
                            {
                                NextPatternMatch = result.NextPatternMatch
                            });
                        }
                        break;
                    }
                    else
                    {
                        if (matchResult != null)
                        {
                            matchResult.NextPatternMatch = result.NextPatternMatch;
                        }
                    }
                }
            } while (found && tokenEntity != null);

            if (matched < minMatches)
            {
                // not matched.
                return(new MatchResult(false, this)
                {
                    NextPatternMatch = matchResult?.NextPatternMatch
                });
            }

            return(new MatchResult(true, this, tokenEntity, start, end)
            {
                NextPatternMatch = matchResult?.NextPatternMatch
            });
        }
Beispiel #5
0
        public override MatchResult Matches(MatchContext context, TokenEntity startToken, PatternMatcher nextPatternMatcher)
        {
            var tokenEntity = startToken;

            if (tokenEntity != null)
            {
                if (nextPatternMatcher != null)
                {
                    MatchResult nextPatternMatch = nextPatternMatcher?.Matches(context, tokenEntity, null);
                    if (nextPatternMatch.Matched && nextPatternMatch.NextToken != tokenEntity)
                    {
                        return(new MatchResult(false, this)
                        {
                            NextPatternMatch = nextPatternMatch
                        });
                    }
                }

                if (!context.IsTokenMatched(tokenEntity))
                {
                    // if last child is a wildcard and it's end matches the last token's end
                    // then we will merge the wildcards together.
                    var previousToken  = context.GetPrevTokenEntity(tokenEntity);
                    var wildcardEntity = context.CurrentEntity.Children.FirstOrDefault(wildcard => wildcard.Type == this.entityType && wildcard.End == previousToken.End);
                    if (wildcardEntity != null)
                    {
                        var newEntity = new LucyEntity()
                        {
                            Type       = entityType,
                            Start      = wildcardEntity.Start,
                            End        = tokenEntity.End,
                            Score      = ((float)tokenEntity.End - wildcardEntity.Start) / context.Text.Length / 2,
                            Text       = context.Text.Substring(wildcardEntity.Start, tokenEntity.End - wildcardEntity.Start),
                            Resolution = context.Text.Substring(wildcardEntity.Start, tokenEntity.End - wildcardEntity.Start),
                        };

                        // remove old entity
                        context.CurrentEntity.Children.Remove(wildcardEntity);

                        // add new merged wildcard entity "joe" "smith" => "joe smith"
                        context.AddToCurrentEntity(newEntity);
                    }
                    else
                    {
                        var newEntity = new LucyEntity()
                        {
                            Type       = entityType,
                            Start      = tokenEntity.Start,
                            End        = tokenEntity.End,
                            Score      = ((float)tokenEntity.End - tokenEntity.Start) / context.Text.Length / 2,
                            Text       = context.Text.Substring(tokenEntity.Start, tokenEntity.End - tokenEntity.Start),
                            Resolution = context.Text.Substring(tokenEntity.Start, tokenEntity.End - tokenEntity.Start)
                        };
                        context.AddToCurrentEntity(newEntity);
                    }

                    return(new MatchResult(true, this, context.GetNextTokenEntity(tokenEntity), tokenEntity.Start, tokenEntity.End));
                }
            }

            return(new MatchResult(false, this));
        }
Beispiel #6
0
        public override MatchResult Matches(MatchContext context, TokenEntity startToken, PatternMatcher nextPatterMatcher)
        {
            var tokenEntity = startToken;

            var matchResult = new MatchResult(false, this, tokenEntity);

            if (tokenEntity != null)
            {
                var entity = context.Entities.FirstOrDefault(le => le.Start == tokenEntity.Start && le.Type == EntityType);
                if (entity != null)
                {
                    // add the matched entity to the children of the currentEntity.
                    context.AddToCurrentEntity(entity);

                    matchResult.Matched   = true;
                    matchResult.End       = entity.End;
                    matchResult.NextToken = context.GetFirstTokenEntity(entity.End);
                }
            }
            return(matchResult);
        }