/// <summary> /// Поиск нетерминала ANY и генерация правила для него. /// </summary> /// <param name="trace"></param> private void findNonTermANY(List <Pair> trace, RuleDeclaration rd) { List <SubRulePart> list = trace[trace.Count - 1].List; for (int i = 0; i < list.Count; ++i) { trace[trace.Count - 1].Index = i; //главная проверка if list[i] is subruleany if (list[i] is SubRuleAny) { CreateRuleForANY(trace, list[i] as SubRuleAny, rd); } if (list[i] is SubRuleComplexPart) { SubRuleComplexPart sc = list[i] as SubRuleComplexPart; for (int j = 0; j < sc.Items.Count; ++j) { trace.Add(new Pair(sc.Items[j], 0)); findNonTermANY(trace, rd); trace.RemoveAt(trace.Count - 1); } } } }
public HashSet <string> GetFIRSTforComplexSubRulePart(SubRuleComplexPart SC) { if (FIRST == null) { BuildFIRST(); } HashSet <string> res = new HashSet <string>(); foreach (List <SubRulePart> branch in SC.Items) { res.UnionWith(GetFIRSTForBranch(branch)); } return(res); }
/// <summary> /// В ветке заменяем строковые литералы на лексемы, существующие (при наличии) или новые. /// </summary> /// <param name="branch"></param> private void DeclareTokensInComplexSRP(List <SubRulePart> branch) { foreach (SubRulePart srp in branch) { if (srp is SubRuleAny) { SubRuleAny Any = srp as SubRuleAny; srp.Name = StringConstants.tkANY + AnyCounter; AnyCounter += 1; HashSet <string> newExcept = new HashSet <string>(); foreach (string str in Any.Except) { if (str.StartsWith(StringConstants.StringQuote)) { newExcept.Add(symbolTable.FindOrCreateToken(str)); } else { newExcept.Add(str); } } Any.Except = newExcept; continue; } SubRuleComplexPart sc = srp as SubRuleComplexPart; if (sc != null) { foreach (List <SubRulePart> br2 in sc.Items) { DeclareTokensInComplexSRP(br2); } } else if (srp.Name.StartsWith(StringConstants.StringQuote)) { srp.Name = symbolTable.FindOrCreateToken(srp.Name); } } }
private bool IsUseNameSymbolInBranch(List <SubRulePart> branch) { foreach (SubRulePart srp in branch) { if (srp.UseName) { return(true); } if (srp is SubRuleComplexPart) { SubRuleComplexPart sc = srp as SubRuleComplexPart; foreach (List <SubRulePart> br2 in sc.Items) { if (IsUseNameSymbolInBranch(br2)) { return(true); } } } } return(false); }
/// <summary> /// Преобразуем квадратные скобки в новое правило /// </summary> /// <param name="part"></param> /// <returns></returns> private SubRulePart ConvertComplexSubrulePart(SubRuleComplexPart part) { for (int i = 0; i < part.Items.Count; ++i) { for (int j = 0; j < part.Items[i].Count; ++j) { if (part.Items[i][j] is SubRuleComplexPart) { part.Items[i][j] = ConvertComplexSubrulePart(part.Items[i][j] as SubRuleComplexPart); if (part.Items[i][j] == null) { part.Items[i].RemoveAt(j); } --j; } } } part.InitUses(); //тут можно сгенерировать имя так, чтобы одинаковые конструкции не дублировались SubRulePart result = new SubRulePart(); result.UseName = part.UseName; result.UseValue = part.UseValue; result.Name = symbolTable.GetNewName(""); result.Repetition = SubRuleRepetition.Once; RuleDeclaration rd = new RuleDeclaration(); rd.Name = result.Name; rd.Location = part.Location; SubRulePart thisRule = new SubRulePart(result.Name); thisRule.UseName = result.UseName; thisRule.UseValue = result.UseValue; if (part.Repetition == SubRuleRepetition.ZeroOrOne) { rd.SubRules.Add(new List <SubRulePart>()); rd.SubRules.AddRange(part.Items); } else if (part.Repetition == SubRuleRepetition.ZeroOrMore) { rd.SubRules.Add(new List <SubRulePart>()); rd.SubRules.AddRange(part.Items); for (int i = 1; i < rd.SubRules.Count; ++i) { rd.SubRules[i].Insert(0, thisRule); } } else if (part.Repetition == SubRuleRepetition.OneOrMore) { rd.SubRules.AddRange(part.Items); foreach (List <SubRulePart> L in part.Items) { List <SubRulePart> L2 = new List <SubRulePart>(); L2.Add(thisRule); L2.AddRange(L); rd.SubRules.Add(L2); } } else if (part.Repetition == SubRuleRepetition.Once) { if (part.Items.Count == 0) { return(null); } if (part.Items.Count == 1 && part.Items[0].Count == 1) { return(part.Items[0][0]); } rd.SubRules.AddRange(part.Items); } symbolTable.AddRuleDeferred(rd); return(result); }
public HashSet<string> GetFIRSTforComplexSubRulePart(SubRuleComplexPart SC) { if (FIRST == null) BuildFIRST(); HashSet<string> res = new HashSet<string>(); foreach (List<SubRulePart> branch in SC.Items) res.UnionWith(GetFIRSTForBranch(branch)); return res; }
/// <summary> /// Преобразуем квадратные скобки в новое правило /// </summary> /// <param name="part"></param> /// <returns></returns> private SubRulePart ConvertComplexSubrulePart(SubRuleComplexPart part) { for (int i = 0; i < part.Items.Count; ++i) for (int j = 0; j < part.Items[i].Count; ++j) if (part.Items[i][j] is SubRuleComplexPart) { part.Items[i][j] = ConvertComplexSubrulePart(part.Items[i][j] as SubRuleComplexPart); if (part.Items[i][j] == null) part.Items[i].RemoveAt(j); --j; } part.InitUses(); //тут можно сгенерировать имя так, чтобы одинаковые конструкции не дублировались SubRulePart result = new SubRulePart(); result.UseName = part.UseName; result.UseValue = part.UseValue; result.Name = symbolTable.GetNewName(""); result.Repetition = SubRuleRepetition.Once; RuleDeclaration rd = new RuleDeclaration(); rd.Name = result.Name; rd.Location = part.Location; SubRulePart thisRule = new SubRulePart(result.Name); thisRule.UseName = result.UseName; thisRule.UseValue = result.UseValue; if (part.Repetition == SubRuleRepetition.ZeroOrOne) { rd.SubRules.Add(new List<SubRulePart>()); rd.SubRules.AddRange(part.Items); } else if (part.Repetition == SubRuleRepetition.ZeroOrMore) { rd.SubRules.Add(new List<SubRulePart>()); rd.SubRules.AddRange(part.Items); for (int i = 1; i < rd.SubRules.Count; ++i) rd.SubRules[i].Insert(0, thisRule); } else if (part.Repetition == SubRuleRepetition.OneOrMore) { rd.SubRules.AddRange(part.Items); foreach (List<SubRulePart> L in part.Items) { List<SubRulePart> L2 = new List<SubRulePart>(); L2.Add(thisRule); L2.AddRange(L); rd.SubRules.Add(L2); } } else if (part.Repetition == SubRuleRepetition.Once) { if (part.Items.Count == 0) return null; if (part.Items.Count == 1 && part.Items[0].Count == 1) return part.Items[0][0]; rd.SubRules.AddRange(part.Items); } symbolTable.AddRuleDeferred(rd); return result; }