Você está na página 1de 75

Compiladores e Intrpretes

Manual del Programador

Lenguaje MiniPascal

Autores: Mayra Echandi, Agustin Ramone

Contenidos
1. Introduccin General 2. Introduccin a Mini-Pascal 3. Gramtica BNF 4. Anlisis Lxico 5. Anlisis Sintctico 6. Mquina Virtual de Mini-Pascal 7. Anlisis Semntico y Generacin de Cdigo 8. Compilador 9. Archivo de Configuracin 10. Modo de Ejecucin

1. Introduccin General
En este documento se da una descripcin general del proyecto de la materia Compiladores e Intrpretes, dictada en el segundo cuatrimestre de 2006, en la Universidad Nacional del Sur. Brevemente el mismo consisti de la definicin, diseo, implementacin y testeo de un compilador para un subconjunto del lenguaje Pascal; este sublenguaje es llamado Mini-Pascal y esta basado en el reporte de Pascal (User Manual and Report, segunda edicin, Jensen-Wirth). El lenguaje escogido para la implementacin ha sido Java; en particular se ha utilizado el JDK 1.5 y el entorno de desarrollo NetBeans 5. Etapas del proyecto: - Introduccin a Mini-Pascal: describe las principales caractersticas, restricciones y observaciones sobre el lenguaje para el cual se construyo el compilador. - Gramtica: BNF del lenguaje Mini-Pascal. - Anlisis Lxico: Descripcin del alfabeto y componentes lxicos de Mini-Pascal, as como detalles de diseo e implementacin de analizador lxico. - Anlisis Sintctico: Descripcin de la gramtica modificada con el fin de hacerla apropiada para la implementacin mediante un analizador sintctico descendente predictivo y recursivo. Tambin se dan detalles del analizador sintctico implementado para esta gramtica. - Maquina Virtual de Mini-Pascal: Descripcin del lenguaje intermedio MEPA y del intrprete implementando el mismo. - Anlisis Semntico y Generacin de Cdigo: Esquema de traduccin aplicado sobre la gramtica modificada Mini-Pascal. Este esquema considera la traduccin al lenguaje intermedio as como los chequeos y estructuras de soporte para rasgos dependientes del contexto del lenguaje Mini-Pascal. - Compilador: Descripcin de la implementacin del esquema dado en la seccin anterior. Esta implementacin es el objetivo final del proyecto, y consiste del compilador completo para el lenguaje Mini-Pascal.

2. Introduccin a Mini-Pascal
A continuacin se describen las principales caractersticas de este lenguaje; como su nombre lo indica este es un sub-lenguaje de Pascal, por lo tanto la exposicin se har planteando igualdades y/o restricciones con respecto a este ltimo. Una descripcin formal de la sintxis se dar en la seccin III.

2.1. Especificacin de Mini-Pascal


El lenguaje para el que se construir el compilador cuenta con los siguientes elementos: I. Declaraciones de constantes, tipos, variables. No existen declaraciones de etiquetas. II. Constructores de tipos: a) Identidad b) Subrango de enteros c) Arreglos de una nica dimensin, cuyas componentes son de tipo simple. 2

III. Declaracin de funciones y procedimiento. El pasaje de parmetros tanto de los procedimientos como de las funciones, ser por valor o por referencia. Es importante tener en cuenta que en Mini-Pascal no se admiten procedimientos ni funciones como parmetros. Cabe aclarar que al igual que en reporte de Pascal, no se consideran declaraciones forward. IV. Los constructores de sentencias son: a) sentencia compuesta (begin-end). b) sentencia de asignacin. c) sentencia condicional (if-then o if then- else). d) sentencia while. e) sentencia case. f) sentencia vaca. V. Expresiones aritmticas con los operadores: +, - , * y div. VI. Expresiones booleanas con los operadores: And, Or, Not y aquellas formadas utilizando los operadores de comparacin: >, <, =, >=, <= y <> entre expresiones aritmticas y booleanas. En el ltimo caso se toma a los valores booleanos como si fuesen definidos en tipo enumerado: (false, true); es decir false<true. Esto sigue la especificacin dada en el reporte de Pascal. VII. Cuenta con el siguiente conjunto de identificadores predefinidos: a) Constantes: true, false (boolenas) y maxint (entera). La ltima siendo el mayor entero positivo representable; dependiente de la implementacin. b) Tipos: Integer y Boolean. c) Funciones: succ (sucesor) y pred (predecesor). Pueden aceptar un solo parmetro de tipo integer. d) Procedimientos: read, readln, write y writeln. Estos procedimientos pueden aceptar una cantidad arbitraria de parmetros de tipo integer. VIII. El chequeo de tipos se har en todos los casos por estructura.

2.2. Consideraciones sobre el lenguaje


Es importante tener presente las siguientes restricciones del lenguaje: 1. Todos los programas de Mini-Pascal tienen encabezamiento, es decir comienzan con la forma: Program <identificador>; En particular, el encabezamiento no tiene parmetros. 2 No se permiten declaraciones mltiples de constante ni de tipos. Por ejemplo: const id1, id2= maxintl; o Type id3,id4= tipo; no son vlidos. 3 En el caso de las declaraciones de variables, las declaraciones mltiples son permitidas. Se permite por ejemplo una declaracin como la siguiente: var id5,id6 :tipo

4. De igual manera que en reporte de Pascal, se permite en la declaracin de variables que el tipo sea directamente descrito o referenciado mediante un identificador de tipo.

3. Gramatica BNF
Notacin y terminologa <smbolo-especial> :: = + | - | * | = | <> | < | > | <= | >= | ( | ) | [ | ] | { | } | := | . | .. | ; | , | : | div | or | and | not | if | then | else | case | of | while | do | begin | end | const | var | type | array | function | procedure | program <letra> ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z <digito> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Identificadores y nmeros <identificador> ::= <letra> { <letra-o-digito>} <letra-o-digito> ::= <letra> | <digito> <sec-digitos> ::= <digito> { <digito> } <entero-signado> ::= <signo> <entero-no-signado> <entero-no-signado> ::= <sec-digitos> <signo> :: = + | C onstantes <declaracin de constante> ::= <identificador> = <constante> <constante> ::= <entero-signado> | <entero-no-signado> | <identificador> | <signo> <identificador> Definicin de Tipos <definicin de tipo> :: = <identificador> = <tipo> <tipo> ::= <tipo simple> | array [ < tipo simple > ] of <tipo simple> <tipo simple> ::= <tipo subrango> | <identificador> <tipo subrango>::= <constante> .. <constante>

Declaracin de variables <declaracin de variable> ::= <identificador> {, <identificador>} : <tipo> 4

<variable> ::= <identificador> | <variable componente> <variable componente>::= <identificador > [ <expresin> ] Expresiones <expresin> ::= <expresin simple> | <expresin simple> <operador relacional> <expresin simple> <expresin-simple> ::= <termino> | <expresin simple> <operador sumador> <termino> | <signo> <termino> <termino> ::= <factor> | <termino> <operador multiplicador> <factor> <factor> ::= <variable> | <constante no signada> | <llamada a funcin> | ( <expresin> ) | not <factor> <constante no signada> ::= <entero no signado> | <identificador> Operadores <operador multiplicador> ::= * | div | and <operador sumador> ::= + | - | or <operador relacional> ::= = | <> | < | > | <= | >= Llamada a Funcin <llamada a funcin> ::= <identificador> | <identificador> ( <parmetro actual> {, <parmetro actual>}) Sentencias <sentencia> ::= <sentencia simple> | <sentencia estructurada> <sentencia simple> ::= <sentencia asignacin> | <llamada a procedimiento> | <vaco> 5

Sentencia de Asignacin <sentencia asignacin> ::= <variable> := <expresin> Sentencia Estructurada <sentencia estructurada> ::= <sentencia compuesta> | <sentencia condicional> | <sentencia while> Sentencia Compuesta <sentencia compuesta> ::= begin <sentencia> {; <sentencia>} end Sentencia Condicional <sentencia condicional>::= <sentencia if> | <sentencia case> Sentencia If <sentencia if> ::= if <expresin> then <sentencia> [ <parte else>] <parte else> ::= else <sentencia> Sentencia Case <sentencia case> ::= case <expresin> of <lista elementos case> {; <lista elementos case>} end <lista elementos case> ::= <etiqueta lista case> : <sentencia> | <vaco> <etiqueta-lista-case> ::= <constante > {, <constante>} Sentencia While <sentencia while> ::= while <expresin> do <sentencia> Declaracin de Procedimientos <declaracin de procedimiento> ::= <encabezado de procedimiento> <bloque> <encabezado de procedimiento> ::= procedure <identificador>; | procedure <identificador> (<seccin de parmetros formales> {;<seccin de parmetros formales>} ) ; <seccin de parmetros formales> ::= <grupo de parmetros> | var <grupo de parmetros> <grupo de parmetros> ::= <identificador> {,<identificador>} : <identificador> Llamada a procedimiento <llamada a procedimiento> ::= <identificador> | <identificador > ( <parmetro actual> {, <parmetro-actual>}) 6

<parmetro actual>::= <expresin> Bloque <bloque> ::= <seccin definicin constantes> <seccin definicin de tipos> <seccin definicin de variables> <seccin declaracin de funciones y procedimientos> <sentencia compuesta> Seccion Definicin de Constantes <seccin definicin constantes> ::= <vaco> | const <declaracin de constante> {; <declaracin de constante>}; Seccin Definicin de Tipos <seccin definicin de tipos> ::= <vaco> | type <definicin de tipo> {; <definicin de tipo>}; Seccin Definicin de Variables <seccin definicin de variables> ::= <vacio> | var <declaracin de variable> {; <declaracin de variable>}; Seccin de declaracin de Procedimientos y Funciones <seccin declaracin de funciones y procedimientos>::= {<declaracin de procedimiento> | <declaracin de funcin>} Declaracin de Funciones <declaracin de funcin> ::= <encabezado de funcin> <bloque> <encabezado de funcin> ::= function <identificador> : <identificador>; | function <identificador> (<seccin de parmetros formales> {;<seccin de parmetros formales>}) : <identificador>; Programa Mini-Pascal <programa> ::= program <identificador>; <bloque>.

4. Anlisis Lxico - Alfabeto: ={ A,B,C,D,E,F,G,H,I,J,K,L,M,N,,O,P,Q,R,S,T,U,V,W,X,Y,Z, a,b,c,d,e,f,g,h,i,j,k,l,m,n,,o,p,q,r,s,t,u,v,w,x,y,z, 0,1,2,3,4,5,6,7,8,9, . , , , ; , : , ( , ) , = , < , >, + , - , * , { , } , [ , ] , EOF ,<espacio en blanco> , <tabulacion> , <retorno de linea> , <retorno de linea> } 2- Componentes Lxicos (tokens)
Nombre de Token ID NUMERO PUNTO Y COMA PUNTO PUNTO_PUNTO DOS_PUNTOS COMA PAR_ABRE PAR_CIERRA COR_ABRE COR_CIERRA PROGRAM CONST TYPE VAR ARRAY BEGIN END PROCEDURE FUNCTION IF THEN ELSE CASE OF WHILE DO ASIGNACION OP_RELACIONAL OP_SUMA OP_RESTA OP_MULT OP_DIV NOT AND Lexema ; . .. : , ( ) [ ] program const type Var Array Begin End Procedure Function If Then Else Case Of While Do := <,>,<=,>=,<> + * Div Not And Expresin Regular Letra{letra | digito } Digito digito* ; . .. : , ( ) [ ] (P|p)(r|R)(o|O)(g|G)(r|R)(a|A)(m|M) (c|C)(o|O)(n|N)(s|S)(t|T) (t|T)(y|Y)(p|P)(e|E) (v|V)(a|A)(r|R) (a|A)(r|R)(r|R)(a|A)(y|Y) (b|B)(e|E)(g|G)(i|I)(n|N) (e|E)(n|N)(d|D) (P|p)(R|r)(O|o)(C|c)(E|e)(D|d)(U|u)(R|r)(E|e) (f|F)(u|U)(n|N)(c|C)(t|T)(i|I)(o|O)(n|N) (I|i)(F|f) (t|T)(h|H)(e|E)(n|N) (e|E)(l|L)(s|S)(E|e) (c|C)(a|A)(s|S)(e|E) (O|o)(F|f) (w|W)(h|H)(i|I)(l|L)(e|E) (d|D)(o|O) := (<|>|<=|>=|<>) + * (d|D)(i|I)(v|V) (N|n)(O|o)(T|t) (a|A)(n|N)(D|d) 8

OR IGUAL EOF

Or Igual

(o|O)(r|R) (i|I)(g|G)(u|U)(a|A)(l|L)

3. Decisiones de implementacin
3.1 Descripcin de las clases Nota: En esta seccin describimos brevemente las clases involucradas en el proyecto. Puede ver la documentacin precisa de todos los mtodos de cada clase en el directorio dist/javadoc/. aLexico.Reader.java: Es una interface que permite construir cualquier lector de cdigo fuente. En este proyecto es implementada por la clase BufferedFileReader. aLexico.BufferedFileReader.java: Realiza la lectura de los caracteres del archivo fuente. Esta clase hereda de BufferedReader ya que permite realizar una lectura eficiente. aLexico.LexicException: Clase que hereda de Exception y permite crear excepciones cuando se encuentra un error en el anlisis lxico. aLexico.Token.java: Representa a los tokens del lenguaje. ALexico.java: Se encarga de realizar el anlisis lxico. Contiene un mtodo principal llamado nexToken() que retorna el prximo Token del cdigo fuente. Main.java: Permite analizar un archivo fuente. Invocando sucesivamente al mtodo nexToken() de la clase ALexico permite obtener la lista de tokens del lenguaje. Testeador.java: Permite analizar un archivo simple o varios archivos dentro de un directorio (y archivos de subdirectorios).

3.2 Decisiones de diseo del Analizador lxico: - Se cre la interface Reader para poder crear cualquier lector de cdigo fuente. Bsicamente un lector de cdigo fuente debe proveer el mtodo readCharacter() para proporcionar el siguiente carcter al analizador lxico. - Se creo la clase BufferedFileReader. Bsicamente es un lector de cdigo fuente (implementa la interface Reader) que realiza buffering en la lectura de los caracteres. Esto da mayor eficiencia al analizador lexico. - Se utiliza un atributo privado numLinea, para almacenar el nmero de lnea actual - Se utiliza una estructura HashMap para crear la tabla de palabras reservadas. Esta estructura permite saber eficientemente si un determinado identificador es palabra reservada o no, es decir, si esta contenido en dicha tabla. - Se utilizan estructuras HashSet para representar los conjuntos de letras, dgitos y separadores. Esta estructura permite conocer eficientemente si un carcter forma parte del conjunto dado. Por ejemplo: if (digitos.contains(new Character(8))) 9

- Se aadieron dos constructores. Uno que recibe el nombre del archivo a analizar y otro que recibe un lector de cdigo fuente. Este ltimo nos da la flexibilidad de poder analizar lxicamente cualquier secuencia de caracteres, ya sea un archivo, un string, un socket, etcEn particular podemos implementar cualquier lector siempre y cuando respete (implemente) la interface Reader. - El carcter fin de archivo lo representamos como el objeto Character nulo. Es decir: Character EOF = null; - Se cre el metodo leerCaracter donde se chequea si el carcter ledo es fin de lnea o no. Si es fin de lnea se incrementa el atributo numLinea de la clase.

