Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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));
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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 + " )";
        }
Пример #9
0
        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);
        }
Пример #10
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";
            }
        }