91
Documento de Ayuda GOLD Parser Hecho en Guatemala USAC Facultad de Ingeniería

GoldParser

Embed Size (px)

Citation preview

Page 1: GoldParser

Documento de Ayuda

GOLD Parser

Hecho en Guatemala USAC

Facultad de Ingeniería

Page 2: GoldParser

Índice

Caratula 1 Índice 2 Quienes somos, visión, misión 3 Objetivos 4 Introducción GOLD Parser Build 5 Ejemplos 12 ANSI C y GOLD PARSER 14 C Sharp Y GOLD PARSER 34 Java Y GOLD Parser 69 Visual Basic y GOLD Parser 75 Integrantes 91

Page 3: GoldParser

¿Quiénes somos? Somos un grupo de estudiantes de la facultad de Ingenierías en ciencias y sistemas de la universidad de san calos de Guatemala USAC.

Nuestra Misión

Hacer uso de las herramientas tecnológicas tanto de hardware y software, para poder desarrollar productos de alta calidad, que ayude a mejorar la vida ser humano y su entorno.

Nuestra Visión

Ayudar a mejorar o facilitar la situación de nuestro entorno, por medio del desarrollo de software en distintas áreas de la sociedad.

Page 4: GoldParser

OBJETIVOS

de este documento

Generales

Facilitar el uso de la herramienta GOLD Parser en el uso de analizadores.

Explicar fácil y gráficamente los pasos a seguir para pode realizar un analizador a partir de

una gramática.

Específicos

Realizar una gramática desde cero con GOLD Parser

Implementar la gramática para los lenguajes ANSI C (C puro), C#, Java y Visual Basic

Ayudar al lector con información en español de GOLD Parser

Page 5: GoldParser

INTRODUCION GOLD Parser es una herramienta desarrollada por Devin Cook, implementando un LALR (Look Ahead Left to Right- Rightmost derivation), se pueden construir proyectos con base de analizadores, o construir versiones propias de un lenguaje de programación. GOLD Parser es la herramienta con más capacidad de ser implementada en varios lenguajes de programación, ya que guarda un archivo aparte conteniendo información de tablas de parseo y en cada lenguaje se implementa el autómata simple para el análisis de dichas tablas. Otra ventaja es el soporte que todavía se le brinda a la herramienta y es GRATIS. Algunos lenguajes soportados y con implementación disponibles son los siguientes:

Page 6: GoldParser

Funcionamiento

