static EbnfExpression _ReadExpressions(EbnfParser parser)
        {
            EbnfExpression result = null;

            throw new NotImplementedException();
            return(result);
        }
        void _VisitFetchTerminals(EbnfExpression expr, HashSet <EbnfExpression> terms)
        {
            var l = expr as EbnfLiteralExpression;

            if (null != l)
            {
                terms.Add(l);
                return;
            }
            var r = expr as EbnfRegexExpression;

            if (null != r)
            {
                terms.Add(r);
                return;
            }
            var u = expr as EbnfUnaryExpression;

            if (null != u)
            {
                _VisitFetchTerminals(u.Expression, terms);
                return;
            }
            var b = expr as EbnfBinaryExpression;

            if (null != b)
            {
                _VisitFetchTerminals(b.Left, terms);
                _VisitFetchTerminals(b.Right, terms);
                return;
            }
        }
 public string GetIdForExpression(EbnfExpression expression)
 {
     foreach (var prod in Productions)
     {
         if (Equals(prod.Value.Expression, expression))
         {
             return(prod.Key);
         }
     }
     return(null);
 }
 public EbnfOrExpression(EbnfExpression left, params EbnfExpression[] right)
 {
     if (null == right)
     {
         right = new EbnfExpression[] { null }
     }
     ;
     Left = left;
     for (var i = 0; i < right.Length; ++i)
     {
         if (Right == null)
         {
             Right = right[i];
         }
         else
         {
             Right = new EbnfOrExpression(Right, right[i]);
         }
     }
 }
 public EbnfProduction(EbnfExpression expression)
 {
     Expression = expression;
 }
 public EbnfRepeatExpression(EbnfExpression expression)
 {
     Expression = expression;
 }
 public EbnfOptionalExpression(EbnfExpression expression)
 {
     Expression = expression;
 }
        static EbnfExpression _ParseExpression(EbnfDocument doc, ParseContext pc)
        {
            EbnfExpression current = null;
            EbnfExpression e;
            long           position;
            int            line;
            int            column;

            pc.TrySkipCCommentsAndWhiteSpace();
            position = pc.Position; line = pc.Line; column = pc.Column;
            while (-1 != pc.Current && ']' != pc.Current && ')' != pc.Current && '}' != pc.Current && ';' != pc.Current)
            {
                pc.TrySkipCCommentsAndWhiteSpace();
                position = pc.Position; line = pc.Line; column = pc.Column;
                switch (pc.Current)
                {
                case '|':
                    pc.Advance();
                    current = new EbnfOrExpression(current, _ParseExpression(doc, pc));
                    current.SetPositionInfo(line, column, position);
                    break;

                case '(':
                    pc.Advance();
                    e = _ParseExpression(doc, pc);
                    current.SetPositionInfo(line, column, position);
                    pc.Expecting(')');
                    pc.Advance();
                    e.SetPositionInfo(line, column, position);
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }

                    break;

                case '[':
                    pc.Advance();
                    e = new EbnfOptionalExpression(_ParseExpression(doc, pc));
                    e.SetPositionInfo(line, column, position);
                    pc.TrySkipCCommentsAndWhiteSpace();
                    pc.Expecting(']');
                    pc.Advance();
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }

                    break;

                case '{':
                    pc.Advance();
                    e = new EbnfRepeatExpression(_ParseExpression(doc, pc));
                    e.SetPositionInfo(line, column, position);
                    pc.TrySkipCCommentsAndWhiteSpace();
                    pc.Expecting('}');
                    pc.Advance();
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }

                    break;

                case '\"':
                    e = new EbnfLiteralExpression(pc.ParseJsonString());
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }
                    e.SetPositionInfo(line, column, position);
                    break;

                case '\'':
                    pc.Advance();
                    pc.ClearCapture();
                    pc.TryReadUntil('\'', '\\', false);
                    pc.Expecting('\'');
                    pc.Advance();
                    e = new EbnfRegexExpression(pc.Capture);
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }
                    e.SetPositionInfo(line, column, position);
                    break;

                case ';':
                case ']':
                case ')':
                case '}':
                    return(current);

                default:
                    e = new EbnfRefExpression(_ParseIdentifier(pc));
                    if (null == current)
                    {
                        current = e;
                    }
                    else
                    {
                        current = new EbnfConcatExpression(current, e);
                    }
                    e.SetPositionInfo(line, column, position);
                    break;
                }
            }
            pc.TrySkipCCommentsAndWhiteSpace();
            return(current);
        }
        void _ValidateExpression(EbnfExpression expr, IDictionary <string, int> refCounts, IList <EbnfMessage> messages)
        {
            var l = expr as EbnfLiteralExpression;

            if (null != l)
            {
                var i = GetIdForExpression(l);
                // don't count itself. only things just like itself
                if (null != i && !ReferenceEquals(Productions[i].Expression, l))
                {
                    refCounts[i] += 1;
                }
            }
            var rx = expr as EbnfRegexExpression;

            if (null != rx)
            {
                try
                {
                    FA.Parse(rx.Value);
                }
                catch (ExpectingException)
                {
                    messages.Add(
                        new EbnfMessage(
                            EbnfErrorLevel.Error, 12,
                            "Invalid regular expression",
                            expr.Line, expr.Column, expr.Position));
                }
                var i = GetIdForExpression(rx);
                if (null != i && !ReferenceEquals(Productions[i].Expression, l))
                {
                    refCounts[i] += 1;
                }
            }
            var r = expr as EbnfRefExpression;

            if (null != r)
            {
                int rc;
                if (null == r.Symbol)
                {
                    messages.Add(
                        new EbnfMessage(
                            EbnfErrorLevel.Error, 4,
                            "Null reference expression",
                            expr.Line, expr.Column, expr.Position));
                    return;
                }
                if (!refCounts.TryGetValue(r.Symbol, out rc))
                {
                    messages.Add(
                        new EbnfMessage(
                            EbnfErrorLevel.Error, 1,
                            string.Concat(
                                "Reference to undefined symbol \"",
                                r.Symbol,
                                "\""),
                            expr.Line, expr.Column, expr.Position));
                    return;
                }
                refCounts[r.Symbol] = rc + 1;
                return;
            }
            var b = expr as EbnfBinaryExpression;

            if (null != b)
            {
                if (null == b.Left && null == b.Right)
                {
                    messages.Add(
                        new EbnfMessage(
                            EbnfErrorLevel.Warning, 3,
                            "Nil expression",
                            expr.Line, expr.Column, expr.Position));
                    return;
                }
                _ValidateExpression(b.Left, refCounts, messages);
                _ValidateExpression(b.Right, refCounts, messages);
                return;
            }
            var u = expr as EbnfUnaryExpression;

            if (null != u)
            {
                if (null == u.Expression)
                {
                    messages.Add(
                        new EbnfMessage(
                            EbnfErrorLevel.Warning, 3,
                            "Nil expression",
                            expr.Line, expr.Column, expr.Position));
                    return;
                }
                _ValidateExpression(u.Expression, refCounts, messages);
            }
        }