//computes DirectFirsts, Firsts for non-terminals and productions private static void ComputeFirsts(GrammarData data) { //compute prod direct firsts and initialize NT.Firsts foreach (var nt in data.NonTerminals) { foreach (var prod in nt.Productions) { foreach (var term in prod.RValues) { prod.DirectFirsts.Add(term); nt.DirectFirsts.Add(term); nt.Firsts.Add(term); if (!term.IsSet(TermOptions.IsNullable)) break; //foreach term } } }//foreach nt //propagate NT.Firsts int time = 0; var done = false; var newSet = new BnfTermSet(); while (!done) { done = true; foreach (var nt in data.NonTerminals) { newSet.Clear(); foreach (var first in nt.Firsts) { var ntFirst = first as NonTerminal; if (ntFirst != null && ntFirst._lastChanged >= nt._lastChecked) newSet.UnionWith(ntFirst.Firsts); } nt._lastChecked = time++; var oldCount = nt.Firsts.Count; nt.Firsts.UnionWith(newSet); if (nt.Firsts.Count > oldCount) { done = false; nt._lastChanged = time; } }//foreach nt }//while //compute prod.Firsts foreach (var nt in data.NonTerminals) { foreach (var prod in nt.Productions) { prod.Firsts.UnionWith(prod.DirectFirsts); foreach (var directFirst in prod.DirectFirsts) { var ntDirectFirst = directFirst as NonTerminal; if (ntDirectFirst != null) prod.Firsts.UnionWith(ntDirectFirst.Firsts); }//foreach directFirst }//foreach prod }//foreach nt }
//computes DirectFirsts, Firsts for non-terminals and productions private static void ComputeFirsts(GrammarData data) { //compute prod direct firsts and initialize NT.Firsts foreach (var nt in data.NonTerminals) { foreach (var prod in nt.Productions) { foreach (var term in prod.RValues) { prod.DirectFirsts.Add(term); nt.DirectFirsts.Add(term); nt.Firsts.Add(term); if (!term.IsSet(TermOptions.IsNullable)) { break; //foreach term } } } }//foreach nt //propagate NT.Firsts int time = 0; var done = false; var newSet = new BnfTermSet(); while (!done) { done = true; foreach (var nt in data.NonTerminals) { newSet.Clear(); foreach (var first in nt.Firsts) { var ntFirst = first as NonTerminal; if (ntFirst != null && ntFirst._lastChanged >= nt._lastChecked) { newSet.UnionWith(ntFirst.Firsts); } } nt._lastChecked = time++; var oldCount = nt.Firsts.Count; nt.Firsts.UnionWith(newSet); if (nt.Firsts.Count > oldCount) { done = false; nt._lastChanged = time; } } //foreach nt } //while //compute prod.Firsts foreach (var nt in data.NonTerminals) { foreach (var prod in nt.Productions) { prod.Firsts.UnionWith(prod.DirectFirsts); foreach (var directFirst in prod.DirectFirsts) { var ntDirectFirst = directFirst as NonTerminal; if (ntDirectFirst != null) { prod.Firsts.UnionWith(ntDirectFirst.Firsts); } } //foreach directFirst } //foreach prod } //foreach nt } //method