7.diseÑo de un entorno para el analizador cyklorien.die.upm.es/juancho/pfcs/dpf/capitulo7.pdf ·...

23
Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 127 7. DISEÑO DE UN ENTORNO PARA EL ANALIZADOR CYK 7.1 PRESENTACIÓN El antiguo analizador CYK del GTH, estaba desarrollado en entorno MS-DOS. Aprovechando las oportunidades gráficas de Windows, se decidió integrar este sistema con su nueva funcionalidad, en un entorno gráfico de ventanas, el cual, sería más atractivo de cara al usuario, así como también, más manejable. El nuevo entorno, nos permite manejar el analizador mediante menús y ventanas del mismo tipo que cualquier programa que esté diseñado en entorno Windows. Una de las grandes ventajas que nos proporcionará el entorno gráfico, será a la hora de presentar por pantalla los árboles sintácticos. Éstos, podrán ser recorridos a lo largo y ancho por medio de las barras de "scroll", maximizarlos, minimizarlos, tener varios abiertos a la vez, lo cual nos puede permitir hacer cierto tipo de comparaciones entre árboles... Al ejecutar el programa que analizará textos automáticamente, aparecerá una ventana principal con las mismas características que cualquier ventana de cualquier programa bajo entorno Windows, es decir, con su título y su menú de opciones. Según se escoja una u otra opción del menú, aparecerán unas ventanas u otras según requiera el proceso demandado, pero todas las opciones del menú, así como las diferentes ventanas que se sucederán según la acción requerida, se explicarán en los siguientes apartados. El título de la ventana principal, será "sintax v.2.0". Se le puso ese nombre debido a que este analizador, será la segunda versión del "sintax" del GTH. 7.2 GENERACIÓN DEL ENTORNO Ya se ha comentado, que el sistema de análisis automático, se ha integrado en un entorno de ventanas que facilite el uso y la comprensión del mismo, así como que sea más atractivo en su manejo. Para que sea posible configurar las ventanas, las cuales mantendrán un diálogo constante con el usuario del sistema durante el empleo del mismo, de modo que actúen de la forma que nosotros consideremos, es necesario,

Upload: truongphuc

Post on 21-Oct-2018

223 views

Category:

Documents


0 download

TRANSCRIPT

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 127

7. DISEÑO DE UN ENTORNO PARA

EL ANALIZADOR CYK

7.1 PRESENTACIÓN

El antiguo analizador CYK del GTH, estaba desarrollado en entorno MS-DOS.Aprovechando las oportunidades gráficas de Windows, se decidió integrar este sistemacon su nueva funcionalidad, en un entorno gráfico de ventanas, el cual, sería másatractivo de cara al usuario, así como también, más manejable.

El nuevo entorno, nos permite manejar el analizador mediante menús y ventanasdel mismo tipo que cualquier programa que esté diseñado en entorno Windows. Una delas grandes ventajas que nos proporcionará el entorno gráfico, será a la hora depresentar por pantalla los árboles sintácticos. Éstos, podrán ser recorridos a lo largo yancho por medio de las barras de "scroll", maximizarlos, minimizarlos, tener variosabiertos a la vez, lo cual nos puede permitir hacer cierto tipo de comparaciones entreárboles...

Al ejecutar el programa que analizará textos automáticamente, aparecerá unaventana principal con las mismas características que cualquier ventana de cualquierprograma bajo entorno Windows, es decir, con su título y su menú de opciones. Segúnse escoja una u otra opción del menú, aparecerán unas ventanas u otras según requiera elproceso demandado, pero todas las opciones del menú, así como las diferentes ventanasque se sucederán según la acción requerida, se explicarán en los siguientes apartados.

El título de la ventana principal, será "sintax v.2.0". Se le puso ese nombredebido a que este analizador, será la segunda versión del "sintax" del GTH.

7.2 GENERACIÓN DEL ENTORNO

Ya se ha comentado, que el sistema de análisis automático, se ha integrado en unentorno de ventanas que facilite el uso y la comprensión del mismo, así como que seamás atractivo en su manejo. Para que sea posible configurar las ventanas, las cualesmantendrán un diálogo constante con el usuario del sistema durante el empleo delmismo, de modo que actúen de la forma que nosotros consideremos, es necesario,

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 128

generar un proyecto que utilice Object Windows como interfaz entre el programa y laAPI de Windows.

Para crear esta clase de proyecto se han de seguir los siguientes pasos: esnecesario seleccionar sucesivamente, las siguientes opciones: primero ir al menú "File",y dentro de éste, acceder al submenú "New"; finalmente, seleccionar la opción"AppExpert..." (ver ilustración 7.1).

Una vez hecho esto, se nos dará una serie de posibilidades para configurarnuestro proyecto. Inicialmente, habrá datos por defecto, estos podrán ser cambiados agusto del programador, aunque generalmente se dejan los que están. Las opciones deconfiguración, serán:

• Configuración de la aplicación.• Configuración de la ventana principal y las ventanas clientes.

7.2.1 Configuración de la aplicación

En este apartado, se nos pedirá que confirmemos o cambiemos (según nuestrocriterio), una serie de datos que conciernen a la aplicación.

Ilustración 7.1. Menú para la generación de un proyecto bajo entorno Object Windows.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 129

Estos datos que hay que rellenar obligatoriamente, antes de generar el proyectoserán:

• Opciones básicas: El nombre que identificará el proyecto y el directoriodonde se guardará entre otras. En nuestro caso, el nombre del proyecto es"arbol".