Como la instalación de GOLD Parser documento. (Véase http://www.devincook.com/goldparser/download.htmdescarga del instalador y los complementos que vamos a usar en cada lenguaje).Algoritmo para implementar un analizador:

1. Crear una gramática2. Guardar el archivo que nos genera (CGT “Compiler Grammar

Table” se explicara 3. Crear un esqueleto del lenguaje que deseemos.4. Ingresar las acciones a

Funcionamiento

Como la instalación de GOLD Parser es sencilla no se explicara en este http://www.devincook.com/goldparser/download.htm

descarga del instalador y los complementos que vamos a usar en cada ritmo para implementar un analizador:

gramática valida (sin errores de ningún tipo).Guardar el archivo que nos genera (CGT “Compiler Grammar Table” se explicara más adelante). Crear un esqueleto del lenguaje que deseemos. Ingresar las acciones a nuestro proyecto.

es sencilla no se explicara en este para la

descarga del instalador y los complementos que vamos a usar en cada

valida (sin errores de ningún tipo). Guardar el archivo que nos genera (CGT “Compiler Grammar

Page 7: GoldParser

Tabla Compilada de la GRAMATICA

La tabla de cada analizador es un archivo (.cgt), esta tabla de gramática compilada posee la información

Como vemos no se necesita insertar en la código o acciones semánticasindependiente del lenguaje

Hasta este punto se utiliza la herramienta Gold Parser BUILDER, siexisten Skeletons, ya disponibles para varios lenguajes.(Esqueleto o plantilla) es un archivo con la implementacgramática lista para introducirles accionesusando.

El engine(Motor) del lenguaje de programación utiliza estedependiendo del lenguaje programación analiza el archivo fuente, crea el árbol de sintáctico, permite asociar objetos a cada símbolo de la gramáticaimplementa la tabla de análisis sintáctico para esa gramática

Tabla Compilada de la GRAMATICA (GCT)

La tabla de cada analizador es un archivo (.cgt), esta tabla de gramática información del autómata para análisis léxico y

no se necesita insertar en la construcción de la gramáticanticas, ya que la construcción del analizador LALR es

independiente del lenguaje en que estemos trabajando.

Hasta este punto se utiliza la herramienta Gold Parser BUILDER, si existen Skeletons, ya disponibles para varios lenguajes. Un Skeleton

es un archivo con la implementación de nuestra gramática lista para introducirles acciones en el lenguaje que estemos

del lenguaje de e archivo y

dependiendo del lenguaje de programación analiza el archivo fuente, crea el árbol de análisis

, permite asociar objetos a gramática, e

implementa la tabla de análisis ico para esa gramática.

Para cada lenguaje existen diferentes motores los

cuales deben de descargarlos en librerias o complementos para poder utilizarlos en sus proyectos

La tabla de cada analizador es un archivo (.cgt), esta tabla de gramática y sintáctico.

gramática, n del analizador LALR es

se desea Skeleton

de nuestra en el lenguaje que estemos

Para cada lenguaje existen diferentes motores los

cuales deben de descargarlos en librerias o complementos para poder utilizarlos en sus proyectos

Page 8: GoldParser

Escritura de Gramática y Más

GOLD Parser utiliza notación BNF (Backus Naur Form), por lo que todos los No terminales deben estar encerrados en brackets angulares, por ejemplo <NoTerminal> o <Inicio>.

También permite definir tokens terminales entre comillas, por ejemplo ‘terminal1’ o ‘nombreCompleto’. Ahora noten que el terminal ‘terminal1’ corresponde a la palabra exactamente encerrada, pero no fue declarado al inicio como un terminal, terminal1 correspondería a una expresión regular. Caracteres especiales para realizar la gramática:

Caracteres comunes

NOMBRE INSTRUCCION DESCRIPCION

Tabulador {HT} Conocido como Tab, escribe una tabulación en la línea.

Salto de Línea {LF} Se utiliza para bajar una línea en los documentos

Tabulación Vertical {VT} Se usa para saltase a la siguiente línea marcada

Limpia pantalla {FF} Se usa para saltar toda la pantalla por ejemplo CLR o clear

Retorno de Carro {CR}

Sirve retornar el apuntador al inicio de la línea

Espacio {Space} Se utiliza para separar caracteres

Espacio sin Romper {NBSP} Se utiliza para los espacio donde el salto de línea no es permitido

Símbolo del Euro {Euro Sign} Representa el símbolo del euro

Page 9: GoldParser

Conjuntos de Caracteres comunes

NOMBRE INSTRUCCION DESCRIPCION Numero {Number} Números del 0 al 9.

Digito {Digit} Esta instrucción es similar a number, recomiendan NO USAR ESTA INSTRUCCIÓN.

Letra {Letter} Reconoce una simple letra del alfabeto en minúsculas o mayúsculas no incluye la ñ.

Alfanumérico {AlphaNumeric} Es la unión de las instrucciones Letter y Number.

Cualquier Carácter {Printable} Reconoce cualquier carácter desde el #32-#127 y #160 (No espacios quebrados).

Letra Extendida {Letter Extended} Reconoce todas las letra incluyendo los caracteres especiales como ñ

Cualquier Carácter extendido

{Printable Extended} Reconoce todos los caracteres arriba del carácter #127

Espacio en blanco {Whitespace}

Reconoce los caracteres como espacio, salto de line.

Page 10: GoldParser

Ejemplo:

!--comentario (parte I) {String Char} = {Printable} - ["] {IdLetter} = {Letter} + [_$] {IdAlphaNumeric} = {Alphanumeric} + [_$] !-- parte I define todos los conjuntos para exp. regulares !-- parte II (Expresiones regulares) Identifier = {IdLetter} {IdAlphaNumeric}* StringLiteral = '"'{String Char}*'"' Integer = {Digit}+ terminal1 = {Digit}+'.'{Digit}+ !-- define diferentes expresiones regulares para la gramatica "Start Symbol" = <inicio> <inicio>::= terminal1 | ‘terminal1’ <mas_>

En el breve ejemplo de arriba se nota lo principal entre la expresión regular, nuestra gramática inicia con un terminal1 (numero FLOAT) o con la palabra reservada ‘terminal1’. Esto implica la barra vertical en una regla la bifurcación (OR). También el primer bloque posee conjuntos utilizados para la construcción de las expresiones regulares.

Page 11: GoldParser

recomendables para la explicacióncolocar comentarios de una sola entre !* *!

También GP Builder cuenta con para detallar o permitir ciertas funcionalidades que se insertan al inicio de la gramática. Como Name (nombre de la gramática), Author (autor de la Case Sensitive (Para restricciónmayúsculas y minúsculas).

Ver la ayuda de GP Builder para una

descripcion detalla de los conjuntos ya

prefabricados para uso.

Notar la línea ‘Start Symbol’ que indica la regla inicial de la gramática.

La estructura de las reglas consiste, solo un <No terminal> de la izquierdo luego definimos ‘produce’ colocando ::= y nuestro lado derecho del produce. Los comentarios son muy

explicación de cada parte de la gramática, GP permite colocar comentarios de una sola línea con ! al inicio o bloques de varias

GP Builder cuenta con parámetros para detallar o permitir ciertas funcionalidades que se insertan al inicio de

. Como Name (nombre de la ), Author (autor de la gramática),

restricción de

Ver la ayuda de GP Builder para una

descripcion detalla de los conjuntos ya

prefabricados para uso.

Ver la ayuda de GP Builder para mayor

detalle de los parametros disponibles en la version que se este utilizando.

‘Start Symbol’ que indica la regla inicial de la

La estructura de las reglas consiste, de la

izquierdo luego definimos ‘produce’ colocando ::= y nuestro lado derecho del produce. Los

, GP permite de varias líneas

Ver la ayuda de GP Builder para mayor

detalle de los parametros disponibles en la version que se este utilizando.

Page 12: GoldParser

Ejemplos Prácticos

Page 13: GoldParser

Lista de Lenguajes Para mostrar los diferentes usos de que se le pueden dar a GOLD Parser, presentamos 4 lenguajes de programación, en los cuales damos paso a paso las instrucciones para implementarlo:

ANSI C C#

JAVA Visual Basic

Page 14: GoldParser

ANSI C Generado por GOLD Parser

Page 15: GoldParser

GOLD PARSER Y ANSI C

El lenguaje de Ansi C es uno de los lenguajes de programación que dio lugar a muchos lenguajes más como C++, java, C#. Entre otros. Es un lenguaje muy simple pero poderoso, de el están hechos muchos sistemas operativos. Como en todo programa se necesita de información y esta debe de ser filtrada para un mejor aprovechamiento de los recursos. El uso de un analizador es una de las mejores prácticas para poder filtrar la información. GoldParser es una herramienta que nos ayuda a crear un analizador definiendo una gramática con BNF (Backus-Naur Form), como se muestra en la siguiente imagen:

Page 16: GoldParser

Siguiendo la gramática siguiente: Para poder realizar las acciones deseadas para esta gramática. Debemos de pasar por 4 pasos en GOL Parser: PASO 1: Verificar que la gramática este correcta ( Sin errores léxicos, sintácticos, etc.)

<lenguaje> ::= <Listas> <listas> ::= <listas> ',' <lista>

| <lista> <lista> ::= '{' <numeros> '}' <numeros> ::= <numeros> ',' numero | numero

Page 17: GoldParser

PASO 2: Construir el analizador LALR (Look-Ahead Left Right), verifica que no existan

conflictos de reducción-reducción o desplazamiento-reducción.

PASO 3: Construye el Autómata finito determinantico DFA.

Page 18: GoldParser

PASO 4: En este paso se guarda la gramática analizada en forma de tabla. (Esto nos servirá

para crear un esqueleto para unirlo a nuestro lenguaje Ansi C).

Cuando pasamos por el paso 4 vamos a guardar la tabla compilada de nuestra gramática, este lo vamos a utilizar más adelante

Page 19: GoldParser

Para verificar que nuestro GCT esta correcto, vamos a comprobarlo con un archivo de entrada por medio de la herramienta que nos provee GOLD Parser Builder, Le damos Clic en el icono de un cheque verde (ver figura)

Cuando hayamos hecho lo anterior vamos a ingresar una cadena valida según nuestro lenguaje para poder probarlo.

Page 20: GoldParser

Para probar le damos clic en el icono verde que nos permite ir probando paso a paso, la forma en que va leyendo nuestro archivo la tabla compilada de nuestra gramática, también podemos ir de un solo al final del análisis ya sea algún error o como esta en este documento VALIDA (Acecept)

Page 21: GoldParser

Ya que tenemos nuestra Gramática Compilada en Tabla, vamos a proceder a crear un esqueleto para poderlo utilizar con nuestro lenguaje.

Page 22: GoldParser

Existen 3 tipos de Motores (Engine) para ANSI C, pero nosotros para mayor facilidad vamos a utilizar el 3 motor, KESSELS ENGINE, creado por J.C. Kessels (http://kessels.com/Gold/index.html)

Guardamos el primer archivo .h (no importa el orden .h/.c) que contiene las declaraciones de los símbolos.

Page 23: GoldParser

El segundo archivo es el .c, vamos a guardarlo igual que el .h, este archivo contiene un main por defecto como se verá más adelante

Page 24: GoldParser

Una vez creados los 2 archivos, le damos clic en “Done” para poder proceder a ingresar las acciones a nuestra gramática en ANSI C. (ambos archivos deben de estar en el directorio del proyecto)

Ahora abrimos nuestro archivo *.c con algún compilador o editor para C/C++, en este ejemplo yo utilizo Borland C++, pero pueden usan VC++.net o VC++ 6, asi como cualquier compilador de Linux ya que el motor kessels es aceptado por compilador de C para Windows y Linux.

Page 25: GoldParser

Creando un Nuevo proyecto VC++ 6

Page 26: GoldParser
Page 27: GoldParser
Page 28: GoldParser

Vamos Agregar los archivos que están en esta carpeta el grammar.h y template.c

Dentro de los archivos deben de ir los Engine.h y engine.c que se pueden descargar de la página del creador de estos motores http://kessels.com/Gold/index.html

Page 29: GoldParser

Como menciona en la página anterior, ya descargados y descomprimidos solo queda copiarlos a la carpeta donde tenemos nuestro proyecto y agregarlos.

Ahora vamos a agregar los esqueletos que fueron creados en GOLD Parser Build.

Page 30: GoldParser

El archivo de gramatica.h tiene un pequeño problema con los caracteres, ya que yo tengo el sistema español Latino (GUATEMALA) y me da un pequeño error a la hora de generarlo, como se explica a continuación:

Otro pequeño problema que me tope es que cuando se ha construyendo el .exe se bloquean los archivos y aparece el siguiente mensaje:

Page 31: GoldParser

Antes de proceder a Construir vamos a cambiar el archivo de entrada que viene por default

Procedemos a Construir nuestro proyecto de ejemplo:

Page 32: GoldParser

Les debería de Salir un mensaje exitoso de la construcción del archivo .exe

Page 33: GoldParser

Como menciona la imagen a mi me dio problemas a tratar de Debugear la aplicación, asi que les recomiendo mejor ejecuten y no debugeen

Como ven en la imagen he modificado la salida en la parte de Gramática aceptada

Page 34: GoldParser

C Sharp Generado por GOLD Parser

Page 35: GoldParser

GOLD PARSER CON C#

El presente documento estará dividido en 2 ejemplos, un ejemplo sencillo para ver las funcionalidades básicas de las herramientas y un ejemplo con cierta mayor dificultad.

Nota: antes de empezar el presente manual el lector debe tener conocimientos básicos en la definición de gramáticas y sintaxis utilizada en GOLD Parser.

La primera gramática utilizada será la siguiente: Una gramática que reconoce un conjunto de números enteros separados por coma y agrupados entre llaves Start Symbol" = <lenguaje> ! Define la producción inicial. Numero = {Digit}+ ! Define el terminal número. <lenguaje> ::= <Listas> <Listas> ::= <Listas> ',' <lista> | <lista> <lista> ::= '{' <numeros> '}' <numeros> ::= <numeros> ',' Numero | Numero Ejemplo de Entrada valida seria: {1,85,8,3,8},{5,8,4,3,0},{1,2}

Page 36: GoldParser

CONEXIÓN GOLDEN PARSER CON C#

Para realizar esto necesitamos: Archivo *.cgt (compiled grammar table): Este archivos es generado por Golden Parser. Archivo *.cs: archivo generado por Golden Parser con sintaxis de C# el cual contiene las producciones definidas en la gramática. Librerías de Golden Parser (CalithaLib.dll y GoldParserEngine.dll): Estas librerías se pueden descargar de la Pagina Oficial de Golden Parser (http://www.devincook.com/goldparser/engine/dot-net/van-loenhout/GoldParserEngine_v1.13_bin.zip)

Generación del archivo *.cgt:

Paso 1: En la parte inferior derecha se encuentra el botón “continue”, realiza 4 pasos.

Page 37: GoldParser

Paso 2: Si la gramática es correcta se mostrara la ventana para guardar el archivo *.cgt.

Page 38: GoldParser

Generación del archivo *.cs:

Paso 1: Vamos a Tools à Create a Skeleton Program

Nota: Para crear el esqueleto del programa debemos realizar los 4 pasos para crear el archivo *.cgt (visto anteriormente, sino lo realizamos el botón estará deshabilitado)

Page 39: GoldParser

Paso 2: Seleccionamos Calitha Engine, Event Based y presionamos Create.

Page 40: GoldParser

Paso 3: Seleccionamos una ubicación para nuestro archivo *.cs y lo nombramos. Por último presionamos guardar.

Page 41: GoldParser

Obtenemos las librerías:

Page 42: GoldParser

UNIR LOS ELEMENTOS PARA REALIZAR LA

CONEXIÓN

Paso 1: Creamos un nuevo proyecto de C# y extraemos las librerías del archivo .zip anterior, vamos al área de referencias y seleccionamos Add Reference.

Page 43: GoldParser

Paso 2: Seleccionamos la pestaña Browse y las 2 librerias de Golden Parser, presionamos Ok.

Page 44: GoldParser

Paso 3: Añadir el archivo *.cs a nuestro proyecto. Damos clic derecho a nuestro proyecto y seleccionamos Add à Existing Item.

Paso 4: Seleccionamos nuestro archivo y presionamos el botón Add.

Page 45: GoldParser

Paso 5: Al código de nuestro formulario importamos la librería com.calitha.goldenparser

Paso 6: Crear la variable global “Myparser parser;” en el formulario

Page 46: GoldParser

Paso 7: En el constructor de nuestro formulario inicializamos la variable “parser” indicando donde esta el archivo .cgt.

parser = new MyParser(Application.StartupPath + "\\Listas_sumadas.cgt");

Nota: El archivo .cgt debe estar en la misma ubicación donde se encuentra el ejecutable de nuestra aplicación.

Page 47: GoldParser

Paso 8: Crear un textbox y un botón en nuestra interfaz grafica.

Paso 9: Generamos un evento al botón “Analizar” (button1). Agregamos la instrucción “parser.Parse(textBox1.Text);” . La anterior instrucción envía al parser el texto que tengamos en nuestro textBox para ser analizado.

Page 48: GoldParser

AÑADIR FUNCIONALIDAD A NUESTRO PARSER.

Una vez completado los pasos de conexión añadiremos acciones a nuestro parser.

Existen 3 métodos principales:

private Object CreateObject(TerminalToken token): método encargado de los símbolos terminales y no terminales. Devuelve los valores leídos a los elementos de las producciones.

public static Object CreateObject(NonterminalToken token): Este método se encarga de las producciones. Permite obtener los datos de los elementos de las producciones(los hijos) y devolverlos al padre.

private void AcceptEvent(LALRParser parser, AcceptEventArgs args): Este método es invocado cuando el parser acepta la cadena o archivo de entrada.

Page 49: GoldParser

private Object CreateObject(TerminalToken token): //Necesitamos el texto leido por el terminal Numero y el no terminal //<numeros> por ese motivo devolvemos el valor (el texto leido). case (int)SymbolConstants.SYMBOL_NUMERO : //Numero return token.Text;

case (int)SymbolConstants.SYMBOL_NUMEROS : //<numeros> return token.Text; //No necesitamos el valor de la coma “,” o de la llave “{“ cuando son leidos //por ese motivo devolvemos null case (int)SymbolConstants.SYMBOL_COMMA : //',' //todo: Create a new object that corresponds to the symbol return null; case (int)SymbolConstants.SYMBOL_LBRACE : //'{' //todo: Create a new object that corresponds to the symbol return null;

Page 50: GoldParser

public static Object CreateObject(NonterminalToken token): case (int)RuleConstants.RULE_LISTA_LBRACE_RBRACE : //<lista> ::= '{' <numeros> '}' //todo: Create a new object using the stored user objects. return token.Tokens[1].UserObject; Lo que podemos observar allí:

token.Tokens es un array q tiene los tokens del lado derecho de nuestra producción. token.Tokens[n].UserObject tiene el valor del terminal o no terminal en la posición n. En nuestro ejemplo <numeros> tiene la posición 1. UserObject es el objeto que hemos asignado al array en la posición n. return lo que retornamos es lo q le vamos a asignar al símbolo q esta del lado izquierdo de nuestra producción (<lista>). En nuestro ejemplo lo que asignaremos a <lista> será el valor del no terminal <numeros>.

case (int)RuleConstants.RULE_NUMEROS_COMMA_NUMERO : //<numeros> ::= <numeros> ',' Numero //todo: Create a new object using the stored user objects. return null;

Page 51: GoldParser

Lo que podemos observar allí:

De la producción <numeros> à <numeros> ',' Numero Tenemos la regla semantica numeros.val=numeros.val + Numero. token.Tokens es un array q tiene los tokens del lado derecho de nuestra producción. token.Tokens[n].UserObject tiene el valor del terminal o no terminal en la posición n. En nuestro ejemplo <numeros> tiene la posición 0 y Numero la posición 2. UserObject es el objeto que hemos asignado al array en la posición n.

return lo que retornamos es lo q le vamos a asignar al símbolo q esta del lado izquierdo de nuestra producción (<numeros>). En nuestro ejemplo lo que asignaremos a <numeros> será el valor de la suma del no terminal <numeros> con el terminal Numero. Quedando de la siguiente forma: return(int)token.Tokens[0].UserObject + Int32.Parse((string)token.Tokens[2].UserObject); El valor de <numeros> lo obtenemos con la instrucción: (int)token.Tokens[0].UserObject. Ya que lo devuelto por el array es un objeto debemos indicar que el objeto retornado es de tipo entero.

El valor de Numero lo obtenemos con la instrucción: Int32.Parse((string)token.Tokens[2].UserObject). Debido a que el valor devuelto es un Objeto debemos indicar el tipo de objeto contenido, Numero viene de la cadena de entrada por lo tanto es de tipo texto, con la instrucción

Page 52: GoldParser

(string) indicamos que el objeto es de tipo texto, lo que necesitamos es un valor numerico, por lo tanto debemos hacer otra converción de tipos, en este caso la cadena debemos pasarla a un valor entero, esto se consigue con el metodo Int32.Parse(cadena);

case (int)RuleConstants.RULE_LENGUAJE : //<lenguaje> ::= <Listas> Resultado = ordenar((ArrayList)token.Tokens[0].UserObject); return null; Lo que podemos observar allí:

<lenguaje> es la produccion inicial de nuestra gramatica, siendo un analizador ascendente sera la ultima reducción realizada, por lo tanto almacenaremos el resultado final en la variable resultado obteniendo su valor del metodo ordenar enviando como parametro las listas leidas.

Page 53: GoldParser

Nota:

v Debemos declarar la variable global Resultado de tipo Cadena en nuestra clase parser (Listas_Sumadas.cs) para poder utilizarlo dentro del metodo AcceptEvent.

v Para utilizar la clase ArrayList debemos importar la librería System.Collections;.

private void AcceptEvent(LALRParser parser, AcceptEventArgs args): Este método es invocado al momento que es aceptada la cadena de entrada. En el presente ejemplo desplegaremos el resultado en un mensaje de texto (MessageBox). System.Windows.Forms.MessageBox.Show("El resultado es " + resultado); Nota: Definición método Ordenar: public static string Ordenar(ArrayList lista) { string valores = ""; lista.Sort(); for (int i = 0; i < lista.Count; i++) { valores = valores + ", [" + lista[i] + "]"; } lista.Clear(); return valores; }

Page 54: GoldParser

EJEMPLO 2

Para este ejemplo utilizaremos una gramática que reciba la definición de clases simples (variables y métodos), y una definición dirigida por la sintaxis que analice la entrada y despliegue el significado o describa su uso dentro de la clase. La gramática utilizada para este ejemplo es la siguiente: "Start Symbol" = <lenguaje> {String Char} = {Printable} - ["] id ={Letter}{Alphanumeric}* texto = '"'{String Char}*'"' char = ''{String Char}*'' entero = {Number}+ real = {Number}+'.'{Number}* Comment Start = '/*' Comment End = '*/' Comment Line = '//' "Case Sensitive" = 'False' "Start Symbol" = <lenguaje> <lenguaje> ::= <def_clases> <def_clases> ::= <def_clases> <def_clase> | <def_clase> <def_clase> ::= <acceso> 'class' id '{' <def_vars> <def_met> '}' <acceso> ::= 'public' | 'private' | 'protected'

Page 55: GoldParser

<def_vars> ::= <def_vars> <def_var> | <def_var> <def_var> ::= <tipo> id <asigna> ';' | <tipo> ::= 'String' | 'int' | 'double' | 'char' <asigna> ::= '=' <valor> | <valor> ::= texto | entero | real | char | id <def_met> ::= <metodo> <def_met> | <metodo> <metodo> ::= <acceso> <tipo> id '(' ')' '{' <cuerpo_m> 'return' <valor> ';' '}' | <acceso> 'void' id '(' ')' '{' <cuerpo_m>'}' <cuerpo_m> ::= <cuerpo_m> id <asigna> | <cuerpo_m> <def_var> | id <asigna> | <def_var>

Nota: Para continuar con este ejemplo el lector debe haber antes estudiado o tener conocimientos sobre los elementos necesarios para la conexión con C# y como se unen los mismos (se puede encontrar en el ejemplo 1).

Page 56: GoldParser

Luego de realizar la unión de los elementos (añadir el parser, las librerías y definir el archivo *.cgt) vamos a añadir funcionalidad a nuestro parser. Como vimos en el ejemplo 1 los métodos principales son 3, iremos añadiendo funcionalidad a cada uno. private Object CreateObject(TerminalToken token): Devuelve los valores leídos a los elementos de las producciones. Estos elementos son los que queremos recibir exactamente como se lee en la entrada. En nuestra gramática seria principalmente los elementos de la producción: <valor> à texto | entero | real | char | id. Por lo tanto en este método algunas modificaciones serian. case (int)SymbolConstants.SYMBOL_DOUBLE : //double return token.Text; case (int)SymbolConstants.SYMBOL_ENTERO : //entero return token.Text; case (int)SymbolConstants.SYMBOL_ID : //id return token.Text;

Indicando token.Text le decimos al parser que devuelva el valor leído, por ejemplo si leyéramos la cadena Clase1 en nuestro parser se convertiría en un “id” y lo que devolvemos es la cadena “Clase1” para ser utilizada en las producciones. Otro ejemplo seria si leyéramos el valor 15 en nuestro parser se convertiría en un “entero” colocando return token.Text el valor que contendría “entero” es 15.

Page 57: GoldParser

Los lectores se podrían preguntar, ¿se pueden devolver mas valores?, y la respuesta es si, por ejemplo de la producción <acceso> à 'public' | 'private' | 'protected' se tiene: case (int)SymbolConstants.SYMBOL_PRIVATE : //private return null; Pero, ¿por que devolvemos null? En nuestro ejemplo devolveremos null por que el valor ‘private’ es estático, es decir siempre será el mismo, no así valores infinitos como id, entero, texto, etc. ¿Pero si quisiera podría devolver el valor? Y la respuesta es de nuevo si, podríamos retornar token.Text y lo que devolveríamos seria el valor “private”. ¿Por que no lo hacemos? Por que en nuestra gramática ya “sabemos” que vino private por lo tanto devolver “private” seria algo redundante. public static Object CreateObject(NonterminalToken token): Este método es el mas complejo ya que en el se agrega la mayoría de las funcionalidades de nuestro parser, es donde se realizan las reducciones y producciones. Empezaremos por lo mas sencillo devolveremos los valores de las producciones <acceso> y <tipo> case (int)RuleConstants.RULE_ACCESO_PRIVATE : //<acceso> ::= private return "private"; case (int)RuleConstants.RULE_ACCESO_PROTECTED :

Page 58: GoldParser

//<acceso> ::= protected return "protected"; case (int)RuleConstants.RULE_TIPO_STRING : //<tipo> ::= String return "String"; case (int)RuleConstants.RULE_TIPO_INT : //<tipo> ::= int return "int";

En las producciones anteriores únicamente devolvimos texto, ahora veamos como es utilizando los valores dentro de las producciones. Teniendo la producción <valor> case (int)RuleConstants.RULE_VALOR_TEXTO : //<valor> ::= texto return token.Tokens[0].UserObject; case (int)RuleConstants.RULE_VALOR_ENTERO : //<valor> ::= entero return token.Tokens[0].UserObject;

Recordando del ejemplo 1, sabemos que Tokens es un array que contiene los valores de la producción del lado derecho, indicando Tokens[0].UserObject obtenemos el valor en la posición 1, el lector podría preguntarse ¿de donde viene el valor de texto y entero? Esos valores provienen del método 1, donde retornamos “token.Text”. Ahora veamos la producción <asigna>: case (int)RuleConstants.RULE_ASIGNA_EQ : //<asigna> ::= '=' <valor> return token.Tokens[1].UserObject; case (int)RuleConstants.RULE_ASIGNA : //<asigna> ::= //todo: Create a new object using the stored user objects. return null;

Page 59: GoldParser

Esta producción tiene 2 valores posibles, nulo o <asigna> recibirá el dato <valor>. La siguiente producción es la definición de una variable, su tipo, su nombre y el valor asignado. case (int)RuleConstants.RULE_DEF_VAR_ID_SEMI : //<def_var> ::= <tipo> id <asigna> ';' String[] variable = { (string)token.Tokens[0].UserObject, (string)token.Tokens[1].UserObject, (string)token.Tokens[2].UserObject }; return variable;

En nuestra solución definiremos un Array de Strings de 3 valores, en el primero se almacenara el tipo, en el segundo el identificador y en el tercero el valor, el tercer valor puede ser nulo?, si, si puede ser nulo, recordemos que asigna produce valor o nulo, lo que asignaremos en nuestro String sera nulo si no trae valor, pero mas adelante validaremos si viene nulo o trae un valor. Ahora veamos como almacenamos varias variables y vamos “subiendo” el valor en nuestra gramatica. Esto se realiza con la produccion <def_vars>. case (int)RuleConstants.RULE_DEF_VARS : //<def_vars> ::= <def_vars> <def_var> ArrayList aux2 = (ArrayList)token.Tokens[0].UserObject; aux2.Add(token.Tokens[1].UserObject); return aux2; case (int)RuleConstants.RULE_DEF_VARS2 : //<def_vars> ::= <def_var> if (token.Tokens[0].UserObject != null) { varaux = new ArrayList(); varaux.Add(token.Tokens[0].UserObject); return varaux; } return null;

Page 60: GoldParser

Siendo una gramatica recursiva por la izquierda el primer valor reducido sera <def_vars> à <def_var> por lo tanto aca crearemos un arraylist que ira agregando las definiciones de las variables. Antes de continuar debemos realizar una validacion, recordemos que <def_var> puede producir nulo, por lo mismo verificamos si trae valor y viene con valor nulo. Lo que retornaremos si trae valor es “varaux” sino trae valor retornaremos nulo. <def_vars> à <def_vars> <def_var> en esta produccion lo que haremos es obtener el arraylist que creamos en <def_vars> à <def_var> y añadir la nueva definicion de variable <def_vars> à <def_vars> <def_var> , asi sucesivamente hasta recorer todas las variables definidas en nuestra clase. La definición de métodos y clases se realiza de forma similar a la de variables, serán ArrayList y cada uno añadira nuevos valores (Todas las definiciones se pueden encontrar en el codigo fuente del ejemplo). case (int)RuleConstants.RULE_LENGUAJE : //<lenguaje> ::= <def_clases> Resultado = (ArrayList)token.Tokens[0].UserObject; return null;

Al final tendremos un ArrayList Resultado con todo lo que necesitamos (las clases, las variables y métodos).

Page 61: GoldParser

private void AcceptEvent(LALRParser parser, AcceptEventArgs args): Método invocado cuando el parser acepta la cadena de entrada. En este método utilizaremos el ArrayList creado en el método anterior. El ArrayList “Resultado” posee la siguiente estructura.

v Clase: 1. Acceso 2. Nombre 3. Def_variables o nulo 4. Def_metodos

v Def_variables:

1. Tipo 2. Nombre 3. Valor, puede ser nulo

v Def_metodos: 1. Acceso 2. Tipo 3. nombre 4. variables, puede ser nulo

Page 62: GoldParser

System.Windows.Forms.MessageBox.Show("Entrada correcta "); String cadenaR = ""; for (int i = 0; i < Resultado.Count; i++) { ArrayList auxclases = (ArrayList)Resultado[i]; cadenaR = cadenaR+"Definicion de la Clase '" + auxclases[1]+"'\n"; cadenaR = cadenaR + "Acceso: " + auxclases[0]+"\n"; if (auxclases[2] != null) { ArrayList auxvariables = (ArrayList)auxclases[2]; String cadena = ""; for (int y = 0; y < auxvariables.Count; y++) { String[] var = (String[])auxvariables[y]; cadena = cadena + "Tipo: " + var[0] + " variable: " + var[1] + " valor: " + var[2] + "\n"; } cadenaR= cadenaR + "\n Listado de variables Globales\n" + cadena; } cadenaR = cadenaR + "\nListado de Metodos\n"; ArrayList auxmetodos = (ArrayList)auxclases[3]; for (int z = 0; z < auxmetodos.Count; z++) { ArrayList auxmetodos2 = (ArrayList)auxmetodos[z]; cadenaR = cadenaR + "\nDefinicion metodo: '" + auxmetodos2[2]+"'\n"; cadenaR = cadenaR + "Acceso: " + auxmetodos2[0]+" Tipo: "+auxmetodos2[1]+"\n"; if (auxmetodos2[3] != null) { ArrayList auxvariables = (ArrayList)auxmetodos2[3]; String cadena = "";

Page 63: GoldParser

for (int y = 0; y < auxvariables.Count; y++) { String[] var = (String[])auxvariables[y]; cadena = cadena + "Tipo: " + var[0] + " variable: " + var[1] + " valor: " + var[2] + "\n"; } cadenaR = cadenaR + "\n Listado de variables Locales del metodo "+ auxmetodos2[2]+"\n" + cadena; } } cadenaR = cadenaR + "\n\n\n"; } result = cadenaR; Nota: Las variables Resultado de tipo ArrayList y result de tipo string son variables globales a la clase.

Page 64: GoldParser

EXPLICACIÓN DE FUNCIONALIDAD PASO 1: Se ingresa la definición de clases con variables y métodos y se

presiona. ”Analizar”

Paso 2: Si los datos son correctos se muestra el mensaje “Entrada

correcta”

Paso 3: Se presiona aceptar y se presentara lo siguiente.

Page 65: GoldParser

Paso4: Cuando presionamos “Analizar” el programa divide la entrada en

clases, muestra sus atributos, cuales son sus variables globales y sus métodos, además de mostrar las variables locales de los métodos.

Page 66: GoldParser

Entrada: private class Clase1 { String cadena = "texto"; int numero = 10; double porcentaje = 12.5; protected int contador() { int var = 15; return var; } public void mensaje () { String cadena2 = "nada"; double promedio = 90.5; } public void mensaje2 () { String cadena2 = "nada"; double promedio = 90.5; } }

protected class ClaseDos { int cantidad= 1; private void metodounico() { } }

Page 67: GoldParser

Salida: Definicion de la Clase 'Clase1' Acceso: private

Listado de variables Globales Tipo: String variable: cadena valor: "texto" Tipo: int variable: numero valor: 10 Tipo: double variable: porcentaje valor: 12.5

Listado de Metodos

Definicion metodo: 'mensaje2' Acceso: public Tipo: void

Listado de variables Locales del metodo mensaje2 Tipo: String variable: cadena2 valor: "nada" Tipo: double variable: promedio valor: 90.5

Definicion metodo: 'mensaje' Acceso: public Tipo: void

Listado de variables Locales del metodo mensaje Tipo: String variable: cadena2 valor: "nada" Tipo: double variable: promedio valor: 90.5

Definicion metodo: 'contador' Acceso: protected Tipo: int

Listado de variables Locales del metodo contador Tipo: int variable: var valor: 15 Definicion de la Clase 'ClaseDos'

Page 68: GoldParser

Acceso: protected

Listado de variables Globales Tipo: int variable: cantidad valor: 1

Listado de Metodos Definicion metodo: 'metodounico' Acceso: private Tipo: void

Page 69: GoldParser

JAVA Generado por GOLD Parser

Page 70: GoldParser

Java y GOLD Parser Builder Primero: Bajamos el modulo jar compatible para Netbeans y ecplipse

Page 71: GoldParser

Segundo: Lo guardamos en un lugar accesible

Page 72: GoldParser

Cuarto: Hacemos un Nuevo proyecto en Netbeans y agregamos el jar

como libreria.

Page 73: GoldParser

Quinto: Lo agregamos a nuestro proyecto para poder hacer uso de el.

Page 74: GoldParser

Sexto: Asegurarse que el nombre del Skeleton que hizo Goldparser se llame MyParser y luego incluirlo en el scr del proyecto.

Page 75: GoldParser

Séptimo: Debería de quedar el archive java sin errores.

Page 76: GoldParser

Octavo: Instanciamos una variable de tipo MyParser

Page 77: GoldParser

Noveno: Incuimos el archivo config

Este tiene que tener 2 lienas La primera la ubicacion del archivo cgt. La segunda la ubicación del archivo de entrada

Listo ya se pueden implementar las acciones necesarias para realizar el análisis de cualquier lenguaje que obedezca la gramática

Page 78: GoldParser

Visual Basic Generado por GOLD Parser

Page 79: GoldParser

GOLD Parser con VB En esta parte de la documentación se tratara sobre cómo generar gramáticas desde GOLD Parser, para luego utilizarlas desde el lenguaje de Visual Basic. A continuación se da una descripción detallada de los aspectos más importantes para la generación de una gramática. Encabezado de gramática: En esta parte se debe indicar ciertos aspectos sobre la gramática, algunos considerados de importancia son los siguientes:

• Name: Este especifica el nombre de la gramatica. • Author: Indica el autor de la elaboracion de la gramatica. • Version: La version de la gramatica, para tener un control adecuado en

caso de que se lleve cierto versionamiento de la misma. • About: Este muestra la descripcion de la gramatica. • Case Sensitive: Este es requerido si en caso se desea que la gramatica

que se elaborará, distinga entre mayúsculas y minúsculas. En caso se desee esta distinción se debe indicar con el parámetro true, de lo contrario será false. Si este atributo no se indica, la opcion default que se tomará en la gramatica será false.

Start Symbol: Se debe de indicar el simbolo no terminal, inicial de la gramatica. Al cual el LALR debe reducirse. Este es el unico parametro que debe indicarse como obligatorio.

Page 80: GoldParser

Gold Parser proporciona cuatro pasos para la compilación de la gramática y que son necesarios para la generación de las salidas que pueda construir esta herramienta, tal el caso de los skeleton, y las opciones que pueden ser de utilidad como mostrar tabla de estados del LALR, tabla de estados del DFA, además de las pruebas que pueda realizarse para comprobar el funcionamiento de la gramática dentro de la herramienta. Estos cuatro pasos que se mencionan se llevan a cabo por medio de un asistente, este se utiliza únicamente presionando el botón Next. El primer paso verifica los errores de sintaxis de la gramática y advierte de los terminales no utilizados.

El segundo paso calcula la tabla de estados de LALR, y de no haber errores lo genera. Dando lugar al paso tres.

Page 81: GoldParser

El tercer paso se basa en la construcción de autómatas finitos determinÍsticos (DFA)

El cuarto y último paso es el encargado de guardar tanto las tablas generadas en el paso 2(LALR) como las tablas generadas en el paso 3(DFA). Estas son guardadas en un archivo con extensión .cgt.

Se trabajara con el siguiente gramatica:

Page 82: GoldParser

Procede a realizar los cuatro pasos para la compilación de la gramatica y se guarda las tablas en el archivo .cgt.

<lenguaje> ::= <Listas> <listas> ::= <listas> ',' <lista>

| <lista> <lista> ::= '{' <numeros> '}' <numeros> ::= <numeros> ',' Number | number

Page 83: GoldParser

Habiendo compilado la gramática debemos de crear los skeleton que se usaran en el programa, en este caso se trata de Visual Basic.

Page 84: GoldParser

Descargar el Motor .NET a utilizar

En la página de Gold Parser, ir a download

Page 85: GoldParser

En la parte de Engines, dirigirse a Visual Basic .NET

Donde se debe de descargar el motor Klimstra

Page 86: GoldParser

Selecciona el DLL

Archivo GoldParser.dll

El archivo descargado dll debe de copiarse en la carpeta del proyecto en /bin/Debug. Es mejor si esta en esta ubicación ya que es donde se encuentra el ejecutable del proyecto, de lo contrario podría copiarse en donde este ese ejecutable.

Page 87: GoldParser

Dentro del proyecto se debe agregar como referencia la el archivo dll, Se debe dirigir hacia ProyectoàAgregar Referencia.

Page 88: GoldParser

En la pestaña de Examinar se busca el archivo GoldParser.dll que se copio en la carpeta Debug o bien donde se halla ubicado el ejecutable.

Lo que sigue es agregar el archivo .cgt que se genero al momento de la compilación de la gramática. Realizamos los siguientes pasos:

Clic derecho en la carpeta à Agregar à Elemento existente…

Page 89: GoldParser

Se busca el archivo .cgt y agrega al proyecto.

Lo que sigue es darle el tipo de acceso que tendrá el archivo. Entonces se selecciona las propiedades del archivo .cgt agregado

Page 90: GoldParser

En la opcion de Accion de Compilacion se debe seleccionar Recurso Incrustado.

Page 91: GoldParser

Guatemala Centro América Universidad San Carlos de Guatemala

Facultad de Ingeniería Escuela de ciencias y Sistemas

Org. De Lenguajes y compiladores 2

Integrantes

Juan J. Cruz 2004-12979 Joel Jimenez 2004-13135 Walter Ajanel 2005-15897 Mariano Sandoval 2007-15303 Jhony Quiem 2008-19401