5. Anlisis Sintctico
En esta seccion nos ocuparemos de la construccin de un analizador sintctico descendente predictivo y recursivo para el lenguaje Mini-Pascal. Para ello, se deber retocar la gramtica original para que pueda ser procesada por un automata (sin back-tracking) y poder efectivamente testear si un programa es sintcticamente vlido. Una de las reformas a la gramtica original es la eliminacin de la recursin a izquierda, tanto inmediata como no inmediata. Por ejemplo, no debemos permitir producciones de la forma: A Aa ni tampoco A Ba B Aa (recursin no inmediata), donde las letras maysculas son no-terminales. Es sumamente importante librarse de la recursin a izquierda ya que de otra forma el automata puede entrar en un lazo infinito (recordemos que cada no-terminal es un procedimiento): A Aa, A Aaa, A Baaa, A Aaaaaaa. Otra modificacin a la gramtica original es la de factorizacin de las producciones. La factorizacin consiste en optimizar aquellas producciones que comienzan con la misma cadena del lado derecho. Por ejemplo si tenemos la produccin AabCd y la produccin AabEe, podemos factorizar y obtener: AabR y RCd | Ee La ambigedad es otra caracterstica no deseable dado que no se puede aplicar este mtodo de anlisis sintctico con gramticas ambiguas. Sin embargo, la gramtica de mini-pascal es ambigua en la sentencia if, asi que mas adelante se presenta una manera de resolver este problema. Por ltimo, resta eliminar las construcciones repetitivas y opcionales (encerradas entre los smbolos { } y [ ] respectivamente), de la BNF original.

Gramtica Factorizada y Reducida a Izquierda


Convenciones de notacin: - Las producciones encerradas en los cuadros grises muestran las producciones originales de la gramtica sin factorizacin ni reduccin a izquierda. - El smbolo <vaco> de la gramtica original se reemplaz por el smbolo lambda .

10

- Los nombres de no-terminales siguen el estilo de los identificadores de Java, es decir, si son mas de una palabra aparecen pegadas y la primer letra de cada palabra (menos la primera) en maysculas. Ejemplo: noTerminal, terminal, otroNoTerminal. Programa <programa> ::= program <identificador>; <bloque>. <programa> ::= program <identificador>; <bloque>. Bloques <bloque> ::= <seccin definicin constantes> <seccin definicin de tipos> <seccin definicin de variables> <seccin declaracin de funciones y procedimientos> <sentencia compuesta> <bloque> ::= <seccionDefinicionDeConstantes> <seccionDefinicionDeTipos> <seccionDefinicionDeVariables> <seccionDeclaracionProcYFunciones> <sentenciaCompuesta> Seccin de Definicin de constantes <seccin definicin constantes> ::= <vaco> | const <definicion de constante> {; <declaracin de constante>}; < seccionDefinicionDeConstantes > ::= | const <definicionDeConstante> ;<restoDefinicionDeConstante> <restoDefinicionDeConstante> ::= <definicionDeConstante> ; <restoDefinicionDeConstante>|

<definicion de constante> ::= <identificador> = <constante> <constante> ::= <entero-signado> | <entero-no-signado> | <identificador> | <signo> <identificador>

<definicionDeConstante> ::= <identificador> = <constante>

11

<constante> ::= - <idConstante> | +<idConstante> | <idConstante> <idConstante> ::= <sec-digitos> | <identificador> Seccin de Definicin de tipos <seccin definicin de tipos> ::= <vaco> | type <definicin de tipo> {; <definicin de tipo>};

<seccionDefinicionDeTipos> ::= | type <definicinDeTipo> ; <restoDefinicionDeTipo> <restoDefinicionDeTipo> ::= <definicinDeTipo> ; <restoDefinicionDeTipos>|

<definicin de tipo> :: = <identificador> = <tipo> <tipo> ::= <tipo simple> | array [ < tipo simple > ] of <tipo simple> <tipo simple> ::= <tipo subrango> | <identificador> <tipo subrango>::= <constante> .. <constante> <definicinDeTipo> :: = <identificador> = <tipo> <tipo> ::= <tipoSimple> | array [<tipoSimple>] of <tipoSimple> <tipoSimple> ::= <identificador> <restoTipoSimple> | <sec-digitos> .. <constante> | + <restoSubrango> | - <restoSubrango> <restoSubrango>::= <identificador> .. <constante> | <sec-digitos> .. <constante> <restoTipoSimple>::= .. <constante> | Seccin de Definicin de variables <seccin definicin de variables> ::= <vacio> | var <declaracin de variable> {; <declaracin de variable>}; < seccionDefinicionDeVariables > ::= | var <declaracinDeVariables> ; <restoDefinicionDeVariables> < restoDefinicionDeVariables> ::= | <declaracinDeVariables> ; <restoDefinicionDeVariables >

<declaracin de variable> ::= <identificador> {, <identificador>} : <tipo> <variable> ::= <identificador> | <variable componente> <variable componente>::= <identificador > [ <expresin> ] 12

<declaracionDeVariables> ::= < listaIdentificadoresDeVariables>: <tipo> <listaIdentificadoresDeVariables> ::= <identificador> < restoListaIdentificadoresDeVariables> <restoListaIdentificadoresDeVariables> ::= | , <identificador> < restoListaIdentificadoresDeVariables>

Seccin de declaracin de Procedimientos y Funciones <seccin declaracin de funciones y procedimientos>::= {<declaracin de procedimiento> | <declaracin de funcin>} <seccionDeclaracionProcYFunciones > ::= | <declaracionDeProcedimiento > ; < seccionDeclaracionProcYFunciones >| <declaracinDeFuncin> ; < seccionDeclaracionProcYFunciones > Declaracin de Procedimiento <declaracin de procedimiento> ::= <encabezado de procedimiento> <bloque> <encabezado de procedimiento> ::= procedure <identificador>; | procedure <identificador> (<seccin de parmetros formales> {;<seccin de parmetros formales>} ) ; <seccin de parmetros formales> ::= <grupo de parmetros> | var <grupo de parmetros> <grupo de parmetros> ::= <identificador> {,<identificador>} : <identificador> <declaracinDeProcedimiento> ::= <encabezadoDeProcedimiento > <bloque> <encabezadoDeProcedimiento > ::= procedure <identificador> < restoEncabezadoDeProcedimiento > <restoEncabezadoDeProcedimiento > ::= ; | ( < listaParametrosFormales> ) ; < listaParametrosFormales >::= <grupoDeParametros > < restoListaParametrosFormales > <restoListaParametrosFormales >::= | ; <grupoDeParametros> < restoListaParametrosFormales > <grupoDeParametros > ::= < listaIdentificadorParametroFormales > : <identificador> | var <listaIdentificadorParametroFormales>: <identificador> 13

<listaIdentificadorParametroFormales >::= <identificador> < restoListaIdentificadorParametroFormales > <restoListaIdentificadorParametroFormales >::= | , <identificador> < restoListaIdentificadorParametroFormales > Declaracin de Funcin <declaracin de funcin> ::= <encabezado de funcin> <bloque> <encabezado de funcin> ::= function <identificador> : <identificador>; | function <identificador> (<seccin de parmetros formales> {;<seccin de parmetros formales>}) : <identificador>; <declaracionDeFuncion > ::= <encabezadoDeFuncion > <bloque> <encabezadoDeFuncion > ::=function <identificador> < restoEncabezadoDeFuncion > <restoEncabezadoDeFuncion > ::= : <identificador>; | ( < listaParametrosFormales >) : <identificador>; Sentencias <sentencia> ::= <sentencia simple> | <sentencia estructurada> <sentencia simple> ::= <sentencia asignacin> | <llamada a procedimiento> | <vaco> <sentencia asignacin> ::= <variable> := <expresin> <sentencia estructurada> ::= <sentencia compuesta> | <sentencia condicional> | <sentencia while> <sentencia condicional>::= <sentencia if> | <sentencia case> <sentencia> ::= <sentenciaSimple > | < sentenciaCompuesta > | <sentenciaIF> | <sentenciaCASE> | <sentenciaWHILE> <sentenciaSimple> ::= | <identificador> < restoSentenciaSimple > <restoSentenciaSimple > ::= | := <expresin> | [<expresin>] := <expresin> | ( < listaParametrosActuales >)

<sentencia compuesta> ::= begin <sentencia> {; <sentencia>} end 14

<sentenciaCompuesta > ::= begin <sentencia> < restoSentencia >end <restoSentencia > ::= ; <sentencia> < restoSentencia > |

<sentencia if> ::= if <expresin> then <sentencia> [ <parte else>] <parte else> ::= else <sentencia> <sentenciaIF> ::= if <expresin> then <sentencia> <restoSentenciaIF> <restoSentenciaIF > ::= else <sentencia>|

<sentencia case> ::= case <expresin> of <lista elementos case> {; <lista elementos case>} end <lista elementos case> ::= <etiqueta lista case> : <sentencia> | <vaco> <etiqueta-lista-case> ::= <constante > {, <constante>} <sentenciaCASE> ::= case <expresin> of < listaElementosCASE > end <listaElementosCASE> ::= < etiquetaListaCASE > <restoListaElementosCASE> <etiquetaListaCASE> ::= <constante > < restoEtiquetas > : <sentencia> | <restoEtiquetas> ::= ,<constante> < restoEtiquetas > | <restoListaElementosCASE> ::= ; <listaElementosCASE> |

<sentencia while> ::= while <expresin> do <sentencia> <sentenciaWHILE> ::= while <expresin> do <sentencia> Expresiones <expresin> ::= <expresin simple> | <expresin simple> <operador relacional> <expresin simple> <operador relacional> ::= = | <> | < | > | <= | >= <expresin> ::= < expresionSimple > < restoExpresion > < restoExpresion > ::= <operadorRelacional> < expresionSimple > |

15

<operadorRelacional> ::= <> | < | > | <= | >=

<expresin-simple> ::= <termino> | <expresin simple> <operador sumador> <termino> | <signo> <termino> <operador sumador> ::= + | - | or <expresionSimple > ::= <termino> < restoExpresionSimple >| - <termino> < restoExpresionSimple >| + <termino> < restoExpresionSimple > <restoExpresionSimple > ::= | <operadorSumador> <termino>< restoExpresionSimple > <operadorSumador> ::= + | - | or

<termino> ::= <factor> | <termino> <operador multiplicador> <factor> <operador multiplicador> ::= * | div | and <termino> ::= <factor> <restoTermino> <restoTermino> ::= <operadorMultiplicador> <factor> <restoTermino>| <operadorMultiplicador> ::= * | div | and

<factor> ::= <variable> | <constante no signada> | <llamada a funcin> | ( <expresin> ) | not <factor> <constante no signada> ::= <entero no signado> | <identificador> <llamada a funcin> ::= <identificador> | <identificador> ( <parmetro actual> {, <parmetro actual>}) <parmetro actual>::= <expresin> | <variable> <factor> ::= <identificador> <restoFactor>| <sec-digitos> | ( <expresin> ) | 16

not <factor> <restoFactor> ::= [expresion] | (<listaParametrosActuales>) | <listaParametrosActuales > ::= | <expresion > < restoListaParametrosActuales > <restoListaParametrosActuales > ::= | , <expresion > <restoListaParametrosActuales >

Es la gramtica de tipo LL(1)?


La gramtica anterior NO es de tipo LL(1) pues la sentencia if es ambigua y por lo tanto tambin lo es la gramtica. La ambigedad se manifiesta al encontrar dos rboles sintcticos diferentes para una misma cadena. Ejemplo: Dada la cadena if exp1 then if exp2 then S1 else S2, se obtienen los siguientes rboles sintcticos:

sentenciaIF if expresin then sentencia else sentencia S2 exp1 if expresin exp2 sentenciaIF then sentencia S1

if

exp1 then

sentencia

if

exp2

then

sentencia S1

else

sentencia S2

17

Para solucionar este problema asociaremos un else al ltimo then, por lo tanto el segundo rbol es el que genera nuestro compilador.

Decisiones de Diseo del Analizador Sintctico


Manejo de errores mediante Excepciones: Se clasificaron los distintos tipos de errores en excepciones lxicas y excepciones sintcticas. Cada tipo de excepcin representa una clase que hereda de una excepcin bsica cuya utilidad es de proveer una plantilla para las clases hijas. Esta plantilla contiene el cdigo de error y un hashtable que mapea cdigos a mensajes de error. Todas estas excepciones heredan de java.lang.Exception, de manera tal que todas permiten obtener el mensaje de error mediante el mtodo getMessage(). Ejecucin/Testeo genrico de entidades testeables: Se cre una interface Testeable y una clase Testeador que testea aquellos objetos que implementen dicha interface. La idea surgi para no tener que escribir un main diferente tanto para el analizador lxico como para el sintctico (o cualquier otro); en vez de eso, ambos implementan la interface Testeable.

Ejemplo: java Testeador <clase testeable> archivo.pas Donde <clase testeable> puede ser aLexico.AnalizadorLexico o aSintactico.AnalizadorSintactico (o cualquier otra que implemente Testeable). Si en vez de ejecutar desde lnea de comandos deseamos hacerlo desde el cdigo, entonces debemos construir el objeto testeable. Ejemplo: Testeador t = new Testeador(archivo.pas,new AnalizadorLexico()); t.start(); Testea el analizador Lxico Testeador t2 = new Testeador(archivo.pas,new AnalizadorSintactico()); t2.start(); Testea el analizador sintactico Bsicamente el metodo start invoca al metodo run() de la interface testeable, que cada clase implementa de forma particular. Restauracin de lectura de tokens: Para aquellas producciones lambda (vacio), se utiliza una variable global booleana restaurarToken que permite saltear la prxima lectura de un token. Lectura de tokens: Un mtodo de la clase AnalizadorSintactico se encarga de pedir al analizador lxico los tokens. Este mtodo llamado nextToken, controla si el flag restaurarToken es true o false. Si es true entonces retorna el ltimo token leido en la llamada previa a nextToken, mientras que si es false invoca al analizador lxico para retornar un nuevo token.

Descripcin de las Clases


aLexico.Reader.java: Es una interface que permite construir cualquier lector de cdigo fuente. En este proyecto es implementada por la clase BufferedFileReader. 18

aLexico.BufferedFileReader.java: Realiza la lectura de los caracteres del archivo fuente. Esta clase hereda de BufferedReader ya que permite realizar una lectura eficiente. exceptions.BasicException: Es la clase padre de las excepciones y provee una plantilla para las clases hijas. Esta plantilla contiene el cdigo de error y un hashtable que mapea cdigos a mensajes de error. exceptions.LexicException: Clase que hereda de BasicException y permite crear excepciones cuando se encuentra un error en el anlisis lxico. aLexico.Token.java: Representa a los tokens del lenguaje. aLexico.AnalizadorLexico.java: Se encarga de realizar el anlisis lxico. Contiene un mtodo principal llamado nexToken() que retorna el prximo Token del cdigo fuente. Otro mtodo principal run(), que redefine de la interface Testeable, realiza un test pidiendo tokens hasta encontrar el fin de archivo o un error. aSintactico.AnalizadorSintactico: Se encarga de realizar el anlisis sintctico del programa fuente. El mtodo run() comienza el anlisis y adems forma parte del test. exceptions.SintacticException: Clase que hereda de BasicException y permite crear excepciones cuando se encuentra un error en el anlisis sintctico main.Testeable.java: Permite crear objetos testeables. Las clases que implementen esta interface deben redefinir tres mtodos: o El mtodo run(): con el cdigo propio del test. o El metodo setSourceFile(String file): especifica el archivo fuente a testear o El mtodo finish(): permite a las clases realizar acciones luego del test (ej, cerrar el archivo fuente) Las clases AnalizadorLexico y AnalizadorSintactico implementan esta interface, de manera que ambas tienen los tres mtodos descriptos anteriormente y pueden ser testeadas por el objeto Testeador. main.Testeador.java: Permite ejecutar objetos testeables. Un objeto es testeable si y solo si implementa la interface Testeable. El mtodo principal start() se encarga de invocar al metodo run() del objeto a testeable y manejar las excepciones e informe de errores. main.Main.java: Contiene simplemente el mtodo main. En esta entrega se encarga de construir un Testeador con el archivo fuente dado por lnea de comandos y el objeto AnalizadorSintactico a testear. public static void main(String[] args) { Testeador t = new Testeador(args[0], new AnalizadorSintactico()); t.start(); }

19

Descripcin de los Errores Sintcticos


