static IList <IList <string> > _GetDysOr(XbnfDocument d, ICollection <string> syms, IDictionary <XbnfExpression, string> tmap, IDictionary <string, XbnfAttributeList> attrs, IList <KeyValuePair <string, IList <string> > > rules, XbnfProduction p, XbnfOrExpression oe)
        {
            var l = new List <IList <string> >();

            if (null == oe.Left)
            {
                l.Add(new List <string>());
            }
            else
            {
                foreach (var ll in _GetDysjunctions(d, syms, tmap, attrs, rules, p, oe.Left))
                {
                    if (!l.Contains(ll, OrderedCollectionEqualityComparer <string> .Default))
                    {
                        l.Add(ll);
                    }
                }
            }
            if (null == oe.Right)
            {
                var ll = new List <string>();
                if (!l.Contains(ll, OrderedCollectionEqualityComparer <string> .Default))
                {
                    l.Add(ll);
                }
            }
            else
            {
                foreach (var ll in _GetDysjunctions(d, syms, tmap, attrs, rules, p, oe.Right))
                {
                    if (!l.Contains(ll, OrderedCollectionEqualityComparer <string> .Default))
                    {
                        l.Add(ll);
                    }
                }
            }
            return(l);
        }
        static IList <IList <string> > _GetDysConcat(XbnfDocument d, ICollection <string> syms, IDictionary <XbnfExpression, string> tmap, IDictionary <string, XbnfAttributeList> attrs, IList <KeyValuePair <string, IList <string> > > rules, XbnfProduction p, XbnfConcatExpression ce)
        {
            var l = new List <IList <string> >();

            if (null == ce.Right)
            {
                if (null == ce.Left)
                {
                    return(l);
                }
                foreach (var ll in _GetDysjunctions(d, syms, tmap, attrs, rules, p, ce.Left))
                {
                    l.Add(new List <string>(ll));
                }
                return(l);
            }
            else if (null == ce.Left)
            {
                foreach (var ll in _GetDysjunctions(d, syms, tmap, attrs, rules, p, ce.Right))
                {
                    l.Add(new List <string>(ll));
                }
                return(l);
            }
            foreach (var ll in _GetDysjunctions(d, syms, tmap, attrs, rules, p, ce.Left))
            {
                foreach (var ll2 in _GetDysjunctions(d, syms, tmap, attrs, rules, p, ce.Right))
                {
                    var ll3 = new List <string>();
                    ll3.AddRange(ll);
                    ll3.AddRange(ll2);
                    if (!l.Contains(ll3, OrderedCollectionEqualityComparer <string> .Default))
                    {
                        l.Add(ll3);
                    }
                }
            }
            return(l);
        }
        static IList <IList <string> > _GetDysRepeat(XbnfDocument d, ICollection <string> syms, IDictionary <XbnfExpression, string> tmap, IDictionary <string, XbnfAttributeList> attrs, IList <KeyValuePair <string, IList <string> > > rules, XbnfProduction p, XbnfRepeatExpression re)
        {
            string sid = null;
            var    sr  = re.Expression as XbnfRefExpression;

            if (null != d && null != sr)
            {
                sid = string.Concat(sr.Symbol, "List");
            }
            if (string.IsNullOrEmpty(sid))
            {
                var cc = re.Expression as XbnfConcatExpression;
                if (null != cc)
                {
                    sr = cc.Right as XbnfRefExpression;
                    if (null != sr)
                    {
                        sid = string.Concat(sr.Symbol, "ListTail");
                    }
                }
            }
            if (string.IsNullOrEmpty(sid))
            {
                sid = string.Concat(p.Name, "List");
            }
            var listId = sid;
            var i      = 2;
            var ss     = listId;

            while (syms.Contains(ss))
            {
                ss = string.Concat(listId, i.ToString());
                ++i;
            }
            syms.Add(ss);
            listId = ss;
            var attr     = new XbnfAttribute("collapsed", true);
            var attr2    = new XbnfAttribute("nowarn", true);
            var attr3    = new XbnfAttribute("factored", true);
            var attrlist = new XbnfAttributeList();

            attrlist.Add(attr);
            attrlist.Add(attr2);
            attrlist.Add(attr3);
            attrs.Add(listId, attrlist);
            var expr =
                new XbnfOrExpression(
                    new XbnfConcatExpression(
                        new XbnfRefExpression(listId), re.Expression), re.Expression);;

            foreach (var nt in _GetDysjunctions(d, syms, tmap, attrs, rules, p, expr))
            {
                var l = new List <string>();
                var r = new KeyValuePair <string, IList <string> >(listId, l);
                foreach (var s in nt)
                {
                    if (1 < r.Value.Count && null == s)
                    {
                        continue;
                    }
                    r.Value.Add(s);
                }
                rules.Add(r);
            }
            if (!re.IsOptional)
            {
                return(new List <IList <string> >(new IList <string>[] { new List <string>(new string[] { listId }) }));
            }
            else
            {
                var res = new List <IList <string> >();
                res.Add(new List <string>(new string[] { listId }));
                res.Add(new List <string>());
                return(res);
            }
        }
        static IList <IList <string> > _GetDysOptional(XbnfDocument d, ICollection <string> syms, IDictionary <XbnfExpression, string> tmap, IDictionary <string, XbnfAttributeList> attrs, IList <KeyValuePair <string, IList <string> > > rules, XbnfProduction p, XbnfOptionalExpression ope)
        {
            var l = new List <IList <string> >();

            if (null != ope.Expression)
            {
                l.AddRange(_GetDysjunctions(d, syms, tmap, attrs, rules, p, ope.Expression));
                var ll = new List <string>();
                if (!l.Contains(ll, OrderedCollectionEqualityComparer <string> .Default))
                {
                    l.Add(ll);
                }
            }
            return(l);
        }
        static IList <IList <string> > _GetDysjunctions(
            XbnfDocument d,
            ICollection <string> syms,
            IDictionary <XbnfExpression, string> tmap,
            IDictionary <string, XbnfAttributeList> attrs,
            IList <KeyValuePair <string, IList <string> > > rules,
            XbnfProduction p,
            XbnfExpression e
            )
        {
            var le = e as XbnfLiteralExpression;

            if (null != le)
            {
                var res = new List <IList <string> >();
                var l   = new List <string>();
                l.Add(tmap[le]);
                res.Add(l);
                return(res);
            }
            var rxe = e as XbnfRegexExpression;

            if (null != rxe)
            {
                var res = new List <IList <string> >();
                var l   = new List <string>();
                l.Add(tmap[rxe]);
                res.Add(l);
                return(res);
            }
            var rfe = e as XbnfRefExpression;

            if (null != rfe)
            {
                var res = new List <IList <string> >();
                var l   = new List <string>();
                l.Add(rfe.Symbol);
                res.Add(l);
                return(res);
            }
            var ce = e as XbnfConcatExpression;

            if (null != ce)
            {
                return(_GetDysConcat(d, syms, tmap, attrs, rules, p, ce));
            }

            var oe = e as XbnfOrExpression;

            if (null != oe)
            {
                return(_GetDysOr(d, syms, tmap, attrs, rules, p, oe));
            }
            var ope = e as XbnfOptionalExpression;

            if (null != ope)
            {
                return(_GetDysOptional(d, syms, tmap, attrs, rules, p, ope));
            }
            var re = e as XbnfRepeatExpression;

            if (null != re)
            {
                return(_GetDysRepeat(d, syms, tmap, attrs, rules, p, re));
            }
            throw new NotSupportedException("The specified expression type is not supported.");
        }