• Opciones de control del código generado: Nombre de los principalesarchivos fuente y cabecera (ArbolApp.cpp y ArbolApp.h en nuestroproyecto). Cuando se ejecute el programa, lo primero que hará ObjectWindows, será llamar al programa principal de "ArbolApp.cpp" (aquelmarcado por el nombre "OwlMain").

También se nos pedirá el nombre de las clases principales que gestionarán laventana principal (clase TApplication) y los cuadros de diálogo (claseTAboutDialog). Los nombres de estas clases que aparecen por defecto, seránun híbrido entre el nombre de la clase y el del proyecto, por ejemplo, ennuestro caso, la clase que gestionará la ventana principal (TApplication), sellamará "TArbolApp". En el programa principal de "ArbolApp.cpp", secreará un objeto del tipo "TApplication" correspondiente y se llamará almétodo "run" del mismo, el cual provocará la generación de la ventanaprincipal, la cual tendrá el menú que nosotros hayamos diseñado para ella através del archivo "ArbolApp.rc" que luego trataremos.

• Datos administrativos: Por último, se nos pedirá el nombre del autor y el dela compañía que van a desarrollar ese proyecto; en este caso no habrá ningúnvalor por defecto.

En la ilustración 7.2, se muestra, como ejemplo, el cuadro donde se nos pideconfirmación acerca de los nombres de las clases y de los ficheros fuente y cabecera.

7.2.2 Configuración de ventanas

Sobre la configuración de la ventana principal se nos pedirán, además del títulode la misma, los siguientes datos:

• Opciones básicas: Serán opciones acerca del estilo con el que la ventanaaparecerá. Son del tipo de si se quiere la ventana principal con las barras de"scroll" horizontal y vertical y otros datos de la misma clase.

• Definición de las clases relacionadas con la ventana principal: La ventanaprincipal, será la identificada en el cuadro de configuración de ventanas(ilustración 7.3), como SDI Client si se ha escogido en la configuración dela aplicación un modelo de ventanas SDI (Single Document Interface), y serála identificada como MDI Client , si se seleccionó el tipo MDI (MultipleDocument Interface) como modelo de ventanas.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 130

En nuestro caso, se ha escogido un modelo MDI, con lo cual accedemos a laopción MDI Client de la sección de configuración de la ventana principal, yahí, rellenamos los nombres que nos piden que son: nombre de la clase quegestiona este tipo de ventanas, y los nombres de los ficheros cabecera yfuente donde estarán definidos los métodos y los elementos que componendicha clase (también se pueden dejar los que están por defecto. Verilustración 7.3).

• Definición de las clases relacionadas con la ventana de diálogo: En la mismasección, se nos pedirá que asignemos un nombre a la clase y a los ficherosfuente y cabecera relacionados con la ventana de diálogo por defecto.

• Definición de las clases relacionadas con las ventanas hijas: En la últimasección de configuración del proyecto "AppExpert", se nos pedirá, como enlas secciones anteriores, que pongamos los nombres de la clase, ficherofuente y fichero cabecera que van a definir el comportamiento de lasventanas hijas de la ventana principal.

Dentro de este apartado, también se nos ofrecerá la posibilidad de queelijamos de qué forma queremos, que se presente los documentos en nuestrapantalla (casilla MDI client/view class). Tendremos cuatro opciones:TEditView (se verá como cualquier archivo de texto), TListView, TOleView

Ilustración 7.2. Opciones de configuración de la generación del código.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 131

y TWindowView. Para conseguir nuestro objetivo, de presentar árbolessintácticos, elegiremos esta última. Según cambiemos de un tipo de esoscuatro a otro, los nombres de la clase, el fichero fuente y cabecera que haypor defecto, también cambiará, ya que esos nombres serán una mezcla entreel nombre del proyecto y el del tipo de presentación de los documentos (ennuestro caso, al elegir "TwindowView", el nombre de la clase por defecto es"TarbolWindowView"). En la ilustración 7.4, se muestra la pantalla donde serealiza esta configuración.

Por último, decir, que la clase de documento siempre será "TfileDocument". Másadelante, se explicará qué métodos de la clase "TWindowView" hay que tocar paraconseguir presentar los documentos del modo que sea necesario.

Una vez se han rellenado todos los datos pertinentes, y se han cambiado anuestro gusto todos los nombres de clases y ficheros, se pulsará a la tecla "Generate", yse generará el proyecto con todos los ficheros que gestionan el comportamiento de lasventanas.

Nuestro analizador, se integrará a este nuevo proyecto con herramientas ObjectWindows, sin más que añadir los archivos con nuestros procesos al proyecto generadode la forma que se ha descrito.

Ilustración 7.3. Configuración de la ventana principal.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 132

7.3 CLASE TWINDOWVIEW

La clase principal de un proyecto de estas características, será aquella quegestiona la ventana principal del programa; ésta será "TApplication". Cuando se ejecuteel proyecto, se irá al programa principal, que se encuentra en "ArbolApp.cpp" señaladocon la etiqueta "OwlMain", éste creará un objeto de la clase "TApplication", y llamaráal método "run" del mismo. La ejecución de ese método, provocará la aparición enpantalla de la ventana principal que gestionará el analizador.

