public ParseNode_Base Recover(SyntaxTreeBuilder pSyntaxTreeBuilder, out int numMissing)
    {
        numMissing = 0;

        var current = this;

        while (current.parent != null)
        {
            var next = current.parent.NextAfterChild(current, pSyntaxTreeBuilder);
            if (next == null)
            {
                break;
            }

            var nextId = next as ParseNode_Id;
            if (nextId != null && nextId.Name == "attribute")
            {
                return(nextId);
            }

            var nextMatchespSyntaxTreeBuilder = next.Matches(pSyntaxTreeBuilder);
            while (next != null && !nextMatchespSyntaxTreeBuilder && next.FirstSet.ContainsEmpty())
            {
                next = next.parent.NextAfterChild(next, pSyntaxTreeBuilder);
                nextMatchespSyntaxTreeBuilder = next != null && next.Matches(pSyntaxTreeBuilder);
            }

            if (nextMatchespSyntaxTreeBuilder && pSyntaxTreeBuilder.TokenScanner.Current.text == ";" && next is ParseNode_Many_Opt)
            {
                return(null);
            }

            ++numMissing;
            if (nextMatchespSyntaxTreeBuilder)
            {
                if (pSyntaxTreeBuilder.TokenScanner.Current.text == "{" ||
                    pSyntaxTreeBuilder.TokenScanner.Current.text == "}" ||
                    pSyntaxTreeBuilder.PreCheck(next, 3))//next.Scan(clone))
                {
                    return(next);
                }
            }

            if (numMissing <= 1 && pSyntaxTreeBuilder.TokenScanner.Current.text != "{" && pSyntaxTreeBuilder.TokenScanner.Current.text != "}")
            {
                //TODO using
                var lapSyntaxTreeBuilder = pSyntaxTreeBuilder.Clone();
                if (lapSyntaxTreeBuilder.TokenScanner.MoveNext() && next.Matches(lapSyntaxTreeBuilder) && lapSyntaxTreeBuilder.PreCheck(next, 3))
                {
                    return(null);
                }
            }
            current = next;
        }
        return(null);
    }
 public virtual bool CheckPredicate(SyntaxTreeBuilder pSyntaxTreeBuilder)
 {
     //if (debug)
     //{
     //    var s = pSyntaxTreeBuilder.Clone();
     //    Debug.Log(s.Current.tokenKind + " " + s.Current.text);
     //    s.MoveNext();
     //    Debug.Log(s.Current.tokenKind + " " + s.Current.text);
     //}
     if (predicate != null)
     {
         return(predicate(pSyntaxTreeBuilder));
     }
     else if (nodePredicate != null)
     {
         return(pSyntaxTreeBuilder.PreCheck(nodePredicate));//, new GoalAdapter());
     }
     return(false);
 }