public string Run(Grammar grammar)
        {
            var astValid = grammar.IsValid;

            if (astValid != IsValid)
            {
                IsValid = astValid;
                ValidityChanged?.Invoke();
            }

            var rtf = new RtfBuilder();

            grammar.Visit(rtf);

            return(rtf.ToString());
        }
        public void MarkValidity(Control source, bool valid)
        {
            lock (_lock) {
                // Check validity state and add/update this validity source
                bool validBefore = false;
                _validitySources.TryGetValue(source, out validBefore);
                int countBefore      = _validitySources.Count;
                int numInvalidBefore = _validitySources.Values.Count(v => !v);
                _validitySources.AddOrUpdate(source, valid, (ctrl, oldValid) => valid);

                // Raise an event if:
                //      This was the first validity source added
                //      This is now the only invalid source
                //      This was the last invalid source and it just became valid
                if ((countBefore == 0) ||
                    (numInvalidBefore == 0 && !valid) ||
                    (numInvalidBefore == 1 && !validBefore && valid))
                {
                    ValidityChanged?.Invoke(this, EventArgs.Empty);
                }
            }
        }