/*public void Generate(Coderack coderack, IContinuation succ, IFailure fail, double weight)
         * {
         *  PatternTemplateSource checker = new PatternTemplateSource(this, coderack, weight, succ);
         *
         *  ContinuationAppender appender = new ContinuationAppender(pattern, checker);
         *
         *  Evaluator eval = new Evaluator(maxSalience * weight, ArgumentMode.ManyArguments, appender.AsIndex(0), appender.AsIndex(1), true);
         *
         *  eval.Continue(pattern, fail);
         * }*/

        #region IContinuation Members

        public bool Continue(object value, IFailure fail)
        {
            Context context = (Context)value;

            // Did we successfully match everything?  If so, evaluate the template
            if (Matcher.IsRemainderOptional(context.Contents))
            {
                Evaluator eval  = new Evaluator(salience, ArgumentMode.ManyArguments, succ, new NopCallable(), true);
                Context   child = new Context(context, template.Contents);
                child.Map["$production"] = true;
                return(eval.Continue(child, fail));
            }
            else
            {
                // we didn't match everything
                fail.Fail("Context is not empty", succ);
                return(true);
            }
        }
        public override bool Evaluate()
        {
            // Drill down to a single POSPhrase
            List <IParsedPhrase> unmatched = new List <IParsedPhrase>(matcher.Unmatched);
            IParsedPhrase        input     = matcher.Input;

            while (!input.IsLeaf)
            {
                GroupPhrase groupPhrase = new GroupPhrase(input);
                unmatched.InsertRange(0, groupPhrase.GetRange(1));
                input = groupPhrase.GetBranch(0);
            }

            List <IContent> elements = matcher.Context.LookupDefaulted <List <IContent> >(name, new List <IContent>());

            elements.Add(new Word(input.Text));

            Context eaten;

            if (needRemoval)
            {
                eaten = new Context(matcher.Context, matcher.Context.Contents.GetRange(1, matcher.Context.Contents.Count - 1));
            }
            else
            {
                eaten = new Context(matcher.Context, matcher.Context.Contents);
            }
            eaten.Map.Add(name, elements);

            // Continue matcher
            if (unmatched.Count == 0)
            {
                if (eaten.Contents.Count == 0 || Matcher.IsRemainderOptional(eaten.Contents))
                {
                    matcher.Success.Continue(eaten, matcher.Failure);
                }
                else
                {
                    matcher.Failure.Fail("Ran out of input after *.", matcher.Success);
                }
            }
            else
            {
                // This matcher is for StarEater to eat another
                Matcher clone = (Matcher)matcher.Clone();
                clone.Context   = eaten;
                clone.Input     = unmatched[0];
                clone.Unmatched = unmatched.GetRange(1, unmatched.Count - 1);

                StarEater eater = new StarEater(coderack, salience, clone, name, false);

                if (eaten.Contents.Count == 0)
                {
                    // Just add ourselves again
                    coderack.AddCodelet(eater, "Evaluate empty");
                }
                else
                {
                    Matcher.MatchAgainst(salience, eaten, clone.Input, clone.Unmatched, matcher.Success, eater);
                }
            }

            return(true);
        }