public Go_To(int ID, TokenType token, Production prod, int nextState) { this.StateID = ID; this.Token = token; this.NextStateID = nextState; this.LRItem = new LRItem(prod, 0); }
public Go_To(int ID, TokenType token, int nextState, LRItem item) { this.StateID = ID; this.Token = token; this.NextStateID = nextState; this.LRItem = item; }
private List <TokenType> getFirstNextItem(LRItem item) { List <TokenType> result = new List <TokenType>(); //Aumentar posicion analizada LRItem kernel = item.Copy(); Inicio: //Validar si no se ha llegado a la posicion final en la expresion if (kernel.Position < kernel.Production.RightSide.Count) { TokenType token = kernel.Production.RightSide[kernel.Position]; if (token != TokenType.Epsilon) { if (grammar.isNotTerminal(token)) { List <TokenType> firstNext = grammar.first.Find (x => x.tokenNT == kernel.Production.RightSide[kernel.Position]) ?.first ?? throw new InvalidOperationException(); result = result.Concat(firstNext).ToList(); if (result.Contains(TokenType.Epsilon)) { result.RemoveAll(x => x == TokenType.Epsilon); kernel.Position++; if (kernel.Position < kernel.Production.RightSide.Count) { result.Add(TokenType.Epsilon); } goto Inicio; } } else { result.Add(token); } } else { result.Add(token); kernel.Position++; goto Inicio; } } else if (result.Contains(TokenType.Epsilon)) { result.RemoveAll(x => x == TokenType.Epsilon); result = result.Concat(item.lookahead).ToList(); } return(result); }
/// <summary> /// Al encontrar un NO TERMINAL, es necesario analizar nuevas producciones. /// Se devuelven todas las que correspondan. /// </summary> private List <LRItem> getFollowUpItems(TokenType NonTerminalToken, List <TokenType> firstNextItem, List <TokenType> lookahead) { List <LRItem> followUpItems = new List <LRItem>(); Queue <TokenLAPair> nextItems = new Queue <TokenLAPair>(); List <TokenLAPair> itemsAlreadyInState = new List <TokenLAPair>(); nextItems.Enqueue(new TokenLAPair(NonTerminalToken, getLookaheadNextItem(firstNextItem, lookahead))); while (nextItems.Count > 0) { List <LRItem> childProductions = getSingleFollowUpItem(nextItems.Dequeue()); foreach (var lritem in childProductions) { var item = lritem.Copy().Production; if (item.RightSide[0] == TokenType.Epsilon) { lritem.action = ActionType.Reduce; lritem.Position = 0; followUpItems.Add(lritem); } else { //Agregar a lista de estados followUpItems.Add(lritem); //Si es un NO terminal, seguir obteniendo mas estados derivados if (grammar.isNotTerminal(item.RightSide[0])) { LRItem copyLR = lritem.Copy(); copyLR.Position++; //obtener lookahead correcto if (!itemsAlreadyInState.Any(x => x.token == item.RightSide[0] && x.isLookaheadEqual(copyLR.lookahead))) { nextItems.Enqueue(new TokenLAPair (item.RightSide[0], getLookaheadNextItem(getFirstNextItem(copyLR), copyLR.lookahead))); itemsAlreadyInState.Add(new TokenLAPair(item.RightSide[0], copyLR.lookahead)); } } } } } return(followUpItems); }
public LRItem Copy() { LRItem temp = (LRItem)this.MemberwiseClone(); return(temp); }
private void getCanonicalCollection() { int actualState = 0; int totalStates = 0; // Variable de control para conocer los siguientes elementos a analizar List <Go_To> nextStates = new List <Go_To> { getFirstState() }; // Recordar por donde han pasado los estados List <StatePointer> previouStates = new List <StatePointer>(); while (nextStates.Count > 0) { //Variables de resultado de este estado State thisState = new State(actualState); List <LRItem> lrItems = new List <LRItem>(); //Obtener Goto's que apuntan al estado que vamos a analizar ahora List <Go_To> itemsToAnalyze = new List <Go_To>( (nextStates.FindAll(x => x.NextStateID == actualState))); //Remover Goto's anteriores de la lista original nextStates.RemoveAll(x => x.NextStateID == actualState); //Analizar todos los correspondientes foreach (var item in itemsToAnalyze) { //Diccionario para validar a que estado dirigirse {Token, NoEstado} Dictionary <TokenType, int> gotoState = new Dictionary <TokenType, int>(); //Aumentar posicion analizada LRItem kernel = item.LRItem.Copy(); kernel.Position++; //Validar si se ha llegado a la posicion final en la expresion o si es epsilon if (kernel.Position > kernel.Production.RightSide.Count || kernel.Production.RightSide[kernel.Position - 1] == TokenType.Epsilon) { kernel.action = kernel.Production.LeftSide == TokenType.NT_Start? ActionType.Accept : ActionType.Reduce; kernel.shiftTo = 0; lrItems.Add(kernel); } else { //Token actual TokenType token = kernel.Production.RightSide[kernel.Position - 1]; List <TokenType> lookAheadNextItem = getLookaheadNextItem(getFirstNextItem(kernel), kernel.lookahead); //Verificar si se ha visto el simbolo anteriormente if (previouStates.Any(x => x.symbol == token && x.isLookaheadEqual(lookAheadNextItem))) { //No hacer nada, solo indicar elemento econtrado LRItem nextLR = kernel.Copy(); nextLR.Position--; var state = previouStates.Find(x => x.symbol == token && x.isLookaheadEqual(lookAheadNextItem))?.state; if (state != null) { nextLR.shiftTo = (int)++totalStates; } lrItems.Add(nextLR); //Agregar goto del elemento actualmente analizado al siguiente estado nextStates.Add(new Go_To(actualState, token, totalStates, kernel)); gotoState.Add(token, totalStates); //Obtener el first del elemento siguiente List <TokenType> firstNextItem = getFirstNextItem(kernel); //Obtener derivados List <LRItem> followUpItems = getFollowUpItems(token, firstNextItem, kernel.lookahead); foreach (var childItem in followUpItems) { //Recuperar valor del simbolo anterior var value = previouStates.Find(x => x.isProductionEqual(childItem.Production) && x.isLookaheadEqual(childItem.lookahead))?.state; if (value != null) { childItem.shiftTo = (int)value; } else { if (!gotoState.ContainsKey(childItem.Production.RightSide[0])) { childItem.shiftTo = ++totalStates; //Agregar goto del elemento actualmente analizado al siguiente estado nextStates.Add(new Go_To(actualState, childItem.Production.RightSide[0], totalStates, childItem)); gotoState.Add(childItem.Production.RightSide[0], totalStates); } } lrItems.Add(childItem); } } else { totalStates++; //Agregar al estado actual el primer elemento LRItem nextLR = kernel.Copy(); nextLR.Position--; nextLR.shiftTo = totalStates; lrItems.Add(nextLR); //Agregar goto del elemento actualmente analizado al siguiente estado nextStates.Add(new Go_To(actualState, token, totalStates, kernel)); gotoState.Add(token, totalStates); //Verificar si es un terminal o un No Terminal if (grammar.isNotTerminal(token)) { previouStates.Add(new StatePointer(token, lookAheadNextItem, totalStates + 1, kernel.Production)); //Si es No terminal obtener todos los derivados //Obtener el first del elemento siguiente List <TokenType> firstNextItem = getFirstNextItem(kernel); //Obtener derivados List <LRItem> followUpItems = getFollowUpItems(token, firstNextItem, kernel.lookahead); foreach (var childItem in followUpItems) { List <TokenType> lookAheadNextChildItem = getLookaheadNextItem(getFirstNextItem(childItem), childItem.lookahead); //Verificar si se ha visto el simbolo anteriormente if (previouStates.Any(x => x.symbol == childItem.Production.RightSide[0] && x.isLookaheadEqual(lookAheadNextChildItem))) { var state = previouStates.Find(x => x.symbol == childItem.Production.RightSide[0] && x.isLookaheadEqual(lookAheadNextChildItem))?.state; if (state != null) { childItem.shiftTo = (int)state; } lrItems.Add(childItem); } else { int nextState; if (childItem.action == ActionType.Shift) { if (gotoState.ContainsKey(childItem.Production.RightSide[0])) { nextState = gotoState[childItem.Production.RightSide[0]]; } else { totalStates++; nextState = totalStates; gotoState.Add(childItem.Production.RightSide[0], nextState); } LRItem next = childItem.Copy(); next.Position++; nextStates.Add(new Go_To(actualState, next.Production.LeftSide, nextState, next)); if (grammar.isNotTerminal(next.Production.LeftSide)) { previouStates.Add(new StatePointer(next.Production.LeftSide, next.lookahead, nextState, next.Production)); } childItem.shiftTo = nextState; } lrItems.Add(childItem); } } } } } } actualState++; thisState.items = lrItems; this.States.Add(thisState); } }