La clase "TWindowView", definirá, como ya hemos dicho, el tipo de ventanahija que vamos a necesitar. La clase que gestione ese tipo de ventanas, será, comotambién se ha mencionado anteriormente "TArbolWindowView". Esta clase, entrará enjuego cuando se pretenda abrir un documento mediante el procedimiento clásico deseleccionar dentro del menú "File", el submenú "Open". Habiendo procedido de estaforma, se presentará por pantalla un cuadro de diálogo que nos mostrará los posiblesarchivos que se podrían abrir (esta opción la puede configurar el programador en elarchivo "ArbolApp.cpp"). Una vez hayamos elegido uno, se llamará al constructor de laclase "TWindowView" pasándole como parámetro el nombre del archivo, entonces, seacudirá a un método de esta clase que se llama "Paint", el cual presentará por pantalla elarchivo, de la forma que hayamos diseñado. Por tanto, para que un fichero cualquiera,

Ilustración 7.4. Configuración de la presentación de los documentos en ventanas hijas.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 133

salga por pantalla de la forma que nosotros queramos, habrá que reescribir el método"Paint" de "TArbolWindowView".

Dentro del método "Paint", podremos definir entonces, cómo presentar porpantalla un determinado tipo de archivo. Por ejemplo, nuestro analizador ha sidoprogramado, para que leyendo los archivos escritos en formato de paréntesisetiquetados, los presente como árboles sintácticos.

En el cuadro 7.1, se pueden observar los componentes de la clase"TArbolWindowView".

Se observa, que esta clase, heredará de las clases "TArbolSintactico" (que esaquella que transformará los paréntesis etiquetados en árboles sintácticos y losalmacenará en memoria dispuestos a ser presentados por pantalla) y "TWindowView"(tipo que define la clase de las ventanas donde se hará la mencionada presentación).

Entre sus componentes, contará con un constructor (TArbolWindowView) y undestructor (~TArbolWindowView), como todas las clases declaradas en cualquierlenguaje orientado a objetos. El constructor recibirá como parámetros el nombre delarchivo que se ha seleccionado para abrir, y la ventana padre, que será la ventanaprincipal. Tendrá el método "Paint", que ya hemos descrito. También tiene un métodopara construir la ventana (SetupWindow); aquí se pueden definir aspectos del estilo dela ventana, como por ejemplo, el tipo de letra con el que se escribirá dentro de la misma.Por último, contiene una serie de componentes relacionados con la tabla de respuestasde la ventana, pero que no vienen al caso en estos momentos.

class TArbolWindowView : public TArbolSintactico, public TWindowView { public: TArbolWindowView(TDocument& doc, TWindow* parent = 0); virtual ~TArbolWindowView();

//{{TArbolWindowViewVIRTUAL_BEGIN}} public: virtual void Paint(TDC& dc, bool erase, TRect& rect);

virtual void TArbolWindowView::SetupWindow(); //{{TArbolWindowViewVIRTUAL_END}}

//{{TArbolWindowViewRSP_TBL_BEGIN}} protected: void EvGetMinMaxInfo(MINMAXINFO far& minmaxinfo); //{{TArbolWindowViewRSP_TBL_END}}

DECLARE_RESPONSE_TABLE(TArbolWindowView);}; //{{TArbolWindowView}}

Cuadro 7.1. Clase TArbolWindowView.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 134

7.4 MENÚ PRINCIPAL

Este es el menú que aparece en la ventana inicial del programa (ver ilustraciónnúmero 7.5). Las posibilidades que ofrece, son las típicas de cualquier otro menú de unprograma diseñado bajo entorno Windows, sumándole a éstas, claro está, aquellas queharán posible desarrollar las acciones que realiza el analizador CYK.

El menú principal, permitirá optar entre las siguientes posibilidades:

• File.• Edit.• Search.• Window.• Categorizador.• Analizador.• Help.

De estas opciones, sólo cabe destacar tres de ellas, ya que las otras son lascomunes que aparecen en cualquier programa en entorno Windows, y desempeñarán lamisma función en todos y cada uno de ellos. Me estoy refiriendo a: Edit (con lasopciones de deshacer el último cambio, cortar, pegar, copiar y borrar), Search (quepermitirá buscar dentro del archivo de la pantalla activa, así como reemplazar texto),Window (modo de presentación de ventanas) y Help (ayuda del programa). Estasfunciones se pueden adaptar a nuestras necesidades reprogramando las funciones a lascuales llaman (métodos de "TApplication", clase que gestiona la ventana principal y por

Ilustración 7.5. Ventana principal del analizador.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 135

tanto también su menú) dentro del archivo "ArbolApp.cpp", pero no se ha hecho en estaocasión.

Son las otras tres opciones del menú (File, Categorizador y Analizador), las quehemos adaptado a lo que se quería para nuestro analizador CYK. En realidad, se haadaptado sólo, la opción "File", ya que "Analizador", más que adaptarse, se ha integradoen el entorno Object Windows. En los siguientes apartados, se van a describir lasposibilidades de estas opciones del menú.

7.4.1 File

Permite realizar todo tipo de acciones con los archivos: crear, abrir, cerrar,salvar, imprimir y enviar ficheros de texto o en formato de paréntesis etiquetados(extensión .ETQ), así como salirse del programa (opciones típicas de cualquierprograma bajo Windows). También proporcionará acceso directo a los cuatro últimosarchivos que fueron abiertos.

Al seleccionar la opción "Open", se nos mostrará por pantalla un cuadro dediálogo, que nos dará la posibilidad de escoger qué fichero queremos abrir. Tendremosla opción de elegir entre archivos de texto (extensión .TXT) o archivos con cadenas deparéntesis etiquetados (extensión .ETQ). En la ilustración 7.6, se puede observar elcuadro de diálogo mencionado.

