static CodeExpression _SerializeErrorSentinels(XbnfGenerationInfo info, List <string> syms) { var result = new List <int>(); foreach (var attrs in info.Cfg.AttributeSets) { var ai = attrs.Value.IndexOf("errorSentinel"); if (-1 < ai) { var o = attrs.Value[ai].Value; if (o is bool && (bool)o) { result.Add(syms.IndexOf(attrs.Key)); } } } return(C.Literal(result.ToArray())); }
public static List <string> GetSymbolTable(XbnfGenerationInfo info, out int termStart) { var result = new List <string>(); var seen = new HashSet <string>(); XbnfDocument xbnf = info.Xbnf; var cfg = info.Cfg; foreach (var s in cfg.FillNonTerminals()) { if (seen.Add(s)) { result.Add(s); } } termStart = result.Count; var ts = new List <string>(); foreach (var prod in xbnf.Productions) { if (prod.IsTerminal) { ts.Add(prod.Name); } } foreach (var s in ts) { //if (0 != string.Compare("#ERROR", s, StringComparison.InvariantCulture) && 0 != string.Compare("#EOS", s, StringComparison.InvariantCulture)) //{ if (seen.Add(s)) { result.Add(s); } //} } result.Add("#EOS"); result.Add("#ERROR"); return(result); }
/*static CodeExpression _SerializeNodeFlags(XbnfGenerationInfo info, List<string> syms) * { * var result = new int[syms.Count]; * foreach (var attrs in info.Cfg.AttributeSets) * { * var ai = attrs.Value.IndexOf("collapsed"); * if (-1 < ai) * { * var o = attrs.Value[ai].Value; * if (o is bool && (bool)o) * { * result[syms.IndexOf(attrs.Key)]=1; * } * } * } * return C.Literal(result); * }*/ static CodeExpression _SerializeParseAttributes(XbnfGenerationInfo info, List <string> syms) { var arr = new ParseAttribute[syms.Count][]; foreach (var aset in info.Cfg.AttributeSets) { var id = syms.IndexOf(aset.Key); int ic = aset.Value.Count; arr[id] = new ParseAttribute[ic]; for (var i = 0; i < ic; ++i) { var a = aset.Value[i]; arr[id][i] = new ParseAttribute(a.Name, a.Value); } } for (var i = 0; i < arr.Length; i++) { if (null == arr[i]) { arr[i] = new ParseAttribute[0]; } } return(_SerializeParseAttributes(arr)); }
static IList <IMessage> _TryToGenInfo(XbnfDocument document, CfgDocument cfg, out XbnfGenerationInfo genInfo) { genInfo = default(XbnfGenerationInfo); var hasErrors = false; var result = new List <IMessage>(); var syms = new HashSet <string>(); // gather the attributes and production names for (int ic = document.Productions.Count, i = 0; i < ic; ++i) { var p = document.Productions[i]; if (!syms.Add(p.Name)) { result.Add(new XbnfMessage(ErrorLevel.Error, -1, string.Format("Duplicate production {0} defined.", p.Name), p.Line, p.Column, p.Position, document.FileOrUrl)); hasErrors = true; } if (0 < p.Attributes.Count) { CfgAttributeList attrs; if (!cfg.AttributeSets.TryGetValue(p.Name, out attrs)) { attrs = new CfgAttributeList(); cfg.AttributeSets.Add(p.Name, attrs); } for (int jc = p.Attributes.Count, j = 0; j < jc; ++j) { var attr = p.Attributes[j]; attrs.Add(new CfgAttribute(attr.Name, attr.Value)); } } } // use a list dictionary to keep these in order var tmap = new ListDictionary <XbnfExpression, string>(); var attrSets = new Dictionary <string, XbnfAttributeList>(); var rules = new List <KeyValuePair <string, IList <string> > >(); // below are scratch var working = new HashSet <XbnfExpression>(); var done = new HashSet <XbnfExpression>(); // now get the terminals and their ids, declaring if necessary for (int ic = document.Productions.Count, i = 0; i < ic; ++i) { var p = document.Productions[i]; if (p.IsTerminal) { string name; if (!tmap.TryGetValue(p.Expression, out name)) { tmap.Add(p.Expression, p.Name); } else { if (name != p.Name) { result.Add(new CfgMessage(ErrorLevel.Error, -1, string.Format("{0} attempts to redefine terminal {1}", name, p.Name), p.Line, p.Column, p.Position, document.FileOrUrl)); hasErrors = true; } } done.Add(p.Expression); } else { _VisitFetchTerminals(p.Expression, working); } } if (hasErrors) { return(result); } foreach (var term in working) { if (!done.Contains(term)) { var newId = _GetImplicitTermId(syms); var found = false; var prod = document.GetProductionForExpression(term); if (null != prod) { found = true; // recycle this symbol newId = prod.Name; } if (!found) { document.Productions.Add(new XbnfProduction(newId, term)); } tmap.Add(term, newId); } } // tmap now contains ALL of our terminal definitions from all of our imports // now we can use tmap and syms to help solve the rest of our productions var ntd = new Dictionary <string, IList <IList <string> > >(); for (int ic = document.Productions.Count, i = 0; i < ic; ++i) { var p = document.Productions[i]; if (!p.IsTerminal) { var dys = _GetDysjunctions(document, syms, tmap, attrSets, rules, p, p.Expression); IList <IList <string> > odys; if (ntd.TryGetValue(p.Name, out odys)) { result.Add(new XbnfMessage(ErrorLevel.Error, -1, string.Format("The {0} production was specified more than once", p.Name), p.Line, p.Column, p.Position, document.FileOrUrl)); hasErrors = true; } ntd.Add(p.Name, dys); if (hasErrors) { return(result); } } } // now that we've done that, build the rest of our attributes foreach (var sattrs in attrSets) { CfgAttributeList attrs; if (!cfg.AttributeSets.TryGetValue(sattrs.Key, out attrs)) { attrs = new CfgAttributeList(); cfg.AttributeSets.Add(sattrs.Key, attrs); } for (int jc = sattrs.Value.Count, j = 0; j < jc; ++j) { var attr = sattrs.Value[j]; attrs.Add(new CfgAttribute(attr.Name, attr.Value)); } } // now write our main rules foreach (var nt in ntd) { foreach (var l in nt.Value) { cfg.Rules.Add(new CfgRule(nt.Key, l)); } } // build our secondary rules foreach (var rule in rules) { cfg.Rules.Add(new CfgRule(rule.Key, rule.Value)); } if (hasErrors) { return(result); } genInfo.Xbnf = document; genInfo.TerminalMap = tmap; genInfo.Cfg = cfg; cfg.RebuildCache(); return(result); }
public static IList <IMessage> TryCreateGenerationInfo(XbnfDocument document, out XbnfGenerationInfo genInfo) { var includes = new XbnfImportList(); _GatherIncludes(document, includes); var incs = new List <XbnfDocument>(); incs.Add(document); foreach (var inc in includes) { incs.Add(inc.Document); } var doc = XbnfDocument.Merge(incs); var cfg = new CfgDocument(); return(_TryToGenInfo(doc, cfg, out genInfo)); }
public static string ToRolexSpec(XbnfGenerationInfo genInfo) { var termStart = 0; var stbl = GetSymbolTable(genInfo, out termStart); var stbli = new List <KeyValuePair <string, int> >(); var id = 0; // assign temp ids foreach (var se in stbl) { if (id >= termStart) { stbli.Add(new KeyValuePair <string, int>(se, id)); } ++id; } stbli.Sort(new _TermPriorityComparer(genInfo.Cfg)); var sb = new StringBuilder(); for (int ic = stbli.Count, i = 0; i < ic; ++i) { var sym = stbli[i].Key; if ("#EOS" == sym || "#ERROR" == sym) { continue; } XbnfExpression e = null; foreach (var k in genInfo.TerminalMap) { if (k.Value == sym) { e = k.Key; break; } } //var te = genInfo.TerminalMap[i]; //var sym = te.Value; //var id = stbli.IndexOf(new KeyValuePair<string, XbnfDocument>(sym, d)); id = stbli[i].Value; if (-1 < id) // some terminals might never be used. { // implicit terminals do not have productions and therefore attributes var pi = genInfo.Xbnf.Productions.IndexOf(sym); if (-1 < pi) { // explicit var prod = genInfo.Xbnf.Productions[pi]; sb.Append(sym); sb.Append("<id="); sb.Append(id); foreach (var attr in prod.Attributes) { sb.Append(", "); sb.Append(attr.ToString()); } sb.Append(">"); } else { // implicit sb.Append(sym); sb.Append(string.Concat("<id=", id, ">")); } sb.AppendLine(string.Concat("= \'", _ToRegex(genInfo.Xbnf, e, true), "\'")); } } return(sb.ToString()); }
static void _TranslateMacros(XbnfGenerationInfo info, CodeTypeDeclaration parser, CodeStatementCollection stmts, CodeTypeReference type, out bool hasChangeType, out bool hasEvalAny, out bool hasReturn) { hasEvalAny = false; hasChangeType = false; hasReturn = false; var hasEA = false; var hasCT = false; var hasR = false; var node = C.ArgRef("node"); for (int ic = stmts.Count, i = 0; i < ic; ++i) { var stmt = stmts[i]; V.Visit(stmt, (ctx) => { var idx = ctx.Target as CodeIndexerExpression; if (null != idx && 1 == idx.Indices.Count) { var to = idx.TargetObject as CodeVariableReferenceExpression; if (null != to) { int pi; if (0 == string.Compare("Child", to.VariableName, StringComparison.InvariantCulture)) { // is a thing like Child[0] hasEA = true; var mi = C.Invoke(C.TypeRef(parser.Name), "_EvaluateAny", C.ArrIndexer(C.PropRef(node, "Children"), idx.Indices[0]), C.ArgRef("state")); V.ReplaceTarget(ctx, mi); } else if (-1 < (pi = info.Xbnf.Productions.IndexOf(to.VariableName))) { // is a thing like Factor[0] var p = info.Xbnf.Productions[pi]; if (!p.IsCollapsed && !p.IsHidden) { if (!p.IsTerminal) { var mi = C.Invoke(C.TypeRef(parser.Name), string.Concat("Evaluate", p.Name), C.ArrIndexer(C.PropRef(node, "Children"), idx.Indices[0]), C.ArgRef("state")); V.ReplaceTarget(ctx, mi); } else { var pr = C.PropRef(C.ArrIndexer(C.PropRef(node, "Children"), idx.Indices[0]), "Value"); V.ReplaceTarget(ctx, pr); } } } else if (0 == string.Compare("SymbolId", to.VariableName)) { var pr = C.PropRef(C.ArrIndexer(C.PropRef(node, "Children"), idx.Indices[0]), "SymbolId"); V.ReplaceTarget(ctx, pr); } } } var v = ctx.Target as CodeVariableReferenceExpression; if (null != v) { foreach (var p in info.Xbnf.Productions) { if (p.IsHidden || p.IsCollapsed) { continue; } if (v.VariableName.StartsWith(p.Name, StringComparison.InvariantCulture)) { if (p.Name.Length < v.VariableName.Length) { var s = v.VariableName.Substring(p.Name.Length); int num; if (int.TryParse(s, out num)) { if (0 < num) { if (!p.IsTerminal) { var mi = C.Invoke(C.TypeRef(parser.Name), string.Concat("Evaluate", p.Name), C.ArrIndexer(C.PropRef(node, "Children"), C.Literal(num - 1)), C.ArgRef("state")); V.ReplaceTarget(ctx, mi); } else { var pr = C.PropRef(C.ArrIndexer(C.PropRef(node, "Children"), C.Literal(num - 1)), "Value"); V.ReplaceTarget(ctx, pr); } } } } } else if (v.VariableName.StartsWith("Child", StringComparison.InvariantCulture)) { if (5 < v.VariableName.Length) { var s = v.VariableName.Substring(5); int num; if (int.TryParse(s, out num)) { if (0 < num) { hasEA = true; var mi = C.Invoke(C.TypeRef(parser.Name), "_EvaluateAny", C.ArrIndexer(C.PropRef(node, "Children"), C.Literal(num - 1)), C.ArgRef("state")); V.ReplaceTarget(ctx, mi); } } } } else if (0 == string.Compare("Length", v.VariableName, StringComparison.InvariantCulture)) { var ffr = C.PropRef(C.PropRef(node, "Children"), "Length"); V.ReplaceTarget(ctx, ffr); } else { if (v.VariableName.StartsWith("SymbolId", StringComparison.InvariantCulture)) { if (8 < v.VariableName.Length) { var s = v.VariableName.Substring(8); int num; if (int.TryParse(s, out num)) { if (0 < num) { var pr = C.PropRef(C.ArrIndexer(C.PropRef(node, "Children"), C.Literal(num - 1)), "SymbolId"); V.ReplaceTarget(ctx, pr); } } } } } } } /*}); * V.Visit(stmt, (ctx) => * {*/ var r = ctx.Target as CodeMethodReturnStatement; if (null != r) { if (!CD.CodeDomResolver.IsNullOrVoidType(type) && (0 != type.ArrayRank || 0 != string.Compare("System.Object", type.BaseType, StringComparison.InvariantCulture))) { var hasVoid = false; if (null != r.Expression) { var p = r.Expression as CodePrimitiveExpression; if (null != p) { if (null == p.Value) { hasVoid = true; } } } if (null == r.Expression || hasVoid) { r.Expression = C.Default(type); } else { var isType = false; var cc = r.Expression as CodeCastExpression; if (null != cc) { if (CD.CodeTypeReferenceEqualityComparer.Equals(cc.TargetType, type)) { isType = true; } } if (!isType) { hasCT = true; r.Expression = C.Cast(type, C.Invoke(C.TypeRef(parser.Name), "_ChangeType", r.Expression, C.TypeOf(type))); } } } hasR = true; } }); if (hasR) { hasReturn = true; } } hasChangeType = hasCT; hasEvalAny = hasEA; }
public static CodeCompileUnit GenerateCompileUnit(XbnfGenerationInfo genInfo, string codeclass, string codenamespace, bool fast) { var result = new CodeCompileUnit(); var ns = new CodeNamespace(); if (!string.IsNullOrEmpty(codenamespace)) { ns.Name = codenamespace; } result.Namespaces.Add(ns); ns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); var td = C.Class(codeclass, false); td.CustomAttributes.Add(GeneratedCodeAttribute); td.BaseTypes.Add(C.Type("GlrTableParser")); // GlrTableParser(int[][][][] parseTable,string[] symbolTable, ParseAttribute[][] attributes,int[] errorSentinels, IEnumerable<Token> tokenizer,int maxErrorCount) td.Members.Add(C.Field(C.Type(typeof(int[][][][])), "ParseTable", MemberAttributes.FamilyAndAssembly | MemberAttributes.Static)); td.Members.Add(C.Field(C.Type(typeof(string[])), "SymbolTable", MemberAttributes.FamilyAndAssembly | MemberAttributes.Static)); td.Members.Add(C.Field(C.Type(C.Type("ParseAttribute", 1), 1), "ParseAttributes", MemberAttributes.FamilyAndAssembly | MemberAttributes.Static)); td.Members.Add(C.Field(C.Type(typeof(int[])), "ErrorSentinels", MemberAttributes.FamilyAndAssembly | MemberAttributes.Static)); //td.Members.Add(C.Field(C.Type(typeof(int[])), "NodeFlags", MemberAttributes.FamilyAndAssembly | MemberAttributes.Static)); var et = C.Type("IEnumerable"); et.TypeArguments.Add(C.Type("Token")); var ctor = C.Ctor(MemberAttributes.Public, C.Param(et, "tokenizer")); ctor.BaseConstructorArgs.AddRange(new CodeExpression[] { C.FieldRef(C.TypeRef(codeclass), "ParseTable"), C.FieldRef(C.TypeRef(codeclass), "SymbolTable"), C.FieldRef(C.TypeRef(codeclass), "ParseAttributes"), C.FieldRef(C.TypeRef(codeclass), "ErrorSentinels"), //C.FieldRef(C.TypeRef(codeclass), "NodeFlags"), C.ArgRef("tokenizer"), C.FieldRef(C.TypeRef(typeof(int)), "MaxValue") }); td.Members.Add(ctor); ctor = C.Ctor(MemberAttributes.Public, C.Param(et, "tokenizer"), C.Param(typeof(int), "maxErrorCount")); ctor.BaseConstructorArgs.AddRange(new CodeExpression[] { C.FieldRef(C.TypeRef(codeclass), "ParseTable"), C.FieldRef(C.TypeRef(codeclass), "SymbolTable"), C.FieldRef(C.TypeRef(codeclass), "ParseAttributes"), C.FieldRef(C.TypeRef(codeclass), "ErrorSentinels"), //C.FieldRef(C.TypeRef(codeclass), "NodeFlags"), C.ArgRef("tokenizer"), C.ArgRef("maxErrorCount") }); td.Members.Add(ctor); ns.Types.Add(td); CfgGlrParseTable pt; genInfo.Cfg.TryToGlrParseTable(out pt); int ts; var syms = XbnfConvert.GetSymbolTable(genInfo, out ts); (C.GetByName("ParseTable", td.Members) as CodeMemberField).InitExpression = C.Literal(pt.ToArray(syms)); (C.GetByName("SymbolTable", td.Members) as CodeMemberField).InitExpression = C.Literal(syms.ToArray()); (C.GetByName("ParseAttributes", td.Members) as CodeMemberField).InitExpression = _SerializeParseAttributes(genInfo, syms); (C.GetByName("ErrorSentinels", td.Members) as CodeMemberField).InitExpression = _SerializeErrorSentinels(genInfo, syms); //(C.GetByName("NodeFlags", td.Members) as CodeMemberField).InitExpression = _SerializeNodeFlags(genInfo,syms); foreach (var code in genInfo.Xbnf.Code) { td.Members.AddRange(SlangParser.ParseMembers(code.Value, code.Line, code.Column, code.Position)); } var hasChangeType = false; var hasEvalAny = false; foreach (var prod in genInfo.Xbnf.Productions) { if (null != prod.Action) { var hasEA = false; var hasCT = false; _GenerateAction(genInfo, syms, td, prod, fast, out hasCT, out hasEA); if (hasCT) { hasChangeType = true; } if (hasEA) { hasEvalAny = true; } } } var consts = new string[syms.Count]; for (int ic = syms.Count, i = 0; i < ic; ++i) { var s = syms[i]; if ("#ERROR" == s) { s = "ErrorSymbol"; } else if ("#EOS" == s) { s = "EosSymbol"; } s = _MakeSafeName(s); s = _MakeUniqueMember(td, s); consts[i] = s; td.Members.Add(C.Field(typeof(int), s, MemberAttributes.Const | MemberAttributes.Public, C.Literal(i))); } if (hasChangeType) { var m = C.Method(C.Type(typeof(object)), "_ChangeType", MemberAttributes.Static | MemberAttributes.Private, C.Param(typeof(object), "obj"), C.Param(typeof(Type), "type")); m.Statements.Add(C.Var(typeof(TypeConverter), "typeConverter", C.Invoke(C.TypeRef(typeof(TypeDescriptor)), "GetConverter", C.ArgRef("obj")))); // if(null!=typeConverter || !typeConverter.CanConvertTo(type)) m.Statements.Add(C.If(C.Or(C.IdentEq(C.Null, C.VarRef("typeConverter")), C.Not(C.Invoke(C.VarRef("typeConverter"), "CanConvertTo", C.ArgRef("type")))), C.Return(C.Invoke(C.TypeRef(typeof(Convert)), "ChangeType", C.ArgRef("obj"), C.ArgRef("type"))) )); m.Statements.Add(C.Return(C.Invoke(C.VarRef("typeConverter"), "ConvertTo", C.ArgRef("obj"), C.ArgRef("type")))); td.Members.Add(m); } if (hasEvalAny) { var sid = C.PropRef(C.ArgRef("node"), "SymbolId"); var m = C.Method(typeof(object), "_EvaluateAny", MemberAttributes.Private | MemberAttributes.Static, C.Param(C.Type("ParseNode"), "node"), C.Param(typeof(object), "state")); for (int ic = genInfo.Xbnf.Productions.Count, i = 0; i < ic; ++i) { var p = genInfo.Xbnf.Productions[i]; if (!p.IsCollapsed && !p.IsHidden) { var sidcmp = syms.IndexOf(p.Name); var sidcf = C.FieldRef(C.TypeRef(td.Name), consts[sidcmp]); var cnd = C.If(C.Eq(sid, sidcf)); if (!p.IsTerminal) { cnd.TrueStatements.Add(C.Return(C.Invoke(C.TypeRef(td.Name), string.Concat("Evaluate", p.Name), C.ArgRef("node"), C.ArgRef("state")))); } else { cnd.TrueStatements.Add(C.Return(C.PropRef(C.ArgRef("node"), "Value"))); } m.Statements.Add(cnd); } } m.Statements.Add(C.Return(C.Null)); td.Members.Add(m); } return(result); }
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); }