Beispiel #6
0
        static void _GenerateAction(XbnfGenerationInfo info, IList <string> syms, CodeTypeDeclaration parser, XbnfProduction prod, bool fast, out bool hasChangeType, out bool hasEvalAny)
        {
            var isStart  = ReferenceEquals(prod, info.Xbnf.StartProduction);
            var isShared = false;

            hasChangeType = false;
            hasEvalAny    = false;
            var hasReturn = false;
            var ai        = prod.Attributes.IndexOf("shared");

            if (-1 < ai)
            {
                var o = prod.Attributes[ai].Value;
                if (o is bool && (bool)o)
                {
                    isShared = true;
                }
            }
            var type = new CodeTypeReference(typeof(object));

            ai = prod.Attributes.IndexOf("type");
            if (-1 < ai)
            {
                var s = prod.Attributes[ai].Value as string;
                if (!string.IsNullOrEmpty(s))
                {
                    //type = new CodeTypeReference(CodeDomResolver.TranslateIntrinsicType(s));
                    type = SlangParser.ParseType(s);
                }
            }
            MemberAttributes pattrs = MemberAttributes.Public | MemberAttributes.Static;
            MemberAttributes attrs  = MemberAttributes.FamilyAndAssembly | MemberAttributes.Static;
            var rs = new StringBuilder();

            foreach (var r in info.Cfg.FillNonTerminalRules(prod.Name))
            {
                rs.AppendLine(r.ToString());
            }

            if (isStart)
            {
                var ms = C.Method(type, "Evaluate", pattrs, C.Param(C.Type("ParseNode"), "node"));
                ms.Comments.AddRange(C.ToComments(string.Format("<summary>\r\nEvaluates a derivation of the form:\r\n{0}\r\n</summary>\r\n<remarks>\r\nThe production rules are:\r\n{1}\r\n</remarks>\r\n<param name=\"node\">The <see cref=\"ParseNode\"/> to evaluate</param>\r\n<returns>The result of the evaluation</returns>", prod.ToString("p").TrimEnd(), rs.ToString().TrimEnd()), true));
                ms.Statements.Add(C.Return(C.Invoke(C.TypeRef(parser.Name), string.Concat("Evaluate", prod.Name), C.ArgRef("node"), C.Null)));
                parser.Members.Add(ms);
                ms = C.Method(type, "Evaluate", pattrs, C.Param(C.Type("ParseNode"), "node"), C.Param(C.Type(typeof(object)), "state"));
                ms.Comments.AddRange(C.ToComments(string.Format("<summary>\r\nEvaluates a derivation of the form:\r\n{0}\r\n</summary>\r\n<remarks>\r\nThe production rules are:\r\n{1}\r\n</remarks>\r\n<param name=\"node\">The <see cref=\"ParseNode\"/> to evaluate</param>\r\n<param name=\"state\">A user supplied state object. What it should be depends on the production's associated code block</param>\r\n<returns>The result of the evaluation</returns>", prod.ToString("p").TrimEnd(), rs.ToString().TrimEnd()), true));
                ms.Statements.Add(C.Return(C.Invoke(C.TypeRef(parser.Name), string.Concat("Evaluate", prod.Name), C.ArgRef("node"), C.ArgRef("state"))));
                parser.Members.Add(ms);
            }
            var m = C.Method(type, string.Concat("Evaluate", prod.Name), (!isStart && isShared)?pattrs:attrs, C.Param("ParseNode", "node"), C.Param(typeof(object), "state"));

            m.Comments.AddRange(C.ToComments(string.Format("<summary>\r\nEvaluates a derivation of the form:\r\n{0}\r\n</summary>\r\n<remarks>\r\nThe production rules are:\r\n{1}\r\n</remarks>\r\n<param name=\"node\">The <see cref=\"ParseNode\"/> to evaluate</param>\r\n<param name=\"state\">A user supplied state object. What it should be depends on the production's associated code block</param>\r\n<returns>The result of the evaluation</returns>", prod.ToString("p").TrimEnd(), rs.ToString().TrimEnd()), true));
            var  stmts = SlangParser.ParseStatements(prod.Action.Value, prod.Action.Line, prod.Action.Column, prod.Action.Position);
            bool hasCT, hasE, hasR;

            _TranslateMacros(info, parser, stmts, type, out hasCT, out hasE, out hasR);
            if (hasCT)
            {
                hasChangeType = true;
            }
            if (hasE)
            {
                hasEvalAny = true;
            }
            if (hasR)
            {
                hasReturn = true;
            }
            if (!hasReturn)
            {
                if (!CD.CodeDomResolver.IsNullOrVoidType(type))
                {
                    stmts.Add(C.Return(C.Default(type)));
                }
                else
                {
                    stmts.Add(C.Return(C.Null));
                }
            }

            m.Statements.AddRange(stmts);
            parser.Members.Add(m);
        }
        internal static XbnfDocument Parse(LexContext pc)
        {
            var result = new XbnfDocument();

            if (!string.IsNullOrEmpty(pc.FileOrUrl))
            {
                result.SetFilename(pc.FileOrUrl);
            }
            while (-1 != pc.Current && '}' != pc.Current)
            {
                pc.TrySkipCCommentsAndWhiteSpace();
                while ('@' == pc.Current)                 // directives
                {
                    pc.Advance();
                    var l   = pc.Line;
                    var c   = pc.Column;
                    var p   = pc.Position;
                    var str = XbnfNode.ParseIdentifier(pc);
                    if (0 == string.Compare("include", str, StringComparison.InvariantCulture))
                    {
                        result.Includes.Add(_ParseIncludePart(result, pc));
                    }
                    else if (0 == string.Compare("options", str, StringComparison.InvariantCulture))
                    {
                        if (0 < result.Options.Count)
                        {
                            throw new ExpectingException("Duplicate directive \"options\" specified", l, c, p, pc.FileOrUrl);
                        }
                        while (-1 != pc.Current && ';' != pc.Current)
                        {
                            l = pc.Line;
                            c = pc.Column;
                            p = pc.Position;
                            var opt = XbnfOption.Parse(pc);
                            opt.SetLocation(l, c, p);
                            result.Options.Add(opt);
                            pc.TrySkipCCommentsAndWhiteSpace();
                            pc.Expecting(';', ',');
                            if (',' == pc.Current)
                            {
                                pc.Advance();
                            }
                        }
                        pc.Expecting(';');
                        pc.Advance();
                        if (0 == result.Options.Count)
                        {
                            throw new ExpectingException("Expection options but \"options\" directive was empty", l, c, p, pc.FileOrUrl);
                        }
                    }
                    else
                    {
                        throw new ExpectingException("Expecting \"include\" or \"options\"", l, c, p, pc.FileOrUrl, "include", "options");
                    }


                    pc.TrySkipCCommentsAndWhiteSpace();
                }
                if (pc.Current == '{')
                {
                    pc.Advance();
                    var l = pc.Line;
                    var c = pc.Column;
                    var p = pc.Position;
                    var s = ReadCode(pc);
                    pc.Expecting('}');
                    pc.Advance();
                    var code = new XbnfCode(s);
                    code.SetLocation(l, c, p);
                    result.Code.Add(code);
                }
                else if (-1 != pc.Current)
                {
                    if ('@' == pc.Current)
                    {
                        throw new ExpectingException("Expecting productions. Includes and options must be specified before any productions", pc.Line, pc.Column, pc.Position, pc.FileOrUrl, "Production");
                    }
                    result.Productions.Add(XbnfProduction.Parse(pc));
                }
                else                 // end of input
                {
                    return(result);
                }
                // have to do this so trailing whitespace
                // doesn't get read as a production
                pc.TryReadCCommentsAndWhitespace();
            }
            return(result);
        }