Ilustración 7.6. Cuadro de diálogo de "Open File".

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 136

Lo particular de la opción "File", es que los archivos que tengan extensión .ETQ,es decir, aquellos que tengan guardados análisis de frases en formato de paréntesisetiquetados, saldrán por pantalla, representados como árboles sintácticos. Los archivosde texto (extensión .TXT), saldrán escritos como si nuestro analizador fuera unprocesador de texto normal y corriente, con la salvedad de que el tamaño y el tipo deletra, están establecidos de antemano y no se podrán cambiar, a menos que se acceda alcódigo del método "Paint".

Para llegar a la presentación por pantalla de un árbol sintáctico, se deberáprimero, crear ese árbol a partir de los paréntesis etiquetados, para ello, se utilizará laclase "TArbolSintactico", a cuyo constructor se llamará, pasándole como parámetro elnombre del fichero que contiene la cadena de paréntesis etiquetados, desde elconstructor de la ventana dentro de la cual se mostrará dicho árbol.

7.4.1.1 La clase TArbolSintactico

Tendrá una serie de métodos que se llamarán para construir un árbol sintáctico apartir de un fichero de paréntesis etiquetados. Se puede observar el conjunto deelementos que forman parte de la clase "TArbolSintactico" en el cuadro 7.3. Lasestructuras "Tnodo", "TEstadisticas" y "TPosicion" están definidas en el cuadro 7.2.

#define MAX_DATO 30

typedef struct {

int x; int y;

} Tposicion;typedef struct Tnodo {

char dato[MAX_DATO]; //Símbolo que forma el nodo int nivel; //Nivel del árbol sintáctico en el que se encuentra int anchura; //Anchura del símbolo mas la de los hermanos de su derecha Tposicion posicion; //Posición que ocupa el nodo en el array de dos dimensiones struct Tnodo *ppadre; //Puntero al padre struct Tnodo *phijo; //Puntero al hijo struct Tnodo *phermanosig; //Puntero al hermano de su derecha struct Tnodo *phermanoant; //Puntero al hermano de su izquierda

} Tnodo;typedef struct {

char dato[MAX_DATO]; int cont;

} Testadisticas;

Cuadro 7.2. Estructuras definidas para la clase TArbolSintactico.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 137

Hay que decir, que un puntero al padre, solamente lo tendrá el "hijo" situado mása la izquierda. Los demás tendrán un puntero al "hermano" de su izquierda(phermanoant) y al de su derecha (phermanosig).

Los métodos más importantes de esta clase serán "CreaArbol", el cual construiráel árbol sintáctico y lo guardará en memoria, y "EscribeEnArray", al cual se le pasarácomo parámetro el árbol sintáctico, y guardará sus elementos (nombre de los símbolosterminales y no terminales que componen el árbol) en un array de dos dimensiones(ARRAY2D), para que después su escritura en la ventana sea más sencilla.

El nodo principal del árbol sintáctico, será el axioma. El árbol estará formadopor nodos, y dividido en niveles. El nivel del axioma será el nivel uno, y según vayasubiendo el número que identifica el nivel, será menor el contenido sintáctico de losnodos que lo componen, por tanto, el nodo con mayor contenido sintáctico será elaxioma, es decir, la oración completa, y será el único que componga el nivel uno delárbol sintáctico.

Todos los nodos que compongan el nivel dos del árbol, serán "hijos" del axioma,y la relación entre ellos, será de "hermanos". Éstos, a su vez, también tendrán "hijos",pero no todos los que compongan el nivel tres del árbol, serán "hijos" de todos los queforman el nivel dos, sino sólo de alguno de ellos. Se puede observar la estructura de unárbol sintáctico, en el cuadro 7.4. En este cuadro, se observa, que "Nodo21", "Nodo22"y "Nodo23", son "hijos" del axioma y "hermanos" entre sí; sólo "Nodo2" ("hermano"más a la izquierda) tendrá un puntero al padre (axioma). "Nodo31" y "Nodo32" sonhermanos entre sí, e "hijos" de "Nodo21". "Nodo22" tendrá a su vez tres "hijos", queserán "Nodo33", "Nodo34" y "Nodo35", los cuales guardarán una relación de"hermanos" entre ellos. Por último, "Nodo23" sólo tendrá un hijo: "Nodo36", el cual notiene "hermanos". También observamos, que es un árbol con "N" niveles y la frase a laque describe, está compuesta por "M" palabras.

Nivel 1 Axioma

Nivel 2 Nodo21 Nodo22 Nodo23

Nivel 3 Nodo31 Nodo32 Nodo33 Nodo34 Nodo35 Nodo36

. . .

Nodo N NodoN1 . . . NodoNM

Cuadro 7.4. Ejemplo de la estructura de un de árbol sintáctico.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 138

Para entenderlo mejor, veamos un ejemplo: recordemos la construcción de reglasgramaticales, que tenían el siguiente formato:

SintagmaNominal = Determinante NombreSintagmaVerbal = Verbo