Cdigo 0 1 2 3 4 5 Mensaje Se espera 'program' Se espera un identificador Se espera un punto y coma ';' Se espera un punto '.' Se espera = Se espera alguna de las siguientes palabras reservadas: const,type,var,procedure,function o begin Se espera un identificador de tipo o alguna de las siguientes palabras reservadas: var,procedure,function o begin se espera un numero o identificador de constante Se espera un identificador de constante o alguna de las siguientes palabras reservadas: type,var,procedure,function o begin identificador de tipo invalido Se espera un identificador o constructor de tipo Simple valido Se espera un [ Se espera un ] Se espera un of 13 14 15 Se espera un identificador de variable o alguna de las siguientes palabras reservadas: procedure,function o begin Se espera un ')' Se espera ';' o falta la lista de parmetros formales. Se espera 'var' o un identificador Se espera '..' Se espera un ':' Luego de una definicin de constante sigue algo distinto a definicin de constante o a alguna de las siguientes palabras reservadas: type,var,procedure,function o begin Despus de = o : en la definicin de tipo no sigue un identificador de tipo valido Se omite el smbolo [ en la definicin de un tipo array o en el uso de una variable array Se omite el smbolo ] en la definicin de un tipo array o en el uso de una variable array Se omite la palabra reservada of en una definicin de tipo array o en una estructura case Se omite el smbolo .. en la definicin de un tipo subrango Se omite el smbolo : cuando se especifica el tipo en una dec de variable, parmetro formal, tipo retorno de funcin o en un item de la estructura case. Luego de una definicin de variable sigue algo distinto a definicin de variable o a alguna de las siguientes palabras reservadas: procedure, function o begin Se omite el smbolo ) En la definicin de procedimiento o funcin luego del parntesis o punto y coma viene algo distinto a la palabra reservada var o identificador 20 Descripcin Se omite la palabra reservada program Se omite el punto y coma Se omite el punto Se omite el igual Se omiten las palabras reservadas en la seccin de declaraciones de un programa Luego de una definicin de tipo sigue algo distinto a definicin de tipo o a alguna de las siguientes palabras reservadas: var,procedure,function o begin

9 10 11 12

16 18 19 20

21 22 23 24 25 26 27 28 29 30 31 32

