public void GenerateTable(DataGridView gridView) { int NextStateNumber = 0; //Número do próximo estado List <LRState> states = new List <LRState>(); //Estados var productions = _syntactic.GetSingleProductions(); //Pega todas as produções var firstProduction = productions.First(); //Inicio com o primeiro estado (0) var firstState = new LRState(); firstState.Number = NextStateNumber; NextStateNumber++; //Adiciona a primeira produção (Slinha) var firstStateProduction = new LRStateProduction(); firstStateProduction.LocalFolow.Add(new Symbol() { Type = SymbolType.EndOfFile, Value = "$" }); firstStateProduction.Production = firstProduction; firstState.Productions.Add(firstStateProduction); states.Add(firstState); while (states.Exists(e => e.Done == false)) { var actualState = states.First(w => w.Done == false); while (actualState.Productions.Exists(u => u.Checked == false)) { var p = actualState.Productions.First(i => i.Checked == false); if (!p.Checked) { Closure(p, ref actualState, productions); } } if (!actualState.Productions.Exists(g => g.Checked == false)) { actualState.Done = true; //TERMINOU O FECHO, CRIA OS PRÓXIMOS ESTADOS } var grouped = actualState.Productions.Where(e => e.Action == ActionType.State).GroupBy(item => item.Marked.Symbol.Value); foreach (var item in grouped) { bool similarTransitionFound = false; //VERIFICA SE JÁ EXISTE ALGUMA TRANSIÇÃO SIMILAR // item = transições para o mesmo estado, agrupadas foreach (var VARIABLE in states.Where(e => !e.Equals(actualState))) { var stateGroupedProductions = VARIABLE.Productions.GroupBy(x => new { x.ActionNumber }); foreach (var gp in stateGroupedProductions) { if (gp.ToList().Count == item.ToList().Count() && gp.All(a => a.Action == ActionType.State)) { bool flag = true; //SÃO DO MESMO TAMANHO, POSSO VERIFICAR SE SÃO IGUAIS for (int i = 0; i < gp.ToList().Count; i++) { if (!(gp.ToList()[i].Production.Equals(item.ToList()[i].Production)) || !(gp.ToList()[i].Marked.Index == item.ToList()[i].Marked.Index)) { flag = false; } else { if (gp.ToList()[i].LocalFolow.ToList().Count == item.ToList()[i].LocalFolow.Count()) { //SÃO DO MESMO TAMANHO, POSSO VERIFICAR SE SÃO IGUAIS for (int j = 0; j < gp.ToList()[i].LocalFolow.Count; j++) { if (!(gp.ToList()[i].LocalFolow[j].Value.Equals(item.ToList()[i].LocalFolow[j].Value))) { flag = false; } } } else { flag = false; } } } if (flag) { similarTransitionFound = true; foreach (var va in item) { va.ActionNumber = gp.First().ActionNumber; } break; } } } if (similarTransitionFound) { break; } } if (!similarTransitionFound) { var newState = new LRState(); newState.Number = NextStateNumber; foreach (var VARIABLE in item) { var nextStateNewProduction = new LRStateProduction() { Production = VARIABLE.Production, Marked = new MarkedSymbol() { Index = VARIABLE.Marked.Index, Symbol = new Symbol() { Type = VARIABLE.Marked.Symbol.Type, Value = VARIABLE.Marked.Symbol.Value } }, Checked = false }; nextStateNewProduction.LocalFolow.AddRange(VARIABLE.LocalFolow); newState.Productions.Add(nextStateNewProduction); } foreach (var pro in newState.Productions) { pro.Checked = false; } states.Add(newState); foreach (var VARIABLE in item) { actualState.Productions.Find(w => w.Equals(VARIABLE)).ActionNumber = NextStateNumber; } NextStateNumber++; } } } CreateTableMatches(states); Generated = true; this.LRstates.AddRange(states.ToList()); }
public void Closure(LRStateProduction p, ref LRState actualState, List <SingleProduction> productions) { //VERIFICO SE PRECISO ANDAR COM O FECHO E INCREMENTO O INDEX p.Marked.Index++; if (p.Marked.Index < p.Production.Produced.Count) { p.Marked.Symbol = p.Production.Produced.ElementAt(p.Marked.Index); } //Verifica se existe um simbolo nesse index. Caso não, é uma redução if ((p.Marked.Index >= p.Production.Produced.Count) || ((p.Marked.Symbol.Type == SymbolType.Empty) && (p.Marked.Index + 1 == p.Production.Produced.Count))) { p.Action = ActionType.Reduction; p.ActionNumber = p.Production.Number; } else { p.Marked.Symbol = p.Production.Produced.ElementAt(p.Marked.Index); p.Action = ActionType.State; //ANDEI COM O FECHO, VERIFICO SE É UM NÃO TERMINAL var s = p.Marked.Symbol; if (s.Type == SymbolType.NonTerminal) { //PEGO AS PRODUÇÕES DESSE NÃO TERMINAL var nonTerminalProductions = productions.Where(t => t.Producer.Value == s.Value); //DECIDO QUAL VAI SER O FOLLOW var localFollow = new List <Symbol>(); if (p.Marked.Index + 1 < p.Production.Produced.Count) { //Pego o first desse simbolo var nextSymbol = p.Production.Produced.ElementAt(p.Marked.Index + 1); if (nextSymbol.Type == SymbolType.Terminal) { localFollow.Add(new Symbol() { Type = nextSymbol.Type, Value = nextSymbol.Value }); } if (nextSymbol.Type == SymbolType.NonTerminal) { localFollow.AddRange(_semantic.GetFirstList() .Find(e => e.NonTerminal.Value == nextSymbol.Value).Terminals); } } else { //Follow local é igual ao follow atual localFollow.AddRange(p.LocalFolow); } //Já tenho o Follow local, verifico se preciso atualizar o follow de alguém if (actualState.ClosureSymbols.Exists(i => i.Value == s.Value)) { var actualStateNumber = actualState.Number; var pendingUpdateProductions = actualState.Productions.Where(r => r.Production.Producer.Value == s.Value && r.GeneratorStateNumber == actualStateNumber); foreach (var lrp in pendingUpdateProductions) { foreach (var followSymbol in localFollow) { if (!lrp.LocalFolow.Exists(e => e.Value == followSymbol.Value)) { lrp.LocalFolow.Add(followSymbol); } } } } else { //CRIEI UM NOVO LRStateProduction para o estado, que é igual à production desse não terminal foreach (var VARIABLE in nonTerminalProductions) { LRStateProduction sp = new LRStateProduction(); sp.Production = VARIABLE; sp.LocalFolow.AddRange(localFollow); sp.GeneratorStateNumber = actualState.Number; actualState.Productions.Add(sp); } //SALVA QUE JÁ GEROU O FECHO DESSE NÃO TERMINAL actualState.ClosureSymbols.Add(s); } } } p.Checked = true; //MARCO QUE TERMINEI O FECHO DESSE }