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."); }
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); }