public List <Produccion> dame_producciones_no_terminal(Produccion prod) { List <Produccion> p = new List <Produccion>(); foreach (Produccion aux_p in _producciones) { foreach (String s_aux in aux_p.RightItems) { string s = s_aux.Replace(prod.LeftItems[0] + "'", ""); if (s.Contains(prod.LeftItems[0])) { if (!s.Contains(prod.LeftItems[0] + "'")) { p.Add(aux_p); break; } } } } return(p); }
private string get_prod_tabla(Produccion p, string c) { string prod = ""; for (int i = 0; i < p.RightItems.Count; i++) { // si el primero es un terminal, devulve la producción que genera ese terminal if (Produccion.IsTerminal(p.RightItems[i][0])) { if (p.RightItems[i][0] == c[0]) { prod = p.RightItems[i]; break; } } else { string nt = "" + p.RightItems[i][0]; int index = 1; if (p.RightItems[i].Length > 1) { while (index < p.RightItems[i].Length && p.RightItems[i][index++] == '\'') { nt += "'"; } } prod = get_prod_tabla(get_produccion(nt), c); if (prod != "") { prod = p.RightItems[i]; } } } return(prod); }
public Produccion calcula_primero_produccion(Produccion prod) { string prod_str = ""; prod_str = prod.LeftItems[0] + " -> "; foreach (string item in prod.RightItems) { string first = dame_primero_de_item(item); // si el primer elemento del item derecho es terminal, se agrega a la producción if (Produccion.IsTerminal(first[0])) { prod_str += "" + item[0] + "|"; } else // si no busca el primero del no terminal en la lista de primeros. { // recorre la lista de los primeros foreach (Produccion p in _primero) { // Si existe el primero obtenido en la lista, asigna sus elementos a el // primero de este. if (p.LeftItems[0] == first) { foreach (string it in p.RightItems) { prod_str += it + "|"; } break; } } } } return(new Produccion(prod_str)); }
private string dame_primero_de_item(string item) { string primero = "" + item[0]; if (Produccion.IsNoTerminal(item[0])) { if (item.Length > 1) { for (int i = 1; i < item.Length; i++) { if (item[i] == '\'') { primero += "'"; } else { break; } } } } return(primero); }
public Produccion calcula_siguiente_produccion(Produccion prod) { string prod_str = ""; string left_str = prod.LeftItems[0] + " -> "; // Obtiene todas las producciones que contienen al no terminal izquierdo // de la produccion a calcular foreach (Produccion p_aux in dame_producciones_no_terminal(prod)) { // Recorre todos los elementos derechos de las producciones // para aplicar las reglas foreach (String it in p_aux.RightItems) { // si la produccion contiene al no terminal a evaluar... string item = it.Replace(prod.LeftItems[0] + "'", ""); if (item.Contains(prod.LeftItems[0])) { if (!item.Contains(prod.LeftItems[0] + "'")) { item = it; // checa la regla que se le aplica para obtener el sigueinte switch (checa_regla_siguiente(item, prod.LeftItems[0])) { case 1: int index = item.IndexOf(prod.LeftItems[0]); if (index < item.Length - 1) { index++; } while (index < item.Length && item[index] == '\'') { index++; } char sig = item[index]; // Si beta es un terminal lo agrega if (Produccion.IsTerminal(sig)) { if (!prod_str.Contains(sig)) { prod_str += "" + sig + "|"; } } else { // si beta es un no terminal obtiene el no terminal string nt = "" + item[index++]; while (index < item.Length && item[index++] == '\'') { nt += "'"; } // agrega los primeros del terminal obtenido a los // siguientes de la produccion actual foreach (String s in get_primeros(nt)) { // si el elemento no está en la lista y es difete de epsilon... if (s != "\u03B5" && !prod_str.Contains(s)) { prod_str += "" + s + "|"; } } if (get_primeros(nt).Contains("\u03B5")) { if (p_aux.LeftItems[0] != prod.LeftItems[0]) { foreach (String s in get_siguientes(p_aux.LeftItems[0])) { if (!prod_str.Contains(s)) { prod_str += "" + s + "|"; } } } } } break; case 2: if (p_aux.LeftItems[0] != prod.LeftItems[0]) { foreach (String s in get_siguientes(p_aux.LeftItems[0])) { if (!prod_str.Contains(s)) { prod_str += "" + s + "|"; } } } break; case 3: break; default: break; } } } } } if (is_inicial) { is_inicial = false; prod_str += "$"; } return(new Produccion(left_str + prod_str)); }
public List <Produccion> factoriza_produccion(Produccion p) { List <Produccion> nueva = new List <Produccion>(); String str_prod1 = p.LeftItemsStr + " -> "; String str_prod2 = p.LeftItemsStr + "' -> "; String prefijo; String prefijo_max = ""; int coincidencias_max = 0; int coincidencias; for (int i = 0; i < p.RightItems.Count; i++) { prefijo = ""; for (int k = 0; k < p.RightItems[i].Length; k++) { prefijo += "" + p.RightItems[i][k]; coincidencias = 0; for (int j = 0; j < p.RightItems.Count; j++) { // implementar otra función de busqueda del prefijo if (p.RightItems[j].Contains(prefijo)) { coincidencias++; } //************************************************* } if (coincidencias > 1 && prefijo.Length >= prefijo_max.Length) { if (prefijo.Length == prefijo_max.Length) { if (coincidencias > coincidencias_max) { prefijo_max = prefijo; coincidencias_max = coincidencias; } } else { prefijo_max = prefijo; coincidencias_max = coincidencias; } } } } // Si tiene un factor if (prefijo_max.Length > 0) { String str = ""; str_prod1 += prefijo_max + p.LeftItems[0] + "'|"; for (int i = 0; i < p.RightItems.Count; i++) { // implementar otra función de busqueda del prefijo if (p.RightItems[i].Contains(prefijo_max)) { //************************************************* str = p.RightItems[i].Remove(0, prefijo_max.Length); if (str == "") { str = "\u03B5"; } str_prod2 += str; if (i < p.RightItems.Count - 1) { str_prod2 += "|"; } } else { str_prod1 += p.RightItems[i]; if (i < p.RightItems.Count - 1) { str_prod1 += "|"; } } } if (str_prod1[str_prod1.Length - 1] == '|') { str_prod1 = str_prod1.Remove(str_prod1.Length - 1, 1); } if (str_prod2[str_prod2.Length - 1] == '|') { str_prod2 = str_prod2.Remove(str_prod2.Length - 1, 1); } nueva.Add(new Produccion(str_prod1)); nueva.Add(new Produccion(str_prod2)); } else // Si no tiene factorización devuelve la misma producción. { nueva.Add(p); } return(nueva); }
public List <Produccion> elimina_recursividad_directa(Produccion p) { List <Produccion> nueva = new List <Produccion>(); String str_prod1 = p.LeftItemsStr + " -> "; String str_prod2 = p.LeftItemsStr + "' -> "; Boolean tiene_recursividad = false; for (int i = 0; i < p.RightItems.Count; i++) { if (p.RightItems[i][0] == p.LeftItems[0][0]) { tiene_recursividad = true; str_prod2 += p.RightItems[i].Remove(0, 1) + p.LeftItemsStr + "'"; if (i < p.RightItems.Count - 1) { str_prod2 += "|"; } } else { if (p.RightItems[i] != "\u03B5") { str_prod1 += p.RightItems[i] + p.LeftItemsStr + "'"; } else { str_prod1 += p.LeftItemsStr + "'"; } if (i < p.RightItems.Count - 1) { str_prod1 += "|"; } } } // Si tiene recursividad if (tiene_recursividad) { // Crea la producción 1 nueva. if (str_prod1[str_prod1.Length - 1] == '|') { str_prod1 = str_prod1.Remove(str_prod1.Length - 1, 1); } nueva.Add(new Produccion(str_prod1)); // Crea la producción 2 nueva con un epsilon al final. if (str_prod2[str_prod2.Length - 1] == '|') { str_prod2 += "\u03B5"; } else { str_prod2 += "|\u03B5"; } nueva.Add(new Produccion(str_prod2)); } else // Si no tiene recursividad devuelve la misma producción. { nueva.Add(p); } return(nueva); }
private void _generate_formal_gram() { String n_t, s_t; for (int i = 0; i < _producciones[0].LeftItems.Count; i++) { _prod_inicial += _producciones[0].LeftItems[i]; } // Recorre todas las producciones en busca de terminales y no terminales for (int i = 0; i < _producciones.Count; i++) { // Busca terminales y no terminales del lado izquierdo for (int j = 0; j < _producciones[i].LeftItems.Count; j++) { // Si el item izquierdo es no terminal... if (Produccion.IsNoTerminal(_producciones[i].LeftItems[j][0])) { // Si no existe el item en la lista de no termilaes lo agerga if (!_no_terminales.Contains(_producciones[i].LeftItems[j][0])) { _no_terminales.Add(_producciones[i].LeftItems[j][0]); } } else// Si no, si el item es terminal { // Si no existe el item en la lista de terminales lo agerga. if (!_terminales.Contains(_producciones[i].LeftItems[j][0])) { _terminales.Add(_producciones[i].LeftItems[j][0]); } } } // Busca terminales y no terminales del lado derecho for (int j = 0; j < _producciones[i].RightItems.Count; j++) { // Si el item derecho es no terminal... for (int k = 0; k < _producciones[i].RightItems[j].Length; k++) { if (Produccion.IsNoTerminal(_producciones[i].RightItems[j][k])) { // Si no existe el item en la lista de no termilaes lo agerga if (!_no_terminales.Contains(_producciones[i].RightItems[j][k])) { _no_terminales.Add(_producciones[i].RightItems[j][k]); } } else// Si no, si el item es terminal { if (_producciones[i].RightItems[j][k] == '\'' && k > 0 && Produccion.IsNoTerminal(_producciones[i].RightItems[j][k - 1])) { break; } // Si no existe el item en la lista de terminales lo agerga. if (!_terminales.Contains(_producciones[i].RightItems[j][k])) { _terminales.Add(_producciones[i].RightItems[j][k]); } } } } } // Formatea los terminales y no terminales para generar la gramática formal n_t = ""; for (int i = 0; i < _no_terminales.Count; i++) { n_t += _no_terminales[i]; if (i < _no_terminales.Count - 1) { n_t += ", "; } } s_t = ""; for (int i = 0; i < _terminales.Count; i++) { s_t += _terminales[i]; if (i < _terminales.Count - 1) { s_t += ", "; } } _gram_formal = "G = ( { " + n_t + " }, { " + s_t + " }, " + _prod_inicial + " )"; }
private int evalua_cadena(Gramatica g, string entrada) { Stack <string> pila = new Stack <string>(); int line_number = 0; entrada += "$"; pila.Push("$"); pila.Push(g.Producciones[0].LeftItems[0]); tb_pila_in.Text = "" + line_number + ": " + entrada + "\r\n"; tb_pila_ev.Text = "" + line_number + ": " + "$" + g.Producciones[0].LeftItems[0] + "\r\n"; line_number++; while (entrada.Length != 0 && pila.Count != 0) { string tope = pila.Pop(); // si el elemento de la pila es terminal if (Produccion.IsTerminal(tope[0])) { // Si el elemento del tope es igual al de la entrada, continua // con el siguiente. if (tope == "$" && tope == "" + entrada[0]) { return(1); } if (tope[0] == entrada[0]) { entrada = entrada.Remove(0, 1); } else if (tope != "\u03B5") { return(0); } } else // si el tope es un no terminal { string element = busca_tabla_analisis(tope, "" + entrada[0]); if (element != "") { List <string> invertidos = genera_tokens(element); foreach (string s in invertidos) { pila.Push(s); } } else { return(0); } } // Guarda los datos de la iteración para mostrar la pila de evaluación string aux = ""; foreach (string s in pila) { aux = aux + s; } tb_pila_ev.Text += "" + line_number + ": " + aux + "\r\n"; tb_pila_in.Text += "" + line_number + ": " + entrada + "\r\n"; line_number++; } return(0); }
private void btn_analizar_Click(object sender, EventArgs e) { Gramatica.GRAM_ERROR err_code; gram = new Gramatica(); String[] lines = tb_gramatica.Lines; tb_recursiva.Text = ""; tb_factorizada.Text = ""; tb_primero.Text = ""; tb_siguiente.Text = ""; // Si hay lineas que analizar... if (lines.Length != 0) { // Analiza las lineas de la gramatica y devielve el error. err_code = gram.AnalizaLineas(lines); // Si no hay errores if (err_code == Gramatica.GRAM_ERROR.NO_ERROR) { // Si el tipo de gramatica no es regular o libre de contexto muestra error if (gram.Type != Gramatica.TIPO_GRAMATICA.LIBRE_DE_CONTEXTO && gram.Type != Gramatica.TIPO_GRAMATICA.REGULAR) { tb_msg.Text = "Error, la gramática no es libre de contexto"; return; } // Elimina la recursividad por la izquierda gram.elimina_recursividad(); foreach (Produccion prod in gram.Producciones) { tb_recursiva.Text += prod.Value + "\r\n"; } // Factoriza la gramática gram.factoriza(); foreach (Produccion prod in gram.Producciones) { tb_factorizada.Text += prod.Value + "\r\n"; } // Calcula el primero de la gramática gram.calcula_primero(); for (int i = 0; i < gram.Primero.Count; i++) { Produccion prod = gram.Primero[i]; if (prod.LeftItems[0].Length > 1) { tb_primero.Text += "P(" + prod.LeftItems[0] + ")" + " = { "; } else { tb_primero.Text += "P(" + prod.LeftItems[0] + ")" + " = { "; } for (int j = 0; j < prod.RightItems.Count; j++) { tb_primero.Text += prod.RightItems[j]; if (j < prod.RightItems.Count - 1) { tb_primero.Text += " , "; } } tb_primero.Text += " }\r\n"; } gram.calcula_siguiente(); for (int i = 0; i < gram.Siguiente.Count; i++) { Produccion prod = gram.Siguiente[i]; if (prod.LeftItems[0].Length > 1) { tb_siguiente.Text += "S(" + prod.LeftItems[0] + ")" + " = { "; } else { tb_siguiente.Text += "S(" + prod.LeftItems[0] + ")" + " = { "; } for (int j = 0; j < prod.RightItems.Count; j++) { tb_siguiente.Text += prod.RightItems[j]; if (j < prod.RightItems.Count - 1) { tb_siguiente.Text += " , "; } } tb_siguiente.Text += " }\r\n"; } gram.genera_tabla_analisis(); muestra_tabla_analisis(gram); tb_recursiva.Text = tb_recursiva.Text.Replace("|", " | "); tb_recursiva.Text = tb_recursiva.Text.Replace("->", " -> "); tb_factorizada.Text = tb_factorizada.Text.Replace("|", " | "); tb_factorizada.Text = tb_factorizada.Text.Replace("->", " -> "); } else // Si hay errores... { // Si el error es de gramatica vacía, muestra error de gramática vacía if (err_code == Gramatica.GRAM_ERROR.EMPTY_GRAM) { tb_msg.Text = "Gramática vacia, no hay gramática a evaluar"; } else // si no es error de gramática vacia, muestra mensaje de error en la gramática. { tb_msg.Text = "Error en la gramática."; } } } else // Si no hay lineas que analizar, muestra error de gramática vacía. { tb_msg.Text = "Gramática vacia, no hay gramática a evaluar"; } }