class TArbolSintactico {protected:

//Datos miembro de TArbolSintactico. char NombreFichero[MAXPATH]; // Nombre del fichero .ETQ char PathFichero[MAXPATH]; // path del fichero .ETQ

char *CodigoEntrada; // Código de paréntesis etiquetados Tnodo *ARBOL; // Arbol sintáctico Testadisticas *TablaEstadisticas; // Tabla con estadísticas TPuntero2D ESTRUCTURA2D; // Estructura con array de dos dimensiones

char **ARRAY2D; // Array de dos dimensiones

public: //Declaración del constructor y destructor de mi clase TArbolSintactico. TArbolSintactico (const char *NomFich); ~TArbolSintactico ();

//Métodos miembro de mi clase TArbolSintactico. void LeerFichEntrada(void); void Filtro(char *linea);

void CreaArbol(int NivelMaximo); void CreaTabla(); void MostrarEstadisticas(); int CompruebaDato(char *data); int CompruebaDicc(char *data); void RecorreNodos(Tnodo *NODO); void PosicionNodos(Tnodo *NODO); int CalculaAnchura(Tnodo *NODO); int CalculaNivel(Tnodo *NODO); Tposicion CalculaPosicion(Tnodo *NODO); int CalculaNumFilas(Tnodo *NODO); void EscribeEnArray(Tnodo *NODO); int CalculaNumElementos(); void DameProfileInt(const char *NombFich, const char *Seccion, const char Parametro, int Defecto, int *Destino);

void FreeArbolSintactico(Tnodo *NODO); void DaFormatoAFichero(FILE *fp1, FILE *fp2, int *FinFichero);};

Cuadro 7.3. Clase TArbolSintactico.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 139

Pues una oración formada por un sintagma nominal y un sintagma verbal, ambosde las anteriores características: Oracion = SintagmaNominal SintagmaVerbal daríalugar a un árbol como el expuesto en el cuadro 7.5.

La composición del árbol sintáctico será la siguiente:

Nivel 1: Oración.Nivel 2: SintagmaNominal SintagmaVerbal.Nivel 3: Determinante Nombre Verbo

SintagmaNominal y SintagmaVerbal son "hermanos" entre ellos, e "hijos" deOracion. Por otra parte, Determinante y Nombre serán "hermanos", y además "hijos" deSintagmaNominal pero no de SintagmaVerbal. De éste, será "hijo" el símbolo Verboque no tendrá "hermanos".

Ahora, sólo nos queda crear un algoritmo de transformación de paréntesisetiquetados a árboles sintácticos. Ese algoritmo, se encuentra en el cuadro 7.6 escrito enpseudocódigo.

Los paréntesis etiquetados, se pasarán a este algoritmo, en una cadena donde sehabrán quitado todos los retornos de carro y los espacios en blanco, excepto aquellosque separen dos símbolos o dos palabras. Por tanto, los caracteres claves para eldesarrollo del algoritmo de conversión, serán los corchetes y los espacios que separansímbolos o palabras. Se irá contando el número de corchetes abiertos (diferencia entrelos corchetes que se abren ([), y los que se cierran (])), por tanto al final de la cadena deparéntesis etiquetados, esta diferencia debe ser cero, si no, tendremos una cadena deparéntesis errónea y se devolverá un mensaje de error. El nivel del árbol sintáctico, dedonde haya que colgar un nuevo nodo, estará determinado por la diferencia entrecorchetes abiertos y cerrados que se tenga en el momento que nos llega un nuevosímbolo, mas uno. Cada vez que se abra un corchete, se subirá un nivel, y cada vez quese cierre se bajará. De igual forma, cuando se abra un corchete, se enganchará al nodoque forma el símbolo que precede a dicho corchete un "hijo", y si es un espacio, se leenganchará un "hermano". Por otro lado, cada vez que se cierre un corchete, como yahemos dicho, se bajará un nivel, por lo que, un símbolo que siga al cierre de uncorchete, se enganchará al último hermano del nivel en que nos encontremos en esemomento.

Se seguirá este proceso, hasta que la diferencia a la que hemos hecho referencia,sea cero, momento en el cual nos saldremos de la función que crea el árbol sintáctico.

Oracion

SintagmaNominal SintagmaVerbal

Determinante Nombre Verbo

Cuadro 7.5. Ejemplo de construcción de árbol sintáctico.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 140

Una vez se tenga la estructura del árbol sintáctico, se calcularán anchuras y

int ContadorCorchetes := 0; //Diferencia corchetes abiertos y cerrados. Me indica el nivelchar Parentesis[MAXLONG]; //Código de paréntesis etiquetadosTnodo *NodoActual; //Último nodo instalado en el árbol

beginQuitaEspaciosRetorno(Parentesis);

NodoActual := InstaloAxioma(); //El axioma es lo que va al principiofor (i := 1; i <= strlen(Parentesis); i++) //Recorro la cadena de paréntesis etiquetados a partir del axioma (i := 1)begin

if (Parentesis[i] == '[')begin

ContadorCorchetes ++;LeeSimbolo();CuelgaHijo(NodoActual);NodoActual := NodoActual -> phijo; //Actualizo el nodo actual

endelse if (Parentesis[i] == ' ')begin

LeeSimbolo();CuelgaHermano(NodoActual);NodoActual := NodoActual -> phermanosig; //Actualizo el nodo actual

endelse if (Parentesis[i] == ']')begin

ContadorCorchetes --;while (NodoActual -> ppadre == NULL) //Actualizo el nodo actual

NodoActual := NodoActual -> phermanoant; //Solo el primer hermano tiene un //puntero al padre

NodoActual := NodoActual -> ppadre;while (Parentesis [++i] == ']') //Puede que se cierren varios corchetes seguidosbegin

ContadorCorchetes --;while (NodoActual -> ppadre == NULL)

NodoActual := NodoActual -> phermanoant;

NodoActual := NodoActual -> ppadre;endif (ContadorCorchetes != 0)begin

LeeSimbolo();CuelgaHermano(NodoActual);NodoActual := NodoActual -> phermanosig;