identificador de funcin invalido identificador de tipo de retorno invalido Se espera ':', '(' o la lista de parametros formales Se espera un begin Se espera un end Se espera := Se espera un then Se espera una constante no signada Se espera [, ( o := Se espera un 'do' "Se espera un 'while' Se espera una expresin

Despus de nombre de funcin sigue algo distinto a : o ( Se omite la palabra reservada begin Se omite la palabra reservada end Se omite el smbolo asignacin Se omite la plabar reservada then Se omite palabra reservada do Se omite la palabra reservada while

6. Mquina Virtual de Mini-Pascal


En esta seccin nos ocuparemos de la construccin de un intrprete de MEPa. La MEPa significa Maquina de Ejecucin de Pascal, y es la maquina virtual sobre la cual ejecutamos las instrucciones generadas en la fase de anlisis sintctico y semntico del lenguaje MiniPascal. Presentaremos las caractersticas generales de la MEPa junto a su set de instrucciones, luego analizaremos aquellas cuestiones que hacen a la organizacin del proyecto y su implementacin: decisiones de diseo, descripcin de errores, descripcin de las clases, etc.

Descripcin de la MEPA
Describiremos en esta seccin la estructura bsica de la MEPa. Una decisin importante que tomaremos ahora es que la MEPa deber ser una mquina de pila. Esto es muy natural, dado que el Pascal permite el uso de procedimientos recursivos, y la recursin est ntimamente ligada al uso de una pila. Las razones de esta decisin quedarn ms claras cuando se trate el tema de los procedimientos. Nuestra mquina de ejecucin tendr una memoria compuesta por tres regiones: - La regin del programa P que contendr las instrucciones de MEPa que se ejecutarn. - Una regin de pila de datos M que contendr los valores que sern manipulados por las instrucciones MEPa. Supondremos que esta regin se compone de palabras de memoria que pueden contener valores enteros. - Un vector de direcciones de base D que contendr punteros a la regin M. Supondremos que los componentes de cada una de estas regiones estn numerados con 0, 1, 2, . . ., sin preocuparnos por las limitaciones de tamao de las mismas. La MEPa tendr dos registros especiales que sern usados para describir el efecto de las instrucciones: - El registro de contador de programa i que contendr la direccin de la prxima instruccin a ser ejecutada, la que por lo tanto ser P[i]. - El registro de tope de pila s que indicar el elemento en el tope de la pila, cuyo valor est por lo tanto en M[s]. 21

Una vez que el programa de la MEPa est cargado en la regin P, y que los registros especiales tienen sus valores iniciales, el funcionamiento de la mquina es muy simple. Las instrucciones indicadas por el registro i son ejecutadas hasta que se encuentre la instruccin de parada, o hasta que ocurra algn error. La ejecucin de cada instruccin, excepto las de desvo, incrementa el valor de i en uno. A continuacin, describiremos el repertorio de las instrucciones de la MEPa motivadas por las construcciones de MiniPascal.

Repertorio de Instrucciones
La siguiente tabla contiene una entrada para cada instruccin. En dicha entrada se especifica la instruccin MEPa, su accin en la maquina virtual (*) y su descripcin. (*) Elegimos el lenguaje java para implementar la mepa, por lo tanto las acciones estn traducidas directamente en Java. Instruccin APCT k SUMA SUST MULT DIVI MODU UMEN CONJ DISJ NEGA CMME CMMA CMIG CMDG CMNI CMYI DUPT DSVS Ln DSVF Ln Accin s++; M[s] = k Descripcin Apila una constante Suma Resta Multiplicacin Divisin Modulo Menos unario

M[s-1] += M[s]; s--; M[s-1] -= M[s]; s--; M[s-1] *= M[s]; s--; M[s-1] /= M[s]; s--; M[s-1] %= M[s]; s--; M[s] = -M[s]

M[s-1] = ((M[s-1]==1 && M[s]==1) ? 1 : 0); sConjuncin lgica -; M[s-1] = ((M[s-1]==1 || M[s]==1) ? 1 : 0); s--; M[s] = 1 - M[s]; M[s-1] = (M[s-1] < M[s]) ? 1 : 0; s--; M[s-1] = (M[s-1] > M[s]) ? 1 : 0; s--; M[s-1] = (M[s-1] == M[s]) ? 1 : 0; s--; M[s-1] = (M[s-1] != M[s]) ? 1 : 0; s--; M[s-1] = (M[s-1] <= M[s]) ? 1 : 0; s--; M[s-1] = (M[s-1] >= M[s]) ? 1 : 0; s--; s++; M[s] = M[s-1]; i=p if(M[0] == 0) i = p; s--; Disyuncin lgica Negacin Comparar por menor Comparar por mayor Comparar por igual Comparar por desigual Comparar por menor o igual comparar por mayor o igual Duplicar el tope de la pila Desviar siempre Desviar si el tope es falso 22

NADA LEER IMPR LELN IMLN APVL m , n ALVL m , n INPP ENPR k LLPR Ln RMEM m LMEM m RTPR k , n PARA APDR m , n APVI m , n ALVI m , n APAR m , n ALAR m , n PUAR m , n , l s++; M[s] = D[m] + n; s++; M[s] = M[M[D[m] + n]]; M[M[D[m] + n]] = M[s]; s--; M[s] = M[D[m + n + M[s]]; M[D[m] + n + M[s-1]] = M[s]; s-=2; for(int k = 1; k<=l; k++){ s++; M[s] = M[D[m]+ n + k - 1]; } for(int k = l; k>=1; k--){ M[D[m] + n + k - 1] = M[s]; s--; } M[s] = M[M[D[m]+n]+M[s]]; M[M[D[m]+n]+M[s-1]] = M[s]; s-=2; s++; M[s] = leerValor(); imprimir(M[s]); s--; s++; M[s] = leerValor(); imprimir(M[s]); s--; s++; M[s] = M[D[m] + n]; M[D[m] + n] = M[s]; s--; S = -1; D[0] = 0; s++; M[s] = D[k] ; D[k] = s+1; s++; M[s] = i; i = p; s += m s -= m D[k] = M[s]; i = M[s-1]; s = s - (n + 2);

Sin accin Lectura del prximo valor en el archivo de entrada Impresin de un valor entero Idem LEER, pero baja la linea. Idem IMPR, pero baja la linea Apila el valor de una variable Almacena el tope de la pila en una variable Comienzo de programa Entrar al procedimiento de nivel k Llamar a un procedimiento de etiqueta Ln(direccion p) Reservar memoria para variables Libera memoria de variables locales Retorna de un procedimiento de nivel k con n parametros Parada de la maquina virtual Apila la direccin de una variable Apila un valor indirecto Almacena el tope de la pila en un valor indirecto o referencia Apila el elemento de un arreglo Almacena un valor en el elemento de un arreglo Carga en la pila un arreglo declarado en el nivel lxico m, con desplazamiento n y longitud l. Copia de la pila a la memoria un arreglo declarado en el nivel lxico m, con desplazamiento n y longitud l Apilar un elemento de un arreglo indirecto Modificar un elemento de un arreglo indirecto Apilar todo un arreglo indirecto con l componentes

POAR m , n , l APAI m , n ALAI m , n PUAI m , n , l

for(int k=0; k<l; k++){ s++; M[s]= M[M[D[m]+n]+k]; }

23

POAI m , n , l

for(int k =l-1; k>=0;k--){ M[M[D[m]+n]+ k] = M[s]; s--; } M[s] = D[m]+n+ M[s];

Modificar todo un arreglo indirecto con l componentes Apilar la direccin de una componente de un arreglo como parmetro por referencia Control del rango de valores donde li y ls son los lmites inferior y superior para los valores vlidos Control de divisin por cero Almacenar relativa en direccin

APDC m , n

CONT li , ls

if(M[s]<li || M[s]>ls) error();

DIVC ALDR IMLV DSVV

if(M[s] == 0) error(); M[M[s-1]] = M[s] ; s -= 2; System.out.println() if( M(s) == 1) i = p; s--;

Imprime salto de lnea Desvia si el tope es 1

Inclusin de instrucciones MePa nuevas: DSVV eti : (Desviar si es Verdadero) desva a la instruccin etiquetada con eti si el tope de la pila es 1(verdadero). if( M(s) == 1) i = p; s--; Es usada en la sentencia CASE para facilitar la generacin del cdigo. ALDR : (Almacenar en Direccin Relativa) almacena el tope de la pila en la direccin guardada en tope 1 M[M[s-1]] = M[s] ; s -= 2; Esta instruccin es til para las funciones predefinidas read y readln. Cuando leemos un valor desde teclado, este se almacena en el tope de la pila. Luego, necesitamos asignar ese valor a una variable apilada anteriormente; pero dado que aqu fue necesario apilar la direccin de dicha variable, se necesitaba contar con esta instruccin. IMLV: (Imprimir Linea Vacia): Se usa para traducir la instruccin writeln sin parmetros. Esta instruccin, a diferencia de la instruccin IMLN, no modifica el tope de la pila. Por lo tanto se pueden generar cualquier cantidad de estas instrucciones sin afectar el estado de la maquina virtual.

Anlisis Lxico Mepa


Alfabeto:

={ A,B,C,D,E,F,G,H,I,J,K,L,M,N,,O,P,Q,R,S,T,U,V,W,X,Y,Z, a,b,c,d,e,f,g,h,i,j,k,l,m,n,,o,p,q,r,s,t,u,v,w,x,y,z, 0,1,2,3,4,5,6,7,8,9, ,, ,EOF , <espacio en blanco> , <tabulacion> , <retorno de linea> , <retorno de linea> }

24

Tokens del Lenguaje Token COMA MENOS NUMERO "APCT" "SUMA" "SUST" "MULT" "DIVI" "MODU" "UMEN" "CONJ" "DISJ" "NEGA" "CMME" "CMMA" "CMIG" "CMDG" "CMNI" "CMYI" "DUPT" "DSVS" "DSVF" "LEER" "LELN" "IMPR" "IMLN" "APVL" "ALVL" "INPP" "ENPR" "LLPR" "RMEM" "LMEM" "RTPR" "APDR" "APVI" "ALVI" "APAR" "ALAR" "PUAR" "POAR" "APAI" "ALAI" "PUAI" "POAI" "APDC" "CONT" Lexema , - APCT SUMA SUST MULT DIVI MODU UMEN CONJ DISJ NEGA CMME CMMA CMIG CMDG CMNI CMYI DUPT DSVS DSVF LEER LELN IMPR IMLN APVL ALVL INPP ENPR LLPR RMEM LMEM RTPR APDR APVI ALVI APAR ALAR PUAR POAR APAI ALAI PUAI POAI APDC CONT Exp. Regular , - Digito (a|A)(p|P)(c|C)(t|T) (s|S)(u|U)(m|M)(a|A) (s|S)(u|U)(s|S)(t|T) (m|M)(u|U)(l|L)(t|T) (d|D)(i|I)(v|V)(i|I) (m|M)(o|O)(d|D)(u|U) (u|U)(m|M)(e|E)(n|N) (c|C)(o|O)(n|N)(j|J) (d|D)(i|I)(s|S)(j|J) (n|N)(e|E)(g|G)(a|A) (c|C)(m|M) (m|M)(e|E) (c|C)(m|M) (m|M)(a|A) (c|C)(m|M) (i|I)(g|G) (c|C)(m|M) (d|D)(g|G) (c|C)(m|M) (n|N)(i|I) (c|C)(m|M) (y|Y)(i|I) (d|D)(u|U)(p|P)(t|T) (d|D)(s|S)(v|V)(s|S) (d|D)(s|S)(v|V)(f|F) (l|L)(e|E) (e|E) (r|R) (l|L)(e|E) (l|L) (n|N) (i|I)(m|M)(p|P)(r|R) (i|I)(m|M)(l|L)(n|N) (a|A)(p|P)(v|V)(l|L) (a|A)(l|L)(v|V)(l|L) (i|I)(n|N) (p|P) (p|P) (e|E)(n|N)(p|P)(r|R) (l|L) (l|L)(p|P)(r|R) (r|R)(m|M)(e|E)(m|M) (l|L)(m|M)(e|E)(m|M) (r|R)(t|T)(p|P)(r|R) (a|A)(p|P)(d|D)(r|R) (a|A)(p|P)(v|V)(i|I) (a|A)(l|L)(v|V)(i|I) (a|A)(p|P)(a|A)(r|R) (a|A)(l|L)(a|A)(r|R) (p|P)(u|U)(a|A)(r|R) (p|P)(o|O)(a|A)(r|R) (a|A)(p|P)(a|A)(i|I) (a|A)(l|L)(a|A)(i|I) (p|P)(u|U)(a|A)(i|I) (p|P)(O|o)(a|A)(i|I) (a|A)(p|P)(d|D)(c|C) (c|C)(O|o)(n|N)(t|T) 25

"DIVC" "NADA" "PARA" "ALDR" "DSVV" IMLV Gramatica BNF

DIVC NADA PARA ALDR DSVV IMLV

(d|D)(i|I)(v|V)(C|c) (n|N)(a|A)(d|D)(a|A) (p|P)(a|A)(r|R)(a|A) (a|A)(l|L)(d|D)(r|R) (d|D)(s|S)(v|V)(v|V) (i|I)(m|M)(l|L)(v|V)

<Programamepa>::=INPP<listaSentensias>EOF <ListaSentencias>::=ETIQUETA<restoListaSentencias>| <instruccin><listaSentencias>| PARA <restoListaSentencias>::=<instruccin><listaSentencias>|PARA <instruccin>::= <instrucionSinParametro>| <instruccion1Parametro>| <instruccionConEtiqueta>| <instruccion2Parametros>| <instruccion2parametroSimple>| <instruccion3Parametro> <instruccionSinParametro>::=SUMA|SUST|MULT|DIVI|MODU|UMEN|CONJ| DISJ|NEGA|CMME|CMMA|CMIG|CMDG|CMNI|CMYI|DUPT|LEER| IMPR|LELN|IMLN|INPP|DIVC|NADA|PARA|IMLV <instruccion1Parametro>::=APCT<numero>| ENPR NUMERO| RMEM NUMERO| LMEM NUMERO <instruccionConEtiqueta>::=DSVS ETIQUETA| DSVF ETIQUTA| LLPR ETIQUETA| DSVV ETIQUETA <instruccion2Parametros>::= ALVL<dosParam>| APVL<dosParam>| APDR<dosParam>| APVI<dosParam>| ALVI<dosParam>| APAR<dosParam>| ALAR<dosParam| APAI<dosParam>| ALAI<dosParam>| APDC<dosParam>| ALDR <dosParam>

26

<instruccion2ParametrosSimples>::= RTPR NUMERO,NUMERO| CONT<numero>,<numero> <instruccion3Parametros>::= PUAR<tresParam>| POAR<tresParam>| PUAI<tresParam>| POAI<tresParam>| <dosParam>::=NUMERO,<numero> <tresParam>::=NUMERO,<numero>,NUMERO <numero>::= NUMERO | -NUMERO

Proceso de Carga
El proceso de carga de las instrucciones tiene lugar a medida que se analiza sintcticamente el programa. Cada instruccin cargada se va almacenando en un arreglo, de manera tal que al finalizar el proceso se pasa este arreglo a la maquina virtual para que ejecute el programa. El arreglo de instrucciones es de la forma: ArrayList <Instruccin> instrucciones;

Estrategia de resolucin de etiquetas


Se utilizan dos tablas hash. La primera tabla, llammosle T1, almacena entradas de la forma <nombre etiqueta, Objeto>, donde Objeto puede ser la direccin de la etiqueta o una lista de instrucciones que hacen referencia a la misma cuando aun no se conoce su direccin. La segunda tabla T2 mantiene las etiquetas no resueltas con entradas de la forma <nombre etiqueta, numLinea>. Cada vez que se resuelve una etiqueta se elimina de la tabla T2, de manera tal que al finalizar el proceso de carga podemos saber si nos qued alguna etiqueta no resulta. Si la tabla T2 es vaca al finalizar la carga entonces todas las etiquetas fueron resueltas, caso contrario podemos identificarlas recorriendo la tabla. Ejemplos: - Primer escenario: Supongamos que la primera aparicin de la etiqueta L1 est al comienzo de la instruccin 50: L1 SUMA En este caso e inserta la entrada [L1, 50] en la tabla T1. Luego si ms adelante se hace referencia a la etiqueta L1, ya se conoce la direccin consultando la tabla para la entrada L1. - Segundo escenario: Supongamos que la primera aparicin de la etiqueta L1 es operando de la instruccin 50: DSVF L1 En este caso la tabla T1 no contiene una entrada para L1, por lo tanto se inserta la instruccin en la lista de instrucciones que hacen referencia a L1 y luego se inserta esta lista en la entrada [L1, list] de la tabla T1. Ahora resta insertar la entrada [L1, 50] en la tabla de etiquetas no declaradas T2. Ms adelante, si aparece otra instruccin que hace referencia a L1, se agregar esta instruccin al final de la lista insertada para la entrada L1. 27

- Tercer escenario: Supongamos la aparicin de la etiqueta L1 al comienzo de la instruccin 50; anteriormente se hicieron referencias a L1 desde otras instrucciones menores a la 50, de manera que la tabla para la entrada L1 contiene la lista de estas instrucciones que la referenciaron. DSVS L1 . DSVF L1 L1 SUST En este punto ya conocemos la direccin de L1 que es 50, entonces asignamos este valor a todas las instrucciones de la lista para la entrada L1 y una vez realizado esto, actualizamos la entrada (eliminando la lista) con el nuevo valor 50. [L1,50]. Ahora solo falta actualizar la tabla T2 (de etiquetas no declaradas), eliminando la entrada para L1.

Decisiones de Diseo
Representacin de las instrucciones: Se cre una clase Instruccin que permite almacenar la siguiente informacin correspondiente a una instruccin MEPa: - nombre de la instruccion, - numero de linea - operando1, operando2, operando 3 (opcionales) - etiqueta (opcional) Resolucin de nombres de etiquetas: Esta operacin se realiza en el analizador sintctico ASMepa. Para tal fin se usaron dos Hashtables como se explic anteriormente. Anlisis sintctico de Instrucciones: En vez de crear un mtodo por cada clasificacin, el anlisis sintctico de la produccin <instruccin> de la gramtica, se implement mediante un switch en el cual se agrupan en casos aquellas instrucciones que tienen mismo nmero y tipo de parmetros. Por ejemplo, el no terminal <Instruccin> de la gramtica se veria algo parecido a esto: private void instruccin(){ Token t = AL.nextToken(); switch(t.codigo){ case SUMA: case SUST: case MULT: case DIVI: case MODU: break; case DSVS: case DSVF: leer1Parametro(); break; case TokenMepa.IMPR: case TokenMepa.LELN: case TokenMepa.IMLN: break } } 28

Para aquellas instrucciones que reciben dos parmetros (ej: ALAI y APAI), se usa un mtodo leer2Parametros(boolean , boolean), en el cual si el parmetro es true significa que el numero puede ser un valor negativo. Testing: Tanto el analizador lxico, el sintctico como la mepa implementan la interface Testeable. Esto les permite ser testeadas separadamente.

Descripcin de las Clases: exceptions.BasicException: Es la clase padre de las excepciones y provee una plantilla para las clases hijas. Esta plantilla contiene el cdigo de error y un hashtable que mapea cdigos a mensajes de error. exceptions.MepaException: Clase que hereda de BasicException y permite crear excepciones cuando se encuentra un error en el anlisis lxico, sintctico o en la ejecucin de la MEPa. mepa.Instruccin: Representa una instruccin MEPa. Mantiene el nombre, los operandos o posible etiqueta. mepa.TokenMepa: Representa a los tokens del lenguaje MEPa mepa.ALMepa: Se encarga de realizar el anlisis lxico. Contiene un mtodo principal llamado nexToken() que retorna el prximo Token del cdigo fuente. Otro mtodo principal run(), que redefine de la interface Testeable, realiza un test pidiendo tokens hasta encontrar el fin de archivo o un error. mepa.ASMepa: Se encarga de realizar el anlisis sintctico del programa fuente. El mtodo run() comienza el anlisis y carga de instrucciones. mepa.Mepa: Contiene la pila, el display, el program counter y dems elementos necesarios para la ejecucin de las instrucciones. El mtodo principal run() comienza la ejecucin y entra en un bucle donde toma una instruccin, incrementa el program counter y ejecuta la instruccin. Esta secuencia se repite hasta encontrar la instruccin PARA o alcanzar una excepcin. main.Testeador: permite testear uniformemente cualquier clase que implemente la interface Testeable. En particular nos permite ejecutar separadamente el analizador lxico, el sintctico y la mepa. main.Testeable: interface que deben implementar las clases que deseen ser testeadas por la clase Testeador. main.Main: Contiene simplemente un metodo main. En esta entrega se encarga de construir un Testeador con el archivo fuente dado por lnea de comandos y el objeto Mepa a testear. public static void main(String[] args) { Testeador t = new Testeador(args[0], new mepa.Mepa()); t.start(); } 29

Descripcin de errores
Cdigo 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Mensaje Valor fuera de rango permitido Divisin por cero Numero mal formado Caracter no perteneciente al alfabeto Nombre de etiqueta invalido Nombre de instruccin no valida Instruccin desconocida El programa debe empezar con INPP Despus de PARA no pueden haber sentencias Existen etiquetas sin declarar El programa debe terminar con PARA La instruccin INPP solo puede ir al comienzo Argumentos invlidos Descripcin Valor de ndice de arreglo menor al limite inferior o mayor al limite superior Dividir por cero Error lxico. Un numero seguido de una letra Error lxico. Se lee un carcter extrao Error lxico. Error lxico. Nombre que termina en digito Error lxico. Nombre que no corresponde con ninguna instruccin. Error sintctico. Error sintctico. Error sintctico. Existen etiquetas no resueltas Error sintctico. Error sintctico.

Error sintctico. Operandos de instruccin incorrectos. Entre dos etiquetas debe ir instruccin Error sintctico. Se omite una instruccin entre dos etiquetas. Comienzo de instruccin invalida Error sintctico. Se espera una instruccin Se espera un nro no negativo como primer Error sintctico. argumento Se espera una etiqueta como primer Error sintctico. argumento Se espera una coma entre primer y 2do Error sintctico. argumento Se espera un nro no negativo como 2do Error sintctico. argumento Se espera una coma entre 2do y 3er arg Error sintctico. Se espera un nro no negativo como 3er Error sintctico. argumento Se espera un numero positivo o negativo Error sintctico. Se espera un numero luego de un menos Error sintctico. Numero no representable Valor de numero demasiado grande La etiqueta ya esta declarada Valor invalido ingresado por teclado Magnitud no representable ingresada por Valor de numero demasiado grande en teclado instruccin de lectura Desborde de pila Direccionamiento fuera de rango Recursos insuficientes para ejecutar el Agotamiento de pila o Display programa 30

7. Anlisis Semntico y Generacin de Cdigo


Nuestra misin ahora es construir un EDT (Esquema de Traduccin) para el lenguaje minipascal. Este esquema de traduccin va a realizar el anlisis semntico del programa, esto quiere decir que no solo chequea que sea sintcticamente valido sino que adems va a chequear que tenga el significado correcto. Resumiendo, en esta etapa se realizan las siguientes tareas: - Sentencias de declaracin: completar la seccin de tipos de la tabla de smbolos. - Sentencias ejecutables: realizar chequeo de tipos entre operandos implicados. - Funciones y procedimientos: comprobar, nmero, orden, y tipo de los parmetros actuales en cada llamada a una funcin o procedimiento. - Identificadores de variables: comprobar si un identificador ha sido declarado antes de utilizarlo. - Etiquetas: comprobar si hay etiquetas repetidas y validacin - Constantes: comprobar que no se utilicen en la parte izquierda de una asignacin. - Conversiones y equivalencias de tipo: verificacin. - Generacin de Cdigo Antes de comenzar con el EDT, es necesario comprender las estructuras de datos y el modelo de diseo que usaremos para construirlo.

Estructuras de Datos utilizadas


Tabla de Smbolos: Consiste de una pila de tablas de smbolos. Cada vez que se ingresa a un nuevo ambiente de referenciamiento, por ej un procedimiento o funcin, se apila una nueva tabla que mantendr los datos locales. De manera tal que la tabla del tope de la pila es siempre la del nivel lxico actual. Luego, al termino del subprograma se desapila la tabla y de esta manera restauramos la tabla de smbolos del programa o subprograma que reliz la llamada. Estructura de la Tabla de smbolos Como su nombre lo indica, la estructura de datos es una tabla. Esta tabla presenta dos columnas, una para el nombre de la entidad u objeto y otra para la entrada. El nombre permite identificar unvocamente a la entidad dentro de cada tabla, aunque puede haber una entidad con el mismo nombre en alguna tabla apilada anteriormente. La entrada es un objeto que permite almacenar toda la informacin que necesita dicha entidad. Por ejemplo, en el caso que una entidad sea una variable la entrada va a estar compuesta por su nombre, su valor, desplazamiento en el nivel lxico actual, tipo de datos; mientras que si la entidad es un procedimiento, necesitamos informacin como parmetros formales, etiqueta del procedimiento, tamao de parmetros, etc.. Otra caracterstica muy importante de la tabla es que se comporta como una tabla hash, es decir, dado el nombre de una entidad, no necesitamos recorrer toda la tabla para recuperar su entrada, sino que la obtenemos en tiempo constante (gracias a la funcin hash). El siguiente diagrama, muestra la estructura de la tabla y sus entradas (Entrys):

31

Tabla de smbolos

nombre cont

entrada

Entry nombre: cont desplazamiento: 0 valor: 23 tipo: integer

tablas hash Pila b

nombre: b desplazamiento: 0 valor: true tipo: boolean

Representacin de las entradas (objeto Entry) El objeto Entry mantiene toda la informacin que necesitan las entidades del programa. Cada atributo de la clase se corresponde con alguna caracterstica especfica de la entidad. Atributos: int clase: permite identificar qu tipo de entrada es. Es decir, si es entrada para variable, constante, tipo, procedimiento, funcin, etc. String nombre: mantiene el nombre de la entidad int nivelLexico: Tipo tipo: mantiene el tipo de datos asociado a la entidad. Cada tipo se representa por un objeto que respeta una jerarqua de clases; como veremos mas adelante Object Valor: se usa por ej. para variables, constantes o funciones. Mantiene el valor String etiqueta: se usa en procedimientos y funciones List<Entry> parametrosFormales: se usa en procedimientos y funciones. Mantiene la lista de parmetros formales, donde cada parmetro int sizeParametros: tamao de parmetros boolean porValor: indica si la entidad se pasa por valor o referencia al subprograma boolean predefinido: indica si la entidad es predefinida. Por ejemplo las funciones suc y pred, MAXINT, etc.

32

Jerarqua de clases de Tipos

Tipo TipoSimple TipoSubrango


Clase Tipo: Es un clase abstracta para los tipos del lenguaje. Proporciona, entre otros, dos mtodos abstractos que las subclases deben implementar: - abstract boolean esEquivalenteCon(Tipo t): determina cuando un tipo es equivalente con otro. abstract int getSize(): retorna el numero de locaciones de memoria que abarca el tipo.

TipoArreglo

Clase TipoSimple: Representa a los tipos integer y boolean. Tambin es la clase base del TipoSubrango, por lo tanto se mantiene una relacion es-un. Dos tipos simples t1 y t2 son equivalentes si se cumple que: i) ambos, t1 y t2 son integer, boolean o subrango ii) t1 es integer y t2 es subrango o viceversa Clase TipoSubrango: Hereda de TipoSimple, y agrega dos atributos li y ls donde mantiene el valor inferior y superior del rango de valores que puede contener (ls li +1). Un tipo subrango es equivalente con otro tipo T si y solo si T es subrango o integer. Contiene un mtodo int getRango(), que retorna el valor (ls li +1) Todos los tipos simples, ya sea boolean, integer o subrango tienen tamao 1 Clase TipoArreglo: Est compuesto por dos subtipos, el tipo del indice y el tipo de las componentes. El tipo indice es un tipo subrango, mientras que el tipo de las componentes es un tipo simple. Adems mantiene el 33

nmero de componentes (tIndice.getRango()) para poder calcular el tamao (numComponentes * tRango.getSize()).

Creacin de tipos mediante la clase TipoFactory Esta clase solamente contiene mtodos estticos que nos proveen los diferentes tipos que necesitamos: static Tipo crearTipoSimple(int cod) static Tipo crearTipoBooleano(); static Tipo crearTipoEntero(); static Tipo crearTipoSubrango(int inf, int sup); static Tipo crearTipoArreglo(TipoSubrango tindice, TipoSimple tRango); Modelo de Tablas de smbolos: Clase AbstractSimbolTable La clase AbstractSimbolTable <T>, es una clase abstracta y genrica que sirve de base para implementar cualquier tabla de smbolos en la cual se desean almacenar entradas de tipo T. Mantiene la estructura de pila de tablas de simbolos (Hashtable). Provee los metodos: - void crearNivelLxico(): construye una nueva tabla y la apila void eliminarNivelLexico(): elimina la tabla del tope de la pila int getNivelLexico(): retorna el nivel lxico actual abstract void init(): Este es el mtodo de inicializacin que las subclases deben implementar. En el se cargaran las entidades predefinidas y/o cualquier otra informacin necesaria antes de comenzar la compilacin. boolean estaDeclarado(String id): chequea si el identificador pertenece a la tabla actual T buscar(String id): busca a partir de la tabla del tope de la pila hasta encontrar la entrada (de tipo T) para ese identificador o retornar null si no se encuentra. void inserta(String name, T entry): inserta una entrada T para el nombre name dentro de la tabla de smbolos actual (del tope de la pila).

Clase concreta para tablas de smbolos: Clase EntryTable Esta es la clase que usaremos en este proyecto. Hereda de AbstractSimbolTable para implementar entradas de tipo Entry: public final class EntryTable extends AbstractSimbolTable<Entry>{ ... } Redefine el mtodo init(), en el cual se agregan las sig. entidades: - Tipos: integer y boolean - Constante MAXINT - Constantes true y false 34

Procedimentos predefinidos: read, readln, write, writeln Funciones predefinidas: succ(x) y pred(x)

Metodos para manejo de las entradas: - void agregarConstante(String id, Entry e): inserta en la tabla de smbolos actual una entrada para la nueva constante. - agregarPrograma(String id): inserta una entrada para el nombre del programa Entry buscarConstante(String id): busca en la tabla una entrada para el identificador. Si se encuentra una pero no es una entrada para constante, se retorna null. void agregarTipo(String id, Entry e): inserta en la tabla de smbolos actual una entrada para el nuevo tipo. Entry buscarTipo(String id): idem a buscar identificador, salvo que adems chequea si la entrada es un tipo. Entry agregarProcedimiento(String id, List<Entry> listPar, String etiqueta): inserta una declaracin de procedimiento en el nivel lxico actual y retorna la entrada generada para el mismo void agregarParaFormales(List<Entry> listPar): inserta los parmetros formales en el nivel lxico actual Entry agregarFuncion(String id, Tipo t, String etiqueta, List<Entry> listPar): inserta una declaracin de funcin en el nivel lxico actual y retorna su entrada int agregarDesplazamientosPar(List<Entry> listaPar): calcula y setea los desplazamientos a la lista de parmetros formales. Retora el desplazamiento del primer parametro void agregarVariables(List<String> listaId, Tipo t): inserta una lista de variables en el nivel lxico actual boolean estaDeclarado(String id): idem a buscar identificador pero solo mira la tabla de smbolos del nivel lxico actual. (declaracin local)

Mtodos incorporados Integer convertirAEntero(String num, int numLinea): convierte el nmero num a objeto Integer. Captura la excepcin si el numero no es representable. void genPredefinida(String id, Tipo t): dado el nombre de la funcin o procedimiento id y el tipo del argumento, genera el cdigo mepa correspondiente. String negar(String val): dado un valor lo niega. Si ya venia con el signo - se lo quita. void genMepa(String inst, boolean conEti, int... par): Este el mtodo que escribe en archivo la instruccin mepa. Posee parmetros par de longitud variable dado que son los operandos que puede recibir. El atributo booleano permite escribir una tabulacin para mejorar la esttica del cdigo generado.

35

String genEtiqueta(): Genera la prxima etiqueta. Incrementa una variable global numEtiqueta para que genere una etiqueta diferente en cada invocacin.

Esquema de Traduccin (EDT)


Programa <programa> ::= program <identificador>; <bloque>. <programa> ::= { TS.inicializar(); } program <identificador> { TS.crearNivelLexico(); TS.agregarPrograma(<identificador>.lexema); genMepa(INPP); <bloque>.etiqueta = genEtiqueta(); <bloque>.esprogram = true; genMepa(DSVS + <bloque>.etiqueta); } ;<bloque>. { genMepa(PARA); } Bloques Atributos Heredados: - nivelLexico: nivel lexico del bloque (solo procedimientos y funciones) - sizeParamForm: tamao de parametros formales (solo proc y func.) - etiqueta: etiqueta de entrada a la seccin de codigo del bloque - esprogram: indica si es bloque del programa principal <bloque> ::= <seccionDefinicionDeConstantes> <seccionDefinicionDeTipos> <seccionDefinicionDeVariables> <seccionDeclaracionProcYFunciones> { if(<bloque>.esprogram) genMepa(<bloque>.etiqueta ,NADA); else genMepa(<bloque>.etiqueta ,ENPR ,TS.getNivelLexico()); if(<seccionDefinicionDeVariables>.sizeVariables>0){ genMepa(RMEM +<seccionDefinicionDeVariables>.sizeVariables); } } <sentenciaCompuesta> { if(<seccionDefinicionDeVariables>.sizeVariables>0){ 36

genMepa(LMEM ,<seccionDefinicionDeVariables>.sizeVariables); } If(!<bloque>.esprogram){ genMepa(RTPR ,<bloque>.nivelLexico, <bloque>.sizeParamFor); } } Seccin de Definicin de constantes < seccionDefinicionDeConstantes > ::= | const <definicionDeConstante> ;<restoDefinicionDeConstante> <restoDefinicionDeConstante> ::= <definicionDeConstante> ; <restoDefinicionDeConstante>| No requieren acciones semnticas Definicin de constante <definicionDeConstante> ::= <identificador> = <constante> <constante> ::= - <idConstante> | +<idConstante> | <idConstante> <idConstante> ::= <numero> | <identificador> Atributos Heredados: - signo: mantiene el signo de la constante (String) Atributos Sintetizados: - valor: valor de la constante - tipo: tipo de la constante <definicionDeConstante> ::= <identificador> { if(TS.estaDeclarado(<identificador>.lexema)) error(identificador ya declarado); } = <constante> { //en la implementacin debemos crear la entrada y pasarsela a este metodo TS.agregarConstante(<identificador>.lexema, <constante>.valor,<constante>.tipo); } <constante> ::= { <idConstante>.signo = - } 37

<idConstante> { <constante>.valor = <idConstante>.valor <constante>.tipo = <idConstante>.tipo } <constante> ::= + { <idConstante>.signo = + } <idConstante> { <constante>.valor = <idConstante>.valor <constante>.tipo = <idConstante>.tipo } <constante> ::= { <idConstante>.signo = } <idConstante> { <constante>.valor = <idConstante>.valor <constante>.tipo = <idConstante>.tipo } <idConstante> ::= <numero> { Integer val; if (<idConstante>.signo = -) { val = negar(<numero>.lexema, true); }else { val = negar(<numero>.lexema, false); } t = new TipoSimple(TipoSimple.ENTERO); <idConstante>.valor = val; <idConstante>.tipo = t } <idConstante> ::= <identificador> { Entry e = TS.buscarConstante(<identificador>.lexema); if (e == null) error(identificador desconocido o no se refiere a una constante); Integer val; if(<idConstante>.signo !=){ if(!e.tipo.esEntero() || e.esSubrango()) error(Solo se puede aplicar + o a valore enteros o subrango); if (<idConstante>.signo = -) { val = e.valor * -1; }else { val = e.valor; 38

} }else{ val = e.valor; } <idConstante>.valor = val; <idConstante>.tipo = e.tipo } Seccin de Definicin de tipos <seccionDefinicionDeTipos> ::= | type <definicinDeTipo> ; <restoDefinicionDeTipo> <restoDefinicionDeTipo> ::= <definicinDeTipo> ; <restoDefinicionDeTipos>| Sin acciones semnticas Definicin de Tipos <definicinDeTipo> :: = <identificador> = <tipo> <tipo> ::= <tipoSimple> | array [<tipoSimple>] of <tipoSimple>

Atributos Sintetizados: - tipo: sintetiza el tipo - size: tamao del tipo <definicinDeTipo> :: = <identificador> = { if(TS.estaDeclarado(<identificador>.lexema)) error(identificador ya declarado); } <tipo> { //en la implementacion habr que crear la entrada TS.agregarTipo(<identificador>.lexema,<tipo>.tipo,<tipo>.size) } <tipo> ::= <tipoSimple> { <tipo>.tipo = <tipoSimple>.tipo <tipo>.size = <tipoSimple>.size } <tipo>::= 39

array [<tipoSimple>1] of <tipoSimple>2 { if(<tipoSimple>1.tipo.esEntero()){ error(el tipo integer no es un tipo de indice valido); } Tipo t = new TipoArreglo(<tipoSimple>1.tipo, <tipoSimple>2.tipo ); <tipo>.tipo = t <tipo>.size = t.getSize(); } Tipo Simple <tipoSimple> ::= <identificador> <restoTipoSimple> | <numero > .. <constante> | + <restoSubrango> | - <restoSubrango> <restoSubrango>::= <identificador> .. <constante> | <numero> .. <constante> <restoTipoSimple>::= .. <constante> | Atributos Heredados: - id: lleva hacia abajo el lexema del identificador de tipo Atributos Sintetizados: - valor: sintetiza el valor de la constante o numero - tipo: idem <tipo>.tipo - size: idem <tipo>.tipo <tipoSimple> ::= <identificador> { <restoTipoSimple>.id =<identificador>.lexema } <restoTipoSimple> { <tipoSimple>.tipo =<restoTipoSimple>.tipo <tipoSimple>.size =<restoTipoSimple>.size } <restoTipoSimple>::= .. <constante> { Entry e = buscarConstante (<restoTipoSimple>.id) If ( e= null ) error(identificador desconocido o no se refiere a una constante); if(<constante>.valor < e.valor) error(subrango de valores invalido (el limite inferior debe ser menor al limite superior)); Tipo t = new TipoSubrango(e.valor,<constante>.valor) <restoTipoSimple>.tipo = t <restoTipoSimple>.size = t.getSize(); } <restoTipoSimple>::= { Entry e = buscarTipo( <restoTipoSimple>.id) If ( e= null ) error(identificador de tipo desconocido); 40

if(!e.tipo.esSimple()) error(Identificador de tipo no valido); <restoTipoSimple>.tipo = e.tipo <restoTipoSimple>.size = e.tipo.getSize(); } <tipoSimple> ::= <numero> .. <constante> { if(<constante>.valor < <numero>.valor) error(subrango de valores invalido (el limite inferior debe ser menor al limite superior)); Tipo t = new TipoSubrango( <numero>.valor,<constante>.valor) <tipoSimple>.tipo = t <tipoSimple>.size = t.getSize(); } <tipoSimple> ::= + { <restoSubrango>.signo = + } <restoSubrango> { <tipoSimple>.tipo = <restoSubrango>.tipo <tipoSimple>.size = 1; } <tipoSimple> ::= { <restoSubrango>.signo = - } <restoSubrango> { <tipoSimple>.tipo = <restoSubrango>.tipo <tipoSimple>.size = 1 } <restoSubrango>::= <identificador> { Entry e = buscarConstante (<identificador>.lexema) If ( e= null ) error(identificador desconocido o no se refiere a una constante); } .. <constante> { Integer val; if (<restoSubrango>.signo = -) val = e.valor * -1 else val = e.valor 41

if(<constante>.val < val) error(subrango de valores invalido (el limite inferior debe ser menor al limite superior)); Tipo t = new TipoSubrango( val,<constante>.valor) <restoSubrango>.tipo = t <restoSubrango>.size = 1; } <restoSubrango>::= <numero> .. <constante> { Integer val; if (<restoSubrango>.signo = -) val = <numero>.valor * -1 else val = <numero>.valor if(<constante>.val < val) error(subrango de valores invalido (el limite inferior debe ser menor al limite superior)); Tipo t = new TipoSubrango( <numero>.valor,<constante>.valor) <restoSubrango>.tipo = t <restoSubrango>.size = 1; } Seccin de Definicin de variables

<seccionDefinicionDeVariables > ::= | var <declaracinDeVariables> ; <restoDefinicionDeVariables> <restoDefinicionDeVariables> ::= | <declaracinDeVariables> ; <restoDefinicionDeVariables > Atributos Sintetizados: sizeVariables: guarda el tamao total de las variables declaradas <seccionDefinicionDeVariables>::= { <seccionDefinicionDeVariables>.sizeVariables = 0; } <seccionDefinicionDeVariables > ::= var <declaracinDeVariables> ; <restoDefinicionDeVariables> { <seccionDefinicionDeVariables >.sizeVariables = <declaracinDeVariables>.sizeVariables + <restoDefinicionDeVariables>.sizeVariables } <restoDefinicionDeVariables> ::= { <restoDefinicionDeVariables>.sizeVariables = 0; 42

} <restoDefinicionDeVariables> ::= <declaracinDeVariables> ; <restoDefinicionDeVariables>1 { <restoDefinicionDeVariables >.sizeVariables = <declaracinDeVariables>.sizeVariables + <restoDefinicionDeVariables>1.sizeVariables } Declaracin de Variables <declaracionDeVariables> ::= < listaIdentificadoresDeVariables>: <tipo>

Atributos sintetizados: - listaid: contiene la lista de identificadores de la declaracin - tipo: tipo de las variables en la lista de identificadores - size: tamao del tipo de datos - sizeVariables: sintetiza el tamao total de las variables declaradas <declaracionDeVariables> ::= <listaIdentificadoresDeVariables>: <tipo> { List<String> listaID = <listaIdentificadoresDeVariables>.listaid; //en la implementacion recibe el objeto Tipo TS.agregarVariables(listaID, <tipo>.tipo, <tipo>.size); <declaracionDeVariables>.sizeVariables = listaID.size() * <tipo>.size }

<listaIdentificadoresDeVariables> ::= <identificador> < restoListaIdentificadoresDeVariables> <restoListaIdentificadoresDeVariables> ::= | , <identificador> < restoListaIdentificadoresDeVariables> Atributos Heredados: -listIn: lista de identificadores de variables actualmente procesados Atributos Sintetizados: - listOut: lista resultante de procesar todos los identificadores de variables <listaIdentificadoresDeVariables> ::= <identificador>{ if(TS.estaDeclarado(<identificador>.lexema)) error(Identificador ya declarado); List<String> list = new LinkedList(); list.addFirst(<identificador>.lexema) <restoListaIdentificadoresDeVariables>.listIn = list; } 43

<restoListaIdentificadoresDeVariables> { <listaIdentificaodresDeVariables>.listid = <restoListaIdentificadoresDeVariables>.listOut; } <restoListaIdentificadoresDeVariables> ::= { <restoListaIdentificadoresDeVariables>.listOut = <restoListaIdentificadoresDeVariables>.listIn; } <restoListaIdentificadoresDeVariables> ::= , <identificador> { if(TS.estaDeclarado(<identificador>.lexema) || <restoListaIdentificadoresDeVariables>.listIn.contains(<identificador>.lexema) error(identificador ya declarado); <restoListaIdentificadoresDeVariables>.listIn.addFirst(<identificador>.lexema); <restoListaIdentificadoresDeVariables>1.listIn = <restoListaIdentificadoresDeVariables>.listIn } <restoListaIdentificadoresDeVariables>1 { <restoListaIdentificadoresDeVariables>.listOut = <restoListaIdentificadoresDeVariables>1.listOut } Seccin de declaracin de Procedimientos y Funciones <seccionDeclaracionProcYFunciones > ::= <seccionDeclaracionProcYFunciones > ::= <declaracionDeProcedimiento > ; < seccionDeclaracionProcYFunciones > <seccionDeclaracionProcYFunciones > ::= <declaracinDeFuncin> ; < seccionDeclaracionProcYFunciones > Sin acciones semnticas Declaracin de Procedimiento <declaracinDeProcedimiento> ::= <encabezadoDeProcedimiento > <bloque>

<declaracinDeProcedimiento> ::= <encabezadoDeProcedimiento > { <bloque>.sizeParamFor = <encabezadoDeProcedimiento>.sizeParamFor <bloque>.etiqueta = <encabezadoDeProcedimiento>.etiqueta; 44

<bloque>.nivelLexico = TS.getNivelLexico(); <bloque>.esprogram = false; } <bloque> { TS.eliminarNivelLexico(); }

<encabezadoDeProcedimiento > ::= procedure <identificador> < restoEncabezadoDeProcedimiento > <restoEncabezadoDeProcedimiento > ::= ; | ( < listaParametrosFormales> ) ; Atributos Sintetizados: - sizeParamFor: tamao de los parmetros formales - etiqueta: etiqueta de la instruccin de comienzo de proced <encabezadoDeProcedimiento > ::= procedure <identificador> { If(TS.estaDeclarado(<identificador>.lexema)) error(identificador ya declarado) } <restoEncabezadoDeProcedimiento> { List<Entry> lista = <restoEncabezadoDeProcedimiento>.listaParmFor String eti = genEtiqueta(); //crea la entrada para el procedimiento Entry e = TS.agregarProcedimiento(<identificador>.lexema, lista, eti); //crea el nivel lxico para este procedimiento TS.crearNivelLexico(); e.nivelLexico = TS.getNivelLexico(); //agrega los desplazamientos adecuados a los parmetros formales TS.agregarDesplazamentoPar(lista); //agrega en la tabla de smbolos los parametros TS.agregarParFormales(lista); <encabezadoDeProcedimiento>.sizeParamFor = <restoEncabezadoDeProcedimiento>.listaParamFor.size(); <encabezadoDeProcedimiento>.etiqueta = eti; } <restoEncabezadoDeProcedimiento > ::= ; { <restoEncabezadoDeProcedimiento>.listaParamFor = new List<Entry>(); } <restoEncabezadoDeProcedimiento > ::= ( <listaParametrosFormales> ) ; { 45

<restoEncabezadoDeProcedimiento>. listaParmFor = <listaParametrosFormales>. listaParmFor } Lista de Parmetros Formales < listaParametrosFormales >::= <grupoDeParametros > < restoListaParametrosFormales >

Atributos Sintetizados: - listaParmFor: lista de entradas para los parmetros formales < listaParametrosFormales >::= { <grupoDeParametros>.listaHer = new List<Entry> (); <grupoDeParametros>.conjIdHer = new HashSet(); } <grupoDeParametros> { <restoListaParametrosFormales >.listaHer =<grupoDeParametros>.listaSint <restoListaParametrosFormales >.conjIdHer = <grupoDeParametros>.conjIdSint } <restoListaParametrosFormales>{ < listaParametrosFormales >. listaParamFor = <restoListaParametrosFormales >.listaSint }

<restoListaParametrosFormales >::= | ; <grupoDeParametros> < restoListaParametrosFormales > <grupoDeParametros > ::= < listaIdentificadorParametroFormales > : <identificador> | var <listaIdentificadorParametroFormales>: <identificador> <listaIdentificadorParametroFormales >::= <identificador> < restoListaIdentificadorParametroFormales > <restoListaIdentificadorParametroFormales >::= | , <identificador> < restoListaIdentificadorParametroFormales > Atributos Heredados: - listaHer: lista de parmetros formales procesados hasta el momento - conjIdHer: conjunto de identificadores de estos parmetros mas el del procedimiento o funcin al que pertenecen. Permite chequear por parmetros repetidos Atributos Sintetizados: - listaSint: lista de parmetros formales resultante - conjIdSint: conjunto de identificadores resultante - listaId; lista de identificadores (Strings) encontrados en listaDeIdentificadoresParamF. 46

<restoListaParametrosFormales >::= { <restoListaParametrosFormales >.listaSint =<restoListaParametrosFormales >.listaHer <restoListaParametrosFormales >.conjIdSint =<restoListaParametrosFormales >.conjIdHer } <restoListaParametrosFormales >::= ;{ <grupoDeParametros>.listaHer = <restoListaParametrosFormales>.listaHer <grupoDeParametros>.conjIdHer = <restoListaParametrosFormales>.conjIdHer } <grupoDeParametros> { <restoListaParametrosFormales >.listaHer = <grupoDeParametros>.listaSint <restoListaParametrosFormales >.conjIdHer = <grupoDeParametros>.conjIdSint } < restoListaParametrosFormales >2 { <restoListaParametrosFormales >. listaParamFor = <restoListaParametrosFormales >2.listaSint } <grupoDeParametros > ::= { <listaIdentificadorParametrosFormales >.conjIdHer = <grupoDeParametros>.conjIdHer } <listaIdentificadorParametroFormales> : <identificador> { Entry e = buscarTipo(<identificador>.lexema); if (e==null) Error(identificador de tipo desconocido o no perteneciente a un tipo); <grupoDeParametros>.conjIdSint = <listaIdentificadorParametrosFormales >.conjIdSint; <grupoDeParametros >.listaSint= <grupoDeParametros >.listaHer; List lista = <listaIdentificadorParametrosFormales >.listaId; String id; Entry entrada; while (lista.size>0){ id=lista.removeFirst(); entrada=new Entry(id,Entry.PAR_FORMAL);//el nivel lxico y los desplazamiento se agregan luego entrada.tipo = e.tipo; entrada.porValor = true; entrada.asignable = true; <grupoDeParametros>.listaSint.addLast(entrada); } } <grupoDeParametros > ::= { <listaIdentificadorParametrosFormales >.conjIdHer = <grupoDeParametros>.conjIdHer } 47

var <listaIdentificadorParametroFormales>: <identificador> { Entry e = buscarTipo(<identificador>.lexema); if (e==null) Error(identificador de tipo desconocido o no pertenece a un tipo); <grupoDeParametros>.conjIdSint = <listaIdentificadorParametrosFormales >.conjIdSint; <grupoDeParametros >.listaSint= <grupoDeParametros >.listaHer; List lista = <listaIdentificadorParametrosFormales >.listaId; String id; Entry entrada; while (lista.size>0){ id=lista.removeFirst(); entrada=new Entry(id,Entry.PAR_FORMAL);//el nivel lxico y los desplazamiento se agregan luego entrada.tipo = e.tipo; entrada.porValor = false; entrada.asignable = true; <grupoDeParametros>.listaSint.addLast(entrada); } } <listaIdentificadorParametroFormales >::= <identificador> { if(<listaIdentificadorParametroFormales>.conjIdHer.contains(<identificador>.lexema)) Error(identificador de parametro formal repetido) <listaIdentificadorParametroFormales>.conjIdHer.add(<identificador>.lexema) <restoListaIdentificadorParametroFormales >.conjIdHer = <listaIdentificadorParametroFormales>.conjIdHer } <restoListaIdentificadorParametroFormales > { <restoListaIdentificadorParametroFormales >.listaId.addFirst(<identificador>.lexema); <listaIdentificadorParametroFormales>.conjIdSint = <restoListaIdentificadorParametroFormales>.conjIdSint <listaIdentificadorParametroFormales>.listaId = <restoListaIdentificadorParametroFormales>.listaId } <restoListaIdentificadorParametroFormales >::= { <restoListaIdentificadorParametroFormales>.conjIdSint = <restoListaIdentificadorParametroFormales>.conjIdHer; <restoListaIdentificadorParametroFormales>.listaId = new List<String>(); } <restoListaIdentificadorParametroFormales >::= , <identificador> { if(<restoListaIdentificadorParametroFormales>.conjIdIn.contains(<identificador>.lexema)) error(identificador de parmetro formal repetido); <restoListaIdentificadorParametroFormales >.conjIdHer.add(<identificador>.lexema); 48

<restoListaIdentificadorParametroFormales>1.conjIdHer = <restoListaIdentificadorParametroFormales>.conjIdHer; } <restoListaIdentificadorParametroFormales>1 { <restoListaIdentificadorParametroFormales>.conjIdSint = < restoListaIdentificadorParametroFormales >1.conjIdSint; <restoListaIdentificadorParametroFormales>.listaId = < restoListaIdentificadorParametroFormales >1.listaId; <restoListaIdentificadorParametroFormales >.listaId.addFirst(<idenfircador>.lexema); } Declaracin de Funcin <declaracionDeFuncion > ::= <encabezadoDeFuncion > <bloque> Atributo Sintetizado: - nombreFun: nombre de la funcin que sintetiza el encabezado <declaracionDeFuncion > ::= <encabezadoDeFuncion > { <bloque>.sizeParamFor = <encabezadoDeFuncion>.sizeParamFor <bloque>.etiqueta = <encabezadoDeFuncion>.etiqueta; <bloque>.nivelLexico = TS.getNivelLexico(); <bloque>.esprogram = false; } <bloque> { //Pone asignable en false a la funcin para que no pueda ser asignada fuera del bloque Entry e = buscarFuncion(<encabezadoDeFuncion>.nombreFun); e.asignable = false; TS.eliminarNivelLexico(); }

<encabezadoDeFuncion > ::= function <identificador> < restoEncabezadoDeFuncion > <restoEncabezadoDeFuncion > ::= : <identificador>; | ( <listaParametrosFormales >) : <identificador>; Atributos Heredados - id: identificador de funcin que se pasa al resto del encabezado Atributo Sintetizado: - nombreFun: nombre de la funcin que sintetiza el encabezado <encabezadoDeFuncion > ::= function <identificador> { if(TS.estaDeclarado(<identificador>.lexema)) error(identificador ya declarado); 49

<restoEncabezadoDeFuncion>.id = <identificador>.lexema } <restoEncabezadoDeFuncion>{ <encabezadoDeFuncion>.sizeParamFor = <restoEncabezadoDeFuncion>.sizeParamFor <encabezadoDeFuncion>.etiqueta = <restoEncabezadoDeFuncion>.etiqueta <encabezadoDeFuncion>.nombreFun = <identificador>.lexema } <restoEncabezadoDeFuncion > ::= : <identificador> { Entry e = TS.buscarTipo(<identificador>.lexema); If(e==null) error(tipo desconocido o el identificador no se refiere a un tipo) If(!e.tipo.esSimple()) error(la funcion debe retornar un tipo simple); List listaPar = new List<Entry>(); <restoEncabezadoDeFuncion>.listaParamFor = listaPar; <restoEncabezadoDeFuncion>.sizeParamFor = 0; String etiqueta = genEtiqueta(); Entry efun = TS.agregarFuncion(<restoEncabezadoDeFuncion>id, listaPar, e.tipo, etiqueta) TS.crearNivelLexico(); efun.nivelLexico = TS.getNivelLexico(); efun.desplazamiento = -3; <restoEncabezadoDeFuncion>.etiqueta = etiqueta; } ; <restoEncabezadoDeFuncion > ::= ( <listaParametrosFormales>): <identificador>; { Entry e = TS.buscarTipo(<identificador>.lexema); If(e==null) error(tipo desconocido o el identificador no se refiere a un tipo) If(!e.tipo.esSimple()) error(la funcin debe retornar un tipo simple); List listaPar = <listaParametrosFormales>. listaParmFor <restoEncabezadoDeFuncion >. listaParmFor = <listaParametrosFormales>. listaParmFor <restoEncabezadoDeFuncion>.sizeParamFor = <listaParametrosFormales>. sizeParamFor String eti = genEtiqueta(); Entry entradaFn = TS.agregarFuncion(<restoEncabezadoDeFuncion>id, listaPar, e.tipo, eti) TS.crearNivelLexico(); int desplazamiento = agregarDesplazamientosPar(listaPar); entradaFn.nivelLexico = TS.getNivelLexico(); //restamos uno para que apunte al primer parametro entradaFn.desplazamiento = desplazamiento -1 //agrega los parmetros formales en la TS en nivel lexico actual agregarParFormales(listaPar); <restoEncabezadoDeFuncion>.etiqueta = eti; 50

} Sentencias <sentencia> ::= <sentenciaSimple > | < sentenciaCompuesta > | <sentenciaIF> | <sentenciaCASE> | <sentenciaWHILE>

Sentencia Simple <sentenciaSimple> ::= | <identificador> < restoSentenciaSimple > <restoSentenciaSimple > ::= | := <expresin> | [<expresin>] := <expresin> | ( < listaParametrosActuales >) Atributos Heredados: - id : lleva el nombre del identificador - porValor: idem <expresinSimple>.porValor <sentenciaSimple> ::= <identificador> { if(TS.buscar(<identificador>.lexema)==null) error(identificador no declarado); <restoSentenciaSimple >.id = <identificador>.lexema } <restoSentenciaSimple > <sentenciaSimple> ::= <restoSentenciaSimple > ::= { Entry e = TS.buscar(<restoSentenciaSimple >.id); if(e == null) error(identificador de procedimiento no declarado ); if (!e.esEntradaProcedure()) error(el id no corresoponde a un procedimiento o := ausente); if(e.listaParFor.size()>0) error(el numero de parmetros actuales no corresponde con los formales); if(!e.predefinida) genMepa(LLPR + e.etiqueta); else{ if(e.nombre == writeln) genMepa(IMLV); } } <restoSentenciaSimple > ::= :={ Entry e = TS.buscar (<restoSentenciaSimple >.id); if(e == null) error(identificador de variable no declarado ); if(!e.asignable) error(el identificador no corresponde a una entidad asignable ) 51

<expresion>.porValor = true } <expresin> { if (!e.tipo.compatibleCon(<expresion>.tipo)) error(asignacin de tipos no compatibles) //asignacin de una variable, funcin (retorno), param formal pasados por valor if(e.esEntradaVariable() || e.esEntradaFuncion() || (e.esEntradaParamFormal() && e.porValor)){ if(e.tipo.esSimple()){ if (e.tipo.esSubrango()) genMepa( CONT , e.tipo.getValInferior() , e.getValSuperior()) genMepa (ALVL, e.nivelLexico,e.desplazamiento); } else{//copia el arreglo apilado a la memoria de la variable genMepa(POAR,e.nivelLexico,e.desplazamiento,e.tipo.numComponents); } } else{ //asignacin de un valor a un param formal pasado por referencia if(e.tipo.esSimple()){ if(e.tipo.esSubrango()) genMepa(CONT,e.tipo.getValInferior(),e.tipo.getValSuperior()) genMepa(ALVI,e.nivelLexico,e.desplazamiento) } else{//param formal, arreglo por referencia genMepa(POAI,e.nivelLexico,e.desplazamiento,e.tipo.numComponentes); } } } <restoSentenciaSimple > ::= [{ Entry e = TS.buscar (<restoSentenciaSimple >.id); if(e == null) error(identificador no declarado ); if(!e.asignable) error(el identificador no corresponde a una entidad asignable ) If(!e.tipo.esArreglo())error(se espera un identificador de tipo arreglo ) <expresion>1.porValor = true } <expresin>1 { if (!e.tipo.tipoDominio.compatibleCon(<expresion>1.tipo)) error(se espera un valor de tipo simple) if(e.tipo.esSubrango()){ genMepa( CONT , e.tipo. tipoDominio.getValInferior() , e.tipo Dominio. getValSuperior()) genMepa (APCT, e.tipo. tipoDominio.getValInferior()) genMepa (SUST) } else{//puede ser boolean genMepa( CONT , 0, 1); } } 52

] := { <expresion>2.porValor = true; } <expresin> 2 { if (!e.tipo.tipoRango.compatibleCon(<expresion>2.tipo)) error(se espera un valor de tipo simple) if (e.tipo.tipoRango.esSubrango) genMepa( CONT , e.tipo. tipoRango.getValInferior() , e.tipoRango. getValSuperior()) if (!e.porValor) genMepa (ALAI, e.nivelLexico,e.desplazamiento) else genMepa (ALAR, e.nivelLexico,e.desplazamiento) } <restoSentenciaSimple > ::= ( { Entry e = TS.buscar (<restoSentenciaSimple >.id); if(e == null) error(identificador no declarado ); if (!e.esEntradaProcedure()) error(el id no corresponde a un procedimiento) if (e.listaParFor.size() == 0 && !e.predefinida) error(demasiados parmetros actuales) <listaParametrosActuales>.listaParFor = e.listaParFor <listaParametrosActuales>.predefinida = e.predefinida <listaParametrosActuales>.id = <restoSentenciaSimple >.id } <listaParametrosActuales>) { if(!e.predefinida) genMepa(LLPR, e.etiqueta) } Sentencia Compuesta <sentenciaCompuesta > ::= begin <sentencia> < restoSentencia >end <restoSentencia > ::= ; <sentencia> < restoSentencia > | Sin acciones semanticas Sentencia IF <sentenciaIF> ::= if <expresin> then <sentencia> <restoSentenciaIF> <restoSentenciaIF > ::= else <sentencia>| Atributos Heredados: - etiqueta: etiqueta de resto sentencia donde saltar si la condicin no se cumple

53

<sentenciaIF> ::= if { <expresin>.porValor = true } <expresin> then { if(!<expresin>.tipo.esBoolean()) error(se espera una expresin booleana) String eti = genEtiqueta(); genMepa(DSVF ,eti); } <sentencia> { <restoSentenciaIF>.etiqueta = eti; } <restoSentenciaIF> <restoSentenciaIF > ::= else{ String eti = genEtiqueta(); genMepa(DSVS + eti); //termina la ejecucin del if genMepa(<restoSentenciaIF>.etiqueta +NADA); //entrada al else } <sentencia> { genMepa(eti+ NADA); //termina todo el if } <restoSentenciaIF > ::= { genMepa(<restoSentenciaIF>.etiqueta + NADA); } Sentencia CASE <sentenciaCASE> ::= case <expresin> of < listaElementosCASE > end <sentenciaCASE> ::= case { <expresin>.porValor = true; } <expresin> of { if(!<expresin>.tipo.esSimple()) error(en la sentencia case se espera una expresin de tipo simple); <listaElementosCASE>.tipo = <expresin>.tipo String etiquetaFinal = genEtiqueta(); <listaElementosCASE>.etiEnd = etiquetaFinal; 54

} <listaElementosCASE > end { //desapila el valor de la expresion genMepa(etiquetaFinal + LMEM 1); }

<listaElementosCASE> ::= <etiquetaListaCASE > <restoListaElementosCASE> <etiquetaListaCASE> ::= <constante > <restoEtiquetas> : <sentencia> | <restoEtiquetas> ::= ,<constante> <restoEtiquetas > | <restoListaElementosCASE> ::= ; <listaElementosCASE> | Atributos heredados: - tipo: tipo de la expresin case - etiEnd: etiqueta de la instruccin donde termina el case <listaElementosCASE> ::= { <etiquetaListaCASE>.tipo = <listaElementosCASE>.tipo <etiquetaListaCASE>.etiEnd = <listaElementosCASE>.etiEnd } <etiquetaListaCASE> { <restoListaElementosCASE>.tipo = <listaElementosCASE>.tipo <restoListaElementosCASE>.etiEnd = <listaElementosCASE>.etiEnd } <restoListaElementosCASE> <etiquetaListaCASE> ::= { String etiFinSent = genEtiqueta(); } <constante>{ If(!<constante>.tipo.compatibleCon(<etiquetaListaCase>.tipo)) Error( constante de tipo incompatible con la expresion) genMepa(DUPT) genMepa(APCT,<constante>.valor) genMepa(CMIG) String etiSent = genEtiqueta(); genMepa(DSVV + etiSent); <restoEtiquetas>.etiSent = etiSent <restoEtiquetas>.etiFinSent = etiFinSent <restoEtiquetas>.tipo = <etiquetaListaCASE>.tipo } <restoEtiquetas> : { genMepa(DSVS + etiFinSent); genMepa(etiSent +NADA) } 55

<sentencia> { genMepa(DSVS + <etiquetaListaCASE>.etiEnd); genMepa(etiFinSent +NADA) } <etiquetaListaCASE> ::= <restoEtiquetas> ::= ,<constante> { If(!<constante>.tipo.compatibleCon(<restoEtiquetas>.tipo)) Error( constante de tipo incompatible con la expresion) genMepa(DUPT) genMepa(APCT,<constante>.valor) genMepa(CMIG) genMepa(DSVV + <restoEtiquetas>.etiSent); <restoEtiquetas>.etiSent = <restoEtiquetas>.etiSent <restoEtiquetas>.etiFinSent = <restoEtiquetas>.etiFinSent <restoEtiquetas>.tipo = <restoEtiquetas>.tipo } <restoEtiquetas> <restoEtiquetas> ::= <restoListaElementosCASE> ::= { <listaElementosCASE>.tipo = <restListaElementosCASE>.tipo <listaElementosCASE>.etiEnd = <restListaElementosCASE>.etiEnd } ; <listaElementosCASE> <restoListaElementosCASE> ::= Sentencia WHILE <sentenciaWHILE> ::= while <expresin> do <sentencia>

<sentenciaWHILE> ::= while { String eti = genEtiqueta(); genMepa(eti + NADA); //punto de entrada al while <expresin>.porValor = true; } <expresin> do { if(!<expresin>.tipo.esBoolean()) error(se espera una expresin booleana); String etiSalida = genEtiqueta(); //chequeo la condicion genMepa(DSVF + etiSalida);. 56

} <sentencia> { //salta a la condicion del while genMepa(DSVS +eti); //punto de salida del while genMepa(etiSalida + NADA); } Expresiones <expresin> ::= < expresionSimple > < restoExpresion > < restoExpresion > ::= <operadorRelacional> < expresionSimple > |

Atributos Hereados: - porValor: boolean. Indica si la expresin esta en el contexto de un parmetro por refencia o valor - tipoHer : Tipo. Lleva el tipo de la sub-expresin de la izquierda para permitir chequeo de tipo con la sub-expresin derecha Atributos Sintetizados: - tipo: sintetiza el tipo de la expresin <expresin> ::= { <expresionSimple>.porValor = <expresin>.porValor } <expresionSimple> { <restoExpresion>.tipoHer = <expresionSimple>.tipo; <restoExpresion>.porValor = <expresin>.porValor; } <restoExpresion> { <expresin>.tipo = <restoExpresion>.tipo; } <restoExpresion> ::= <operadorRelacional> { if(!<restoExpresion>.porValor) error(se espera el nombre de una variable o componente de arreglo); if(<restoExpresion>.tipoHer.esArreglo()) error(los operadores relacionales solo se aplican a expresiones de tipos simples) <expresionSimple>.porValor=true } <expresionSimple> { if(<expresionSimple>.tipo.esArreglo()) 57

error(los operadores relacionales solo se aplican a expresiones de tipos simples) if( ! (<restoExpresion>.tipoHer.compatibleCon(<expresionSimple>.tipo)) error(expresin relacional con tipos incompatibles); if(<operador_relacioneal>.valor == <) genMepa(CMME); else if(<operador_relacioneal>.valor == <=) genMepa(CMNI); else if(<operador_relacioneal>.valor == >) genMepa(CMMA); else if(<operador_relacioneal>.valor == >=) genMepa(CMYI); else if(<operador_relacioneal>.valor == <>) genMepa(CMDG); else if(<operador_relacioneal>.valor == =) genMepa(CMIG); <restoExpresion>.tipo= new TipoSimple(TipoSimple.BOOLEAN); } <restoExpresion> ::= { <restoExpresion>.tipo = <restoExpresion>.tipoHer; }

<operadorRelacional> ::= <> | < | > | <= | >= Atributo Sintetizado: - valor: String. Sintetiza el lexema del operador <operadorRelacional> ::= <> {<operadorRelacional>.valor= <> } <operadorRelacional> ::= < {<operadorRelacional>.valor= < } <operadorRelacional> ::= > {<operadorRelacional>.valor= > } <operadorRelacional> ::= <= {<operadorRelacional>.valor= <= } <operadorRelacional> ::= >= {<operadorRelacional>.valor= >= } <operadorRelacional> ::= = {<operadorRelacional>.valor= = } Expresin Simple <expresionSimple > ::= <termino> < restoExpresionSimple >| <signo> <termino> < restoExpresionSimple >| <restoExpresionSimple > ::= | <operadorSumador> <termino>< restoExpresionSimple > Atributos Heredados: - tipoHer: idem <restoExpresin>.tipoHer Atributos Sintetizados: - tipo: idem <expresin>.tipo <expresionSimple > ::= { <termino>.porValor = <expresionSimple>.porValor } <termino> { <restoExpresionSimple>.porValor = <expresionSimple>.porValor 58

<restoExpresionSimple>.tipoHer = <termino>.tipo } < restoExpresionSimple > { <expresionSimple>.tipo = <restoExpresionSimple>.tipo } <expresionSimple > ::= <signo> { if(!<expresionSimple>.porValor) error(se espera el nombre de una variable o componente de un arreglo como parmetro actual); <termino>.porValor = true } <termino> { if ( !(<termino>.tipo.esEntero() || <termino>.tipo.esSubrango()) ) error(los operadores unarios + o solo se aplica a expresiones enteras) if(<signo>.valor == -) genMepa(UMEN); <restoExpresionSimple>.porValor = <termino>.porValor <restoExpresionSimple>.tipoHer = <termino>.tipo } <restoExpresionSimple > { <expresionSimple>.tipo = <restoExpresionSimple>.tipo } <signo>::= + {<signo>.valor = +} <signo>::= - {<signo>.valor = -} <restoExpresionSimple > ::= { <restoExpresionSimple>.tipo= <restoExpresionSimple>.tipoHer } <restoExpresionSimple > ::= <operadorSumador> { if(!<restoExpresionSimple>.porValor) error(no se permite pasar por referencia un valor numrico o booleano) <termino>.porValor = true } <termino> { If (! <restoExpresionSimple>.tipoHer.compatibleCon(<termino>.tipo)) error( tipos de operandos incompatibles) if (<operadorSumador>.valor == + ) { if (<termino>.tipo.esBoolean() || <termino>.tipo.esArreglo()) error( no se puede sumar valores de tipo arreglo o booleano) 59

genMepa(SUMA); } if (<operadorSumador>.valor == - ) { if (<termino>.tipo.esBoolean() || <termino>.tipo.esArreglo()) error( no se puede restar valores de tipo arreglo o booleano); genMepa(SUST); } if (<operadorSumador>.valor == or ) { if (!<termino>.tipo.esBoolean()) error( se esperan operandos de tipo boolean); genMepa(DISJ); } <restoExpresionSimple>2.porValor = true; <restoExpresionSimple>2.tipoHer = <termino>.tipo

} <restoExpresionSimple>2

<operadorSumador> ::= + | - | or Atributo Sintetizado: valor: String. Sintetiza el lexema <operadorSumador> ::= + {<operadorSumador>.valor =+} <operadorSumador> ::= - {<operadorSumador>.valor =-} <operadorSumador> ::= or {<operadorSumador>.valor =or} Termino <termino> ::= <factor> <restoTermino> <restoTermino> ::= <operadorMultiplicador> <factor> <restoTermino>| Atributos Heredados: - tipoHer: idem < restoExpresin >.tipoHer Atributos Sintetizados: - tipo: idem <expresin>.tipo <termino> ::= { <factor>.porValor = <termino>. porValor } <factor> { <restoTermino>.porValor = <termino>.porValor <restoTermino>.tipoHer = <factor>.tipo } <restoTermino>{ <termino>.tipo = <restoTermino>.tipo }

60

<restoTermino> ::= <operadorMultiplicador> { if(!<restoTermino>.porValor) error(se espera el nombre de una variable o componente de un arreglo) <factor>.porValor = true } <factor> { if (!<restoTermino>.tipoHer.compatibleCon(<factor>.tipo)) error( operandos de tipos incompatibles); if (<operadorMultiplicador>.valor == * ) { if ( <factor>.tipo.esBoolean() || <factor>.tipo.esArreglo()) error( no se puede multiplicar valores de tipo arreglo o boolean) genMepa(MULT); } if (<operadorMultiplicador>.valor == div ) { if ( <factor>.tipo.esBoolean || <factor>.tipo.esArreglo) error( no se puede multiplicar valores de tipo arreglo ni booleano) genMepa(DIVC); genMepa(DIVI); } if (<operadorMultiplicador>.valor == and ){ if ( !<factor>.tipo.esBoolean()) error( se esperan operando de tipo booleano) genMepa ( CONJ); } <restoTermino>2.porValor = true <restoTermino>2.tipoHer = <factor>.tipo } <restoTermino>2 { <restoTermino>.tipo = <restoTermino>2.tipo } <restoTermino> ::= { <restoTermino>.tipo= <restoTermino>.tipoHer }

<operadorMultiplicador> ::= * | div | and Atributo Sintetizado: - valor: String. Sintetiza el lexema <operadorMultiplicador>::= * {<operadorMultiplicador>.valor=*;} <operadorMultiplicador>::= div{<operadorMultiplicador>.valor=div;} <operadorMultiplicador>::= and {<operadorMultiplicador>.valor=and;}

61

Factor <factor> ::= <identificador> <restoFactor>| <sec-digitos> | ( <expresin> ) | not <factor> <restoFactor> ::= [expresion]> | (<listaParametrosActuales>) | Atributos Heredados: - porValor: idem <expresin>.porValor - id: nombre del identificador que hereda restoFactor Atributos Sintetizado: - tipo: idem <expresin>.tipo <factor> ::= <identificador> { Entry e = TS.buscar(<identificador>.lexema) if(e == null) error(identificador no declarado) <restoFactor>.id = <identificador>.lexema <restoFactor>.porValor = <factor>.porValor } <restoFactor>{ <factor>.tipo = <restoFactor>.tipo } <factor> ::= { if(!<factor>.porValor) error( no se puede pasar una numero por referencia) } <numero>{ <factor>.tipo = newTipoSimple( Tipo.ENTERO); genMepa(APCT, <numero>.lexema); } <factor> ::= { if(!<factor>.porValor) error(se espera el nombre de una variable o componente de arreglo como parmetro actual) <expresion>.porValor = true; } (<expresin> ) { <factor>.tipo =<expresion>.tipo } <factor> ::= { if(!<factor>.porValor) error( no se puede pasar por referencia una valor constante) 62

} not <factor>2 { if (!<factor>2.tipo.esBoolean()) error(el operador not solo se aplica a expresiones booleanas) genMepa(NEGA ) <factor>.tipo = <factor>2.tipo } <restoFactor> ::= [ { Entry e = TS.buscar(<restoFactor>.id) If (!e.tipo.esArreglo) error(el identificador no es de tipo arreglo) <expresion>.porValor = true } <expresion> { if (!e.tipo.tipoDominio.compatibleCon(<expresion>1.tipo)) error(se espera un valor de tipo simple) if(e.tipo.tipoDominio.esBoolean()){ genMepa(CONT,0,1); } else{//subrango genMepa( CONT , e.tipo. tipoDominio.getValInferior() , e.tipo.tipoDominio. getValSuperior()); genMepa (APCT, e.tipo. tipoDominio.getValInferior()) ; genMepa (SUST) ; } } ] { if (<restoFactor>.porValor) { //variable o parametro array por valor if(e.porValor) genMepa("APAR",e.nivelLexico,e.desplazamiento); //parametro array por referencia else genMepa("APAI",e.nivelLexico,e.desplazamiento); } else {//debe dejar la referencia //variable o parametro array por valor if(e.porValor) genMepa("APDR",e.nivelLexico,e.desplazamiento); //parametro array por referencia else genMepa("APDC", e.nivelLexico,e.desplazamiento); } <restoFactor>.tipo = e.tipo.tipoRango }

<factor>2.porValor = true

63

<restoFactor> ::= ( { Entry e = TS.buscar(<restoFactor>.id) If (!e.esFuncion()) error(el identificador no corresponde a una funcin) if(!<restoFactor>.porValor) error (no se puede pasar una funcin por referencia); if(!e.predefinida) genMepa(RMEM 1); <listaParametrosActuales >.listaParFor = e.listaParFor <listaParametrosActuales >.predefinida = e.predefinida <listaParametrosActuales >.id = <restoFactor>.id } <listaParametrosActuales>) { if(!e.predefinida){ genMepa(LLPR, e.etiqueta) } <restoFactor>.tipo = e.tipo; } <restoFactor> ::= { Entry e = TS.buscar(<restoFactor>.id) if(e.esProgram() || e.esProcedure() || e.esType()) error(se espera un identificador de variable, constante, funcion o parame tro) if(<restoFactor>.porValor){ if(e.esConstante()){ genMepa(APCT + e.valor); <restoFactor>.tipo = e.tipo } else if(e.esVariable() ){ if(e.tipo.esSimple()){ genMepa(APVL,e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } else{//copia del arreglo n = e.tipo.numComponents; genMepa(PUAR, e.nivelLexico,e.desplazamiento,n) <restoFactor>.tipo = e.tipo } } else if (e.esParametro()){ if (e.porValor){ if(e.tipo.esSimple()){ genMepa(APVL,e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } else{//copia del arreglo n = e.tipo.numComponents; genMepa(PUAR, e.nivelLexico,e.desplazamiento,n) <restoFactor>.tipo = e.tipo } 64

}else{ if(e.tipo.esSimple()){ genMepa(APVI,e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } else{//copia del arreglo n = e.tipo.numComponents; genMepa(PUAI, e.nivelLexico,e.desplazamiento,n) <restoFactor>.tipo = e.tipo.tipoRango } } } else{//funcion If(e.listaParFor.size()!=0) error(faltan parametros actuales) genMepa(RMEM 1); genMepa(LLPR +e.etiqueta); <restoFactor>.tipo = e.tipo } } else {// por referencia if(e.esConstante() || e.esFuncion()) error(se espera un identificador de variable o parametro) else if(e.esVariable() || (e.esParametro() && e.porValor)){ if(e.tipo.esSimple()){ genMepa(APDR,e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } else{//copia del arreglo genMepa(APCT,0); genMepa(APDC, e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } } else { // parametro formal por referencia genMepa(APVL,e.nivelLexico,e.desplazamiento); <restoFactor>.tipo = e.tipo } } <listaParametrosActuales > ::= |<expresion > < restoListaParametrosActuales > <restoListaParametrosActuales > ::= |, <expresin> <restoListaParametrosActuales > Atributos Heredados: - index : lleva la posicin del parmetro actual - listaParFor : mantiene la lista de parmetros formales del procedimiento o funcin. Se usa para poder chequear en numero, posicin y tipo con los parmetros actuales - predefinida: indica si los parmetros actuales son de una funcin o procedimiento predefinido

65

<listaParametrosActuales > ::= { if(!<listaParametrosActuales >.predefinida) Entry e = < listaParametrosActuales >.listaParFor.get(0); if(<listaParametrosActuales >.predefinida) { if (< listaParametrosActuales >.id == read || <listaParametrosActuales >.id == readln) <expresion>.porValor = false else <expresion>.porValor = true } else <expresion>.porValor = e.porValor; } <expresin> { if(!<listaParametrosActuales>.predefinida && !e.tipo.compatibleCon (<expresion>.tipo)) error(incompatibilidad de tipos entre parmetro formal y actual) if(<listaParametrosActuales>.predefinida) { if(!<expresin>.tipo.esSimple()) error(se espera un parmetro de tipo simple) genPredefinida(<listaParametrosActuales>.id, <expresin>.tipo); } <restoListaParametrosActuales>.listaParFor=< listaParametrosActuales >.listaParFor; <restoListaParametrosActuales>.index=1 <restoListaParametrosActuales>.id = <listaParametrosActuales>.id; <restoListaParametrosActuales>.predefinida = <listaParametrosActuales>.predefinida; } <restoListaParametrosActuales > <restoListaParametrosActuales > ::= { if (<restoListaParametrosActuales>.index < <restoListaParametrosActuales>.listaParFor.size() && !<restoListaParametrosActuales>.predefinida ) error(el numero de parmetros actuales no corresponde con los formales) } <restoListaParametrosActuales > ::= , { int i = <restoListaParametrosActuales>.index if(i >= <restoListaParametrosActuales>.listaParFor.size() && !<restoListaParametrosActuales>.predefinida ) error( numero de parametros actuales no corresponde con los formales); if(!<restoListaParametrosActuales>.predefinida) Entry e = <restoListaParametrosActuales>.listaParFor.get(i); if(<restoListaParametrosActuales>.predefinida){ 66

if(<restoListaParametrosActuales>.id = "read" || <restoListaParametrosActuales>.id ="readln") <expresin>.porValor = false; else <expresin>.porValor = true; } else <expresin>.porValor = e.porValor; } <expresin> { if(!<restoListaParametrosActuales>.predefinida && !e.tipo.compatibleCon (<expresin>.tipo)) error(incompatibilidad de tipos entre parmetro formal y actual) if(<restoListaParametrosActuales>.predefinida) { if(!<expresin>.tipo.esSimple()) error(se espera un parmetro de tipo simple) genPredefinida(<restoListaParametrosActuales>.id, <expresin>.tipo); } <restoListaParametrosActuales>2.predefinida = <restoListaParametrosActuales>.predefinida; <restoListaParametrosActuales>2.listaParFor = <restoListaParametrosActuales>.listaParFor; <restoListaParametrosActuales>2.id = <restoListaParametrosActuales>.id; <restoListaParametrosActuales>2.index = i + 1

} <restoListaParametrosActuales >2

Funcion para generar codigo mepa de funciones predefinidas genPredefinida(string id, TipoSimple t){ if (!(t.esEntero || t.esSubrango)) Error(las operaciones predefinidas solo admiten tipos enteros) if ( id.equalsIgnoreCase(write)) genMepa(IMPR) If ( id.equalsIgnoreCase(writeln)) genMepa(IMLN) If ( id.equalsIgnoreCase(read)) { genMepa(LEER); if (t.esSubrango()) genMepa(CONT, t.getValInferior(),t.getValSuperior()) genMepa(ALDR); } If (id.equalsIgnoreCase(readln)){ genMepa(LELN); if (t. esSubrango()) genMepa(CONT, t.getValInferior(),t.getValSuperior()) genMepa(ALDR); } If(id.equalsIgnoreCase(succ)) { genMepa(APCT 1 ) genMepa(SUMA) 67

if (t. esSubrango()) genMepa(CONT, t.getValInferior(),t.getValSuperior()) else genMepa(CONT, - MAXINT,MAXINT) } If(id.equalsIgnoreCase(pred)) { genMepa(APCT 1 ) genMepa(SUST) if (t. esSubrango()) genMepa(CONT, t.getValInferior(),t.getValSuperior()) else genMepa(CONT, - MAXINT,MAXINT) } }

2. Errores Semnticos
Cdigo 0 1 2 3 4 5 6 7 8 10 11 12 14 15 16 17 18 19 20 21 22 23 24 26 27 28 29 30 31 33 Mensaje identificador ya declarado se espera un tipo simple identificador de constante no valido No se puede aplicar + o - a una constante no entera El tipo integer no es un tipo de ndice valido Identificador de tipo no valido Identificador de parmetro formal repetido Identificador desconocido Incopatibilidad de tipos en asignacin Se espera un arreglo Se espera una expresin de tipo boolean Se espera una expresin de tipo simple los operadores relacionales solo se aplican a expresiones de tipos simples expresin relacional con tipos incompatibles se espera el nombre de una variable o componente de un arreglo como parmetro actual se espera el nombre de una variable o componente de arreglo los operadores unarios + o solo se aplica a expresiones enteras no se permite pasar por referencia un valor numrico o booleano Tipos incompatibles en expresin no se puede sumar ni restar valores de tipo arreglo o booleano no se puede multiplicar o dividir valores de tipo arreglo o booleano se esperan operando de tipo boolean no se puede pasar una numero o funcin por referencia El identificador no corresponde a una funcin no se puede pasar una funcin por referencia faltan parmetros actuales incompatibilidad de tipos entre parmetro formal y actual se espera un parmetro de tipo simple el numero de parmetros actuales no corresponde con los formales se espera un identificado de procedimiento o := ausente 68

34 35 36 37 38 39

el identificador no corresponde a una entidad asignable se esperan operando de tipo entero o subrango se esperan un identificador de Variable, Constante, Funcin o Parmetro valor de tipo incompatible con la expresin en la sentencia case subrango de valores invalido (el limite inferior debe ser menor al limite superior) Magnitud no representable

8. Compilador
Decisiones de Diseo Creacin de clase MiniPas para ensamblar las etapas de anlisis y ejecucin en una sola entidad testeable: Como vimos en las entregas anteriores, cada modulo del compilador es una entidad testeable; es decir que se puede ejecutar por separado. Nuestro compilador final ser entonces un nuevo test el cual combina la ejecucin del modulo de anlisis y generacin de cdigo (AnalizadorSintactico) con el modulo de ejecucin (Mepa). Inclusin de archivo de configuracin: Para dar mayor flexibilidad al testing y ejecucin del compilador se creo un archivo llamado minipas.conf el cual contiene ciertas propiedades que podemos modificar. Por ejemplo: generacin de cdigo opcional, habilitar modo debug..etc. En el punto 6 del informe, se explica detalladamente las propiedades y sus valores que pueden tomar. Creacin de Tabla de smbolos abstracta y genrica: La clase AbstractSimbolTable <T>, es una clase abstracta y genrica que sirve de base para implementar cualquier tabla de smbolos en la cual se desean almacenar entradas de tipo T. Mantiene la estructura de pila de tablas de simbolos (Hashtable). Provee los metodos: - void crearNivelLxico(): construye una nueva tabla y la apila void eliminarNivelLexico(): elimina la tabla del tope de la pila int getNivelLexico(): retorna el nivel lxico actual abstract void init(): Este es el mtodo de inicializacin que las subclases deben implementar. En el se cargaran las entidades predefinidas y/o cualquier otra informacin necesaria antes de comenzar la compilacin. boolean estaDeclarado(String id): chequea si el identificador pertenece a la tabla actual T buscar(String id): busca a partir de la tabla del tope de la pila hasta encontrar la entrada (de tipo T) para ese identificador o retornar null si no se encuentra. void inserta(String name, T entry): inserta una entrada T para el nombre name dentro de la tabla de smbolos actual (del tope de la pila). 69

En la documentacin final se explica en detalle la estructura y el funcionamiento. Implementacin concreta de la tabla de smbolos con entradas de tipo Entry: Se cre la clase EntryTable que en definitiva es la tabla de simbolos. Hereda de AbstractSimbolTable para implementar entradas de tipo Entry: public final class EntryTable extends AbstractSimbolTable<Entry>{ ... } Redefine el mtodo init(), en el cual se agregan las sig. entidades: - Tipos: integer y boolean - Constante maxint - Constantes true y false - Procedimentos predefinidos: read, readln, write, writeln - Funciones predefinidas: succ(x) y pred(x) En la documentacin final se explicaran todos los mtodos de la clase. Creacin de jerarqua de clases para representar tipos: La Tipo, es una clase abstracta y base para los tipos del lenguaje. Proporciona, entre otros, dos mtodos abstractos que las subclases deben implementar: - abstract boolean esEquivalenteCon(Tipo t): determina cuando un tipo es equivalente con otro. abstract int getSize(): retorna el numero de locaciones de memoria que abarca el tipo.

Creacin de clase TipoFactory: Esta clase solamente contiene mtodos estticos que nos proveen los diferentes tipos que necesitamos: static Tipo crearTipoSimple(int cod) static Tipo crearTipoBooleano(); static Tipo crearTipoEntero(); static Tipo crearTipoSubrango(int inf, int sup); static Tipo crearTipoArreglo(TipoSimple tindice, TipoSimple tRango); El objetivo de esta clase, es tal cual el objetivo del patrn de diseo Factory: centralizar la creacin de un objeto de manera eficiente. Es eficiente primero porque los mtodos son estticos, y segundo porque se pueden reusar los objetos creados. Por ejemplo, cada vez que se solicita un tipo entero TipoFactory.crearTipoEntero() se retorna siempre el mismo objeto. Para los tipos subrango y array no es posible reusar objetos dado que en ellos la informacin de sus atributos es variable (ej: limite inferior y superior del subrango puede ser diferente en muchas invocaciones).

Creacin de clase BufferedFileWriter:


Permite bufferear la escritura de las instrucciones en el archivo mepa de salida. Utiliza el metodo write(String str) de su clase padre java.io.BufferedWriter. Creacin de clase SemanticException como contenedora de todos los errores semnticos.

Casos de Test 70

Los casos de test se ubican en el directorio test del proyecto. Estn organizados en forma jerrquica, como indica la siguiente figura: test lxico validos no-validos sintctico validos no-validos semntico validos no-validos mepa validos no-validos Adems, se a adoptado la siguiente poltica: - Test Validos: pocos test largos - Test No validos: muchos test cortos. Organizacin de Paquetes y Clases main: Main.java MiniPas.java Testeador.java Testeable.java Utils BufferedFileReader.java BufferedFileWriter.java Reader.java aLexico AnalizadorLexico.java Token.java aSintactico AbstractSimbolTable.java EntryTable.java Entry.java AnalizadorSintactico.java aSintactico.tipos Tipo.java TipoFactory.java TipoSimple.java TipoSubrango.java TipoArreglo.java

71

mepa ALMepa.java TokenMepa.java Instruccin.java ASMepa.java Mepa.java

exceptions BasicException.java MepaException.java LexicException.java SintacticException.java SemanticException.java

9. Archivo de configuracin (minipas.conf)


En el directorio base del proyecto se encuentra el archivo minipas.conf. Dentro del mismo podemos setear las siguientes propiedades: Propiedad gen_codigo debug Valores Posibles on / off on / off Descripcin Si est en off realiza el anlisis sin generacin de cdigo. Si est en on ejecuta el compilador mostrando un mayor nivel de detalle informativo en pantalla. Es til para realizar trazas en busca de errores en el cdigo. Indica al compilador los archivos que puede ejecutar. Por default solo tiene la extensin .pas

file_extension

Lista de extensiones de archivos separadas por coma. Ej .pas, .txt

La generacin de cdigo opcional permite al desarrollador realizar tests puntuales del anlisis lxico, sintctico o semntico. Esto es til cuando el objetivo no es ejecutar el programa sino verificar si el programa pasa o no la etapa de anlisis. Una ventaja de esto es que el test resulta mas eficiente ya que se saltea la etapa de ejecucin, en donde se cargan, analizan y ejecutan las instrucciones. Una ventaja importante del modo debug es que si ocurre una excepcin, se conserva el archivo mepa con las instrucciones generadas hasta ese momento. Por lo tanto tenemos un panorama de informacin an mayor que simplemente el mensaje de error en pantalla. Las extensiones de archivos soportadas dan mayor seguridad a la hora de ejecutar el compilador. Por ejemplo, si ejecutamos a partir de un directorio, el testeador va a probar compilar todos los archivos contenidos en el mismo. El problema es que en ese directorio podran haber otros archivos que no contienen cdigo fuente; por ejemplo: los archivos .mep generados en los tests previos. Entonces gracias a esta propiedad le decimos al compilador que saltee los archivos que no tienen la extensin indicada.

10. Modos de Ejecucin


72

1) Ejecucin con Testeador: Es el mtodo ms flexible, ya que permite testear los mdulos del compilador en forma separada. Sintaxis: java jar dist/MiniPascal.jar <clase> <file o dir> Ejemplos: - Testeo del Compilador: java jar dist/MiniPascal.jar main.Minipas <file o dir> - Testeo de la MePA: java jar dist/MiniPascal.jar mepa.Mepa <file o dir> - Testeo del analizador lxico: java jar dist/MiniPascal.jar aLexico.AnalizadorLexico <file o dir>

2) Ejecucin con mtodo main (tradicional) Ejecuta solamente el compilador (anlisis sintctico y semntico + mepa). java cp dist/MiniPascal.jar main.Main <file o dir> Nota: aqu ejecutamos con la opcin cp en vez de -jar, esto es porque en el manifest esta especificado que la clase principal sea main.Testeador . Por lo tanto si ejecutamos con jar implcitamente se invoca al main de la clase Testeador. 3) Ejecucin mediante scripts: minipas.bat: ejecuta el compilador como se indica en el modo 2) test-minipas.bat: ejecuta el compilador como se indica en el modo 1) test-lxico.bat: realiza el anlisis lxico mostrando los tokens del programa test-lexicoMepa.bat: realiza el anlisis lxico del archivo mepa test-sintctico.bat: realiza el anlisis sintctico y semntico del programa fuente test-sintacticoMepa.bat: realiza el anlisis sintctico del archivo mepa test-mepa.bat: ejecuta el archivo con las instrucciones mepa

Para ms informacin leer el archivo Readme.txt que se encuentra en el directorio del proyecto.

11. JavaDoc
73

En el directorio dist/javadoc se encuentra la documentacin de las APIs del proyecto en formato html.

74

Você também pode gostar