public static IProductionRuleItem ResolveTemplateSoftReference<T>(this ISoftTemplateReferenceProductionRuleItem item, T entry, OilexerGrammarFile file, ICompilerErrorCollection errors) where T : IOilexerGrammarProductionRuleEntry { IOilexerGrammarProductionRuleTemplateEntry iprte = null; var closeMatches = GetList(new { Entry = (IOilexerGrammarProductionRuleTemplateEntry)null, ArgumentInformation = default(TemplateArgumentInformation) }); foreach (IOilexerGrammarProductionRuleTemplateEntry template in ruleTemplEntries) { if (template.Name == item.PrimaryName) { TemplateArgumentInformation tai = template.GetArgumentInformation(); if (item.Parts.Count >= tai.FixedArguments) { closeMatches.Add(new { Entry = template, ArgumentInformation = tai }); if (tai.DynamicArguments > 0) { if ((item.Parts.Count - tai.FixedArguments) % tai.DynamicArguments == 0) { if (tai.InvalidArguments == 0) { iprte = template; break; } } } else if (tai.InvalidArguments == 0) { if (item.Parts.Count == tai.FixedArguments) { iprte = template; break; } } } else { closeMatches.Add(new { Entry = template, ArgumentInformation = tai }); continue; } } } if (iprte != null) { foreach (IProductionRuleSeries iprs in item.Parts) iprs.ResolveProductionRuleSeries(entry, file, errors); TemplateReferenceProductionRuleItem rResult = new TemplateReferenceProductionRuleItem(iprte, new List<IProductionRuleSeries>(item.Parts.ToArray()), item.Column, item.Line, item.Position); if (resolutionAid != null) resolutionAid.ResolvedSinglePartToRuleTemplate(item, iprte); if (item.RepeatOptions != ScannableEntryItemRepeatInfo.None) rResult.RepeatOptions = item.RepeatOptions; if (item.Name != null && item.Name != string.Empty) rResult.Name = item.Name; return rResult; } else if (closeMatches.Count > 0) { var fixedMatch = (from templateArguments in closeMatches let arguments = templateArguments.ArgumentInformation where arguments.FixedArguments > 0 orderby arguments.FixedArguments descending select templateArguments.Entry); IOilexerGrammarProductionRuleTemplateEntry closestMismatch = null; foreach (var mismatch in fixedMatch) { if (item.Parts.Count > mismatch.Parts.Count) { closestMismatch = mismatch; break; } } /**/ if (closestMismatch == null) closestMismatch = fixedMatch.Last(); if (fixedMatch != null) errors.SourceModelError<ISoftTemplateReferenceProductionRuleItem, IOilexerGrammarProductionRuleTemplateEntry>(OilexerGrammarCore.CompilerErrors.FixedArgumentMismatch, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item, closestMismatch, new string[] { closestMismatch.Name, closestMismatch.Parts.Count.ToString(), item.Parts.Count.ToString() }); else { var dynamicMatch = (from templateArguments in closeMatches let arguments = templateArguments.ArgumentInformation where arguments.DynamicArguments > 0 select templateArguments.Entry).FirstOrDefault(); if (dynamicMatch != null) errors.SourceModelError<IOilexerGrammarProductionRuleTemplateEntry>(OilexerGrammarCore.CompilerErrors.DynamicArgumentCountError, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), dynamicMatch); else { var invalidMatch = (from templateArguments in closeMatches let arguments = templateArguments.ArgumentInformation where arguments.InvalidArguments > 0 select templateArguments.Entry).FirstOrDefault(); if (invalidMatch != null) errors.SourceModelError<IOilexerGrammarProductionRuleTemplateEntry>(OilexerGrammarCore.CompilerErrors.InvalidRepeatOptions, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), invalidMatch); else if (ruleEntries.OilexerGrammarFindScannableEntry(item.PrimaryName) != null) errors.SourceModelError<ISoftTemplateReferenceProductionRuleItem>(OilexerGrammarCore.CompilerErrors.RuleNotTemplate, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item, item.PrimaryName); } } //errors.Add(OilexerGrammarCore.GetParserError(entry.FileName, item.Line, item.Column, OilexerGrammarParserErrors.DynamicArgumentCountError)); } else if (ruleEntries.OilexerGrammarFindScannableEntry(item.PrimaryName) != null) errors.SourceModelError<ISoftTemplateReferenceProductionRuleItem>(OilexerGrammarCore.CompilerErrors.RuleNotTemplate, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item, item.PrimaryName); else { var matches = (from template in ruleTemplEntries where template.Name == item.PrimaryName select template).Count(); if (matches > 0) errors.SourceError(OilexerGrammarCore.CompilerErrors.FixedArgumentMismatch, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item.PrimaryName); else errors.SourceError(OilexerGrammarCore.CompilerErrors.UndefinedRuleReference, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item.PrimaryName); } return item; } public static IProductionRuleItem ResolveSoftReference<T>(this ISoftReferenceProductionRuleItem item, T entry, OilexerGrammarFile file, ICompilerErrorCollection errors) where T : IOilexerGrammarProductionRuleEntry { if (entry is IOilexerGrammarProductionRuleTemplateEntry) { var templateEntry = entry as IOilexerGrammarProductionRuleTemplateEntry; if (string.IsNullOrEmpty(item.SecondaryName)) foreach (IProductionRuleTemplatePart iprtp in templateEntry.Parts) if (iprtp.Name == item.PrimaryName) { TemplateParamReferenceProductionRuleItem result = new TemplateParamReferenceProductionRuleItem(templateEntry, iprtp, item.Column, item.Line, item.Position); if (resolutionAid != null) resolutionAid.ResolvedSinglePartToTemplateParameter(templateEntry, iprtp, item); if (item.RepeatOptions != ScannableEntryItemRepeatInfo.None) result.RepeatOptions = item.RepeatOptions; if (item.Name != null && result.Name == null) result.Name = item.Name; return result; } } IOilexerGrammarProductionRuleEntry ipre = ruleEntries.OilexerGrammarFindScannableEntry(item.PrimaryName); if (ipre != null) { RuleReferenceProductionRuleItem rrpri = new RuleReferenceProductionRuleItem(ipre, item.Column, item.Line, item.Position); if (resolutionAid != null) resolutionAid.ResolvedSinglePartToRule(item, ipre); ((ProductionRuleItem)(item)).CloneData(rrpri); return rrpri; } else if (ruleTemplEntries.OilexerGrammarFindScannableEntry(item.PrimaryName) != null) errors.SourceModelError<ISoftReferenceProductionRuleItem>(OilexerGrammarCore.CompilerErrors.RuleIsTemplate, new LineColumnPair(item.Line, item.Column), LineColumnPair.Zero, new Uri(entry.FileName, UriKind.RelativeOrAbsolute), item, item.PrimaryName); else { IOilexerGrammarTokenEntry tokenE = tokenEntries.OilexerGrammarFindScannableEntry(item.PrimaryName); if (tokenE != null) if (item.SecondaryName != null) { ITokenItem iti = tokenE.FindTokenItem(item.SecondaryName); if (iti != null) { IProductionRuleItem result = null; if (iti is ILiteralCharTokenItem) { if (resolutionAid != null) resolutionAid.ResolvedDualPartToTokenItem(item, tokenE, iti); result = new LiteralCharReferenceProductionRuleItem(((ILiteralCharTokenItem)(iti)), tokenE, item.Column, item.Line, item.Position, item.IsFlag, item.Counter); } else if (iti is ILiteralStringTokenItem) { if (resolutionAid != null) resolutionAid.ResolvedDualPartToTokenItem(item, tokenE, iti); result = new LiteralStringReferenceProductionRuleItem(((ILiteralStringTokenItem)(iti)), tokenE, item.Column, item.Line, item.Position, item.IsFlag, item.Counter); } else { /* * * ToDo: Throw an error here for referencing the wrong type of token * */ } if (result != null) { result.Name = item.Name; result.RepeatOptions = item.RepeatOptions; return result; } }
internal static IProductionRuleItem Expand(this IProductionRuleItem ruleItem, IOilexerGrammarProductionRuleEntry currentEntry, IList <IOilexerGrammarTokenEntry> availableStock, ProductionRuleTemplateArgumentSeries argumentLookup, IOilexerGrammarProductionRuleTemplateEntry entry, OilexerGrammarFile file, ICompilerErrorCollection errors) { if (ruleItem is IProductionRulePreprocessorDirective) { return(((IProductionRulePreprocessorDirective)(ruleItem)).Expand(currentEntry, availableStock, argumentLookup, entry, file, errors)); } else if (ruleItem is ITemplateParamReferenceProductionRuleItem) { TemplateParamReferenceProductionRuleItem trpri = (TemplateParamReferenceProductionRuleItem)ruleItem; if (argumentLookup.Lookup.ContainsKey(trpri.Reference)) { IProductionRuleSeries series = argumentLookup.Lookup[trpri.Reference].Replacement; /* * * Fix 4-29-2013 * * * Series null check, if an error is thrown by the user's template within a replacement * the result of the replacement is null, thus this is null. * */ if (series == null) { return(null); } if (series.Count == 1 && series[0].Count == 1) { IProductionRuleItem ipri = series[0][0].Clone(); trpri.CloneData(ipri); return(ipri); } else { ProductionRuleGroupItem result = new ProductionRuleGroupItem(series.ToArray(), trpri.Column, trpri.Line, trpri.Position); trpri.CloneData(result); return(result); } } else { return(trpri.Clone()); } } else if (ruleItem is ITemplateReferenceProductionRuleItem) { ITemplateReferenceProductionRuleItem rI = ruleItem as TemplateReferenceProductionRuleItem; List <IProductionRuleSeries> serii = new List <IProductionRuleSeries>(); foreach (IProductionRuleSeries series in rI) { var seriesCopy = series; /* * * Handle deliteralization here to expedite * phase 3. If a template yields 5000 literals * then deliteralizing that will waste a massive * chunk of processor cycles. * */ if (series.NeedsDeliteralized()) { seriesCopy = seriesCopy.Deliteralize(currentEntry, availableStock, file, errors); } serii.Add(seriesCopy.Expand(currentEntry, availableStock, argumentLookup, entry, file, errors)); } TemplateReferenceProductionRuleItem result = new TemplateReferenceProductionRuleItem(rI.Reference, serii, rI.Column, rI.Line, rI.Position); ((TemplateReferenceProductionRuleItem)ruleItem).CloneData(result); return(result.Expand(availableStock, entry, file, errors)); } else if (ruleItem is IProductionRuleGroupItem) { if (!((IProductionRuleSeries)(ruleItem)).HasExpansion()) { return(ruleItem.Clone()); } else { ProductionRuleGroupItem result = new ProductionRuleGroupItem(((IProductionRuleSeries)ruleItem).Expand(currentEntry, availableStock, argumentLookup, entry, file, errors).ToArray(), ruleItem.Column, ruleItem.Line, ruleItem.Position); result.RepeatOptions = ruleItem.RepeatOptions; result.Name = ruleItem.Name; return(result); } } else { return(ruleItem.Clone()); } }