endelse //Llegamos al final de la cadena

break;end

end

Cuadro 7.6. Algoritmo para la construcción del árbol sintáctico a partir de los paréntesis etiquetados.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 141

posiciones de los nodos en el array (ARRAY2D), lo que a la postre, será su posición enla pantalla ya que el proceso "Paint" de "TArbolWindowView", se limitirá a presentardicho array por pantalla.

La posición y la anchura, se calculan a posteriori, debido a que el árbolsintáctico se construye de izquierda a derecha, y para calcular la anchura de un nodo,como se expone en el cuadro 7.2, se necesita conocer la anchura de todos los nodos queestán a su derecha, por lo que cada vez que se crea uno nuevo, no conocemos lo que estáa su derecha y por tanto no podemos calcular la anchura. Con la posición tendremos elmismo problema, ya que ésta se calcula a partir de la anchura.

Una vez que tenemos todos los datos de cada uno de los nodos que componen elárbol, se reservará memoria para 'ARRAY2D', se rellenará dicho array y se guardará,dispuesto a ser mostrado por pantalla.

Todo este proceso, se realizará en el constructor de "TArbolSintactico" el cualfue llamado como ya se ha dicho antes, por el constructor de "TArbolWindowView".

Para entenderlo mejor, vamos a desarrollar un ejemplo en el quetransformaremos una cadena de paréntesis etiquetados, en un árbol sintáctico. La fraseque se va a tratar, será: "La casa es muy grande". Es un frase muy simple, pero que nosservirá para ilustrar el proceso de transformación que estamos describiendo. El códigode paréntesis etiquetados que se generó es el siguiente:

O[SN[DET[La]Sust[casa]]VERBO[VerboSer[es]]SAdj[AdverMuy[muy]Adj[grande]]]

Lo primero que se hará, siguiendo el algoritmo del cuadro 7.6, será sacar elaxioma (O) y crear el primer nodo del árbol. Este primer nodo estará en el nivel 1(diferencia entre corchetes abiertos y cerrados + 1).

Nos llega un corchete que se abre, entonces subimos un nivel (nivel 2), leemosel símbolo (SN) y lo colgamos del axioma como "hijo". Se lee otro corchete que se abre,volvemos a subir un nivel en el árbol sintáctico (nivel 3), se lee el nuevo símbolo,terminal en este caso (DET), y se cuelga del último nodo creado (SN) como "hijo".Llegamos al nivel 4, debido a la entrada de un nuevo corchete que se abre, obtenemosun nuevo símbolo (la palabra "La"), y de nuevo, se añade al árbol el nodocorrespondiente, que será "hijo" de "DET".

Ahora, se cierra un corchete y sólo uno, por tanto bajamos al nivel 3 y añadimosal último nodo creado para ese nivel (DET), un "hermano", una vez hayamos leído elsímbolo correspondiente (Sust). Con la llegada de un nuevo corchete que se abre,pasamos al nivel 4, colgando un nodo "hijo" al símbolo "Sust". En este instante,llegamos a dos corchetes consecutivos que se cierran, por lo que bajamos dos niveles(nivel 2), leemos el nuevo símbolo (VERBO), y lo colgamos como "hermano" delúltimo nodo instalado en ese nivel, que si recordamos, fue el símbolo no terminal "SN".Así, procederemos hasta que la diferencia entre corchetes abiertos y cerrados sea cero, olo que es lo mismo, hasta que volvamos al nivel 1 donde se encuentra el axioma. En elcuadro 7.7, se puede observar un esquema del proceso completo, según llegan corchetesque se abren ([), o corchetes que se cierran (]).

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 142

Las flechas del cuadro indican los cambios de nivel, según llegan los dosdiferentes tipos de corchetes.

Cuando el árbol esté construido completamente, se calcularán, como yasabemos, anchura y posición de cada nodo y se rellenará el array de dos dimensiones(ARRAY2D), el cual quedará como se expone en la tabla 7.1.

O_ _ _ _ _ _ _ _ _ _ _ _ _ | _ _ _ _ _ _ _ _ _ _

/ | \S N V E R B O S A d j

_ _ _ | _ _ | _ _ _ _ | _ _ _/ \ | / \

D E T S u s t V e r b o S e r A d v e r b M u y A d j| | | | || | | | |

" L a " " c a s a " " e s " " m u y " " g r a n d e "

Hay que decir, que a las palabras que forman la frase se las entrecomilla paradiferenciar el texto de lo que es el análisis propiamente dicho. En este punto, ya estátodo preparado para mostrar por pantalla el árbol correspondiente a este análisissintáctico. En la ilustración 7.7, podemos observar el resultado de abrir un fichero("minimizado.ETQ" en este caso, aunque el nombre puede ser cualquiera) que tenga lacadena de paréntesis etiquetados del ejemplo que se ha propuesto.

Cuadro 7.7. Ejemplo de construcción de árbol sintáctico.

O [ ]

SN VERBO SAdj [ [ [ ] ] ]

DET Sust VerboSer AdverbMuy Adj [ [ [ [ [ ] ] ] ] ]

La casa es muy grande

Tabla 7.1. Aspecto de ARRAY2D.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 143

7.4.2 Categorizador

Una vez integrado en el entorno el sistema de análisis completo, se decidióacoplar también, el sistema de preprocesamiento y categorización gramatical descrito enJiménez[99].

La ejecución de este nuevo sistema integrado, se dispara al elegir el menú"Categorizador" y seleccionar la única opción que se mostrará al desplegarse; estaopción lleva el nombre "Run".

7.4.3 Analizador

Esta será la opción del menú que más nos interese, ya que es la que llamará a losprocesos que van a realizar la labor de análisis de un texto.

La opción "Analizador" del menú, nos ofrece las siguientes posibilidades:

• Cargar gramática.• Cargar gramática de alto nivel.• Análisis sintagmático.• Análisis sintáctico.• Analiza.

Ilustración 7.7. Presentación por pantalla de un árbol sintáctico.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 144

• Pintar árbol.

Aunque ya se conocen las funciones las funciones a las cuales se accederá pormedio de estas posibilidades (ver capítulo 6, sobre la nueva funcionalidad delanalizador), a continuación se describirán los pasos que hay que seguir para llegar a laejecución de esos procesos.

7.4.3.1 Cargar gramática

Una vez tenemos una gramática compilada, es necesario cargarla en memoria, demodo que esos archivos generados en el proceso de compilación, estén a disposición delanalizador a través de una serie de variables a las que accederá durante el desarrollo delanálisis, bien sea sintáctico o sintagmático.

Ésta, será la primera opción que hay que escoger, después de haber compilado lagramática en un módulo externo al nuestro, que será el que esté encargado de realizaresa función, y que no está encuadrado en este nuevo entorno. Por tanto, cada vez quelancemos el analizador, y sin ninguna excepción, ya que cuando se lanza, se reseteantodas las variables que almacenan la información gramatical, para que así estén"limpias" y no se mezclen datos, habrá que seleccionarla la primera. Si no se hace así,se advertirá de la situación al usuario. Se puede ver cómo se llega a esto, en lailustración 7.8, la cual expone la situación en la cual el usuario ha seleccionado una delas opciones de análisis antes de cargar en memoria una gramática previamentecompilada.

Cuando se seleccione la opción "cargar gramática", el analizador, nos dará aelegir entre las gramáticas de que dispongamos, mediante un cuadro de diálogo similaral que se ofrece en la ilustración 7.6. Entonces, se elegirá la gramática que queramos, secomprobará que ha sido compilada, y se cargará en memoria. Igualmente que en laopción compilar, si se produce algún error, se indicará, si por otro lado, la carga se hallevado a cabo sin problemas, se presentará un mensaje de éxito (ver ilustración 7.9).

Es importante saber el alcance de esta opción, ya que las únicas gramáticas quecargará serán aquellas adaptadas para el análisis sintagmático o de primer nivel. Lasgramáticas que describen las relaciones inter-sintagmáticas de la frase, se cargan conotra opción de "Analizador".

7.4.3.2 Cargar gramática de alto nivel

La operación que realiza, es exactamente la misma que la opción explicadaanteriormente, pero adaptada a gramáticas de alto nivel. La diferencia, es que lasgramáticas de diferentes niveles, necesitan acceder a diferentes variables que se debenguardar en memoria, y por tanto, según accedamos a una carga u otra, se rellenarán, conla información correspondiente, unas variables u otras.

Un ejemplo de las diferencias, es que para el proceso de análisis sintáctico dealto nivel, es necesario almacenar en memoria, el archivo "PalabrasEspeciales.TXT"

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 145

(ver apartado 2.6 del capítulo 6) y en el análisis sintagmático o de bajo nivel, no haráfalta.

Los problemas que se pueden dar, son los mismos que anteriormente (intentarcargar gramática no compilada o falta de memoria para almacenamiento deinformación), e igualmente a "Cargar Gramática", habrá un diálogo por parte delordenador con el usuario, para informar del estado del proceso, o de la finalización delmismo.

Los cuadros de diálogo empleados en ambas acciones, serán los mismos debidoa que realizan la misma función y se pueden producir los mismos errores. Solamente enalgunos casos particulares, ha sido necesario cambiar el texto que muestran.

Por último, mencionar que cuando se está realizando el proceso de carga de unagramática, bien sea de bajo o alto nivel, aparece como fondo el archivo CMT, dondeestá desarrollada la gramática. De esta manera el usuario tiene la posibilidad deconsultar los detalles de la misma si éste lo considera preciso. Una vez cargada, laventana del archivo permanecerá en pantalla, pudiendo el usuario elegir si quiere dejarlaabierta o cerrada durante el proceso de análisis. El proceso de cierre de ventanas, es elmismo que se utiliza en cualquier programa bajo entorno Windows.

Ilustración 7.8. Mensaje de error por no haber gramática cargada.

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 146

7.4.3.3 Análisis sintagmático

En el momento en que hayamos cargado una gramática apta para el análisissintáctico de bajo nivel o análisis sintagmático de un texto (como sabemos, tendremosotras gramáticas de alto nivel, preparadas para el análisis sintáctico posterior y no parael sintagmático), se podrá acceder a la opción "Análisis sintagmático". Si la gramáticacargada es de alto nivel, y por consiguiente no es válida para este tipo de análisis, seindicará en la pantalla.

Después de escoger esta opción, se mostrará de nuevo, otro cuadro de diálogosimilar al de la ilustración 7.6, pero con la diferencia, que en este caso, se nos dará aelegir entre aquellos ficheros que tengan texto categorizado (extensión .APS). Alseleccionar uno, se analizará sintagmáticamente por medio del algoritmo CYK, yaconocido y explicado en el capítulo 5. Si se produce algún error, se notificará porpantalla, de lo contrario, se señalará la finalización del análisis.

7.4.3.4 Análisis sintáctico

Igual que pasaba con el análisis sintagmático, es necesario, en esta ocasión, teneren memoria una gramática de alto nivel, apta para el análisis sintáctico; si no es así, seinformará de la situación al usuario del analizador.

Ilustración 7.9. Éxito en la carga de la gramática "segmenta.CMT".

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 147

Si tenemos cargada una gramática válida para esta clase de análisis, se podráacceder a esta opción. Entonces, se nos presentará por pantalla un nuevo cuadro dediálogo en el que se nos dará a elegir entre aquellos archivos que hayan resultado de unanálisis sintagmático previo (recordar que el análisis sintagmático es previo al análisissintáctico de alto nivel), y estén en el formato correcto para que pueda ser entendido porel analizador sintáctico (ficheros con extensión .CRG). Después de seleccionar elfichero correspondiente, se procederá a su análisis inter-sintagmático, notificando porpantalla los errores que se produzcan, o el final del análisis en caso de que todo elproceso se haya realizado con éxito.

7.4.3.5 Analiza

Esta opción, permite realizar el proceso completo de carga de gramáticas yanálisis a ambos niveles de una vez (parecido al modo batch del antiguo analizador).

Para acceder a la opción analiza del menú "Analizador", no es necesario cargarpreviamente una gramática. El propio sistema te irá comunicando los pasos que se hande seguir, es decir, pedirá al usuario que elija una gramática cuando haya que elegirla ypedirá al usuario que seleccione un corpus de entrada cuando haya que seleccionarlo,informará al usuario del análisis que se está realizando en cada momento (sintagmáticoo sintáctico de alto nivel), y el tipo de gramática que debe seleccionar par proceder a sucarga. Se puede decir, que esta opción está destinada a usuarios novatos o pocofamiliarizados con el sistema.

Los procesos a los que va llamando y los ficheros que va generando, son losmismos que se llaman y generan en la ejecución por pasos (aquella en que tu vaseligiendo la gramática que quieres cargar en cada momento y lo que quieres hacer conella).

Para terminar con las opciones de análisis, mencionar que a la vez que se vananalizando frases, se va a generar a la altura del directorio donde se lance el programa,una estructura de directorios, cuyo directorio raíz se llamará "arboles", que contendrálas cadenas de paréntesis etiquetados de cada fragmento particular y de cada frase, quese van produciendo al analizarlos. Por medio de la opción "File" del menú, podremosrecorrer esta estructura de directorios y visualizar los árboles sintácticos que producenlas cadenas de paréntesis etiquetados. Estas cadenas, serán aquellas que produjo elanálisis más simple (aquel con menor número de segmentos).

7.4.3.6 Pintar árbol

Al seleccionar esta opción, se producirá el mismo efecto que al abrir un ficheromediante el menú "File". El resultado será el mismo, pero el método empleado paraconseguirlo no es el mismo.

Cuando se opte por esta posibilidad, se ofrecerá la opción de elegir el archivocon paréntesis etiquetados del que queremos sacar el árbol sintáctico por medio de uncuadro de diálogo idéntico al que se muestra en la ilustración 7.6. Una vez seleccionado

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 148

el fichero deseado, se creará una ventana por medio de la función "CreaVentanaNueva",a la cual se le pasará como parámetro el nombre del archivo que haya elegido el usuario.Luego, esta función llamará al constructor de la clase "TArbolSintactico", el cual seencargará de todo el proceso posterior de construcción del árbol, almacenamiento enmemoria y presentación por pantalla.

7.5 INTERACCIÓN CON EL USUARIO

Para el diálogo que se produce entre máquina y persona, se ha confeccionado uncuadro de diálogo a través del cual, se comunicará al usuario en qué estado se encuentrael proceso en cada momento.

Este cuadro de diálogo, tendrá tres funciones asociadas que son las siguientes:

• InicializaFichero(Texto): Inicializará el cuadro de diálogo. Se le puedemandar el texto que se quiere mostrar al iniciarlo.

• ActualizaFichero(Texto): Actualiza el cuadro de diálogo según el estado delproceso. El mensaja que mostrará, se pasará como parámetro a esta función.

• FinalizaFichero(): Hace desaparecer el cuadro de diálogo. Se llamará a estafunción al finalizar cualquier proceso.

Por otro lado, cuando se produzca un error o un aviso (warning), se inicie ofinalice un proceso, utilizaremos los "MessageBox".

Capítulo 7. Diseño de un entorno para el analizador CYK Pagina 149

7. DISEÑO DE UN ENTORNO PARA EL ANALIZADOR CYK..................................................1277.1 Presentación ........................................................................................................................1277.2 Generación del entorno........................................................................................................127

7.2.1 Configuración de la aplicación .....................................................................................1287.2.2 Configuración de ventanas ...........................................................................................129

7.3 Clase TWindowView...........................................................................................................1327.4 Menú principal ....................................................................................................................134

7.4.1 File..............................................................................................................................1357.4.1.1 La clase TArbolSintactico ........................................................................................136

7.4.2 Categorizador ..............................................................................................................1437.4.3 Analizador ...................................................................................................................143

7.4.3.1 Cargar gramática......................................................................................................1447.4.3.2 Cargar gramática de alto nivel ..................................................................................1447.4.3.3 Análisis sintagmático ...............................................................................................1467.4.3.4 Análisis sintáctico ....................................................................................................1467.4.3.5 Analiza ....................................................................................................................1477.4.3.6 Pintar árbol ..............................................................................................................147

7.5 Interacción con el usuario ....................................................................................................148