domingo, 17 de diciembre de 2017

Practica PL1 (2017-2018): Parte 2 - Analizador sintáctico (I)

Ya hemos creado nuestro analizador lexico que nos devuelve los tokens correspondientes, ahora el analizador sintáctico nos dirá si esos tokens están bien colocados o no. Para ello, ahora tenemos que usar los llamados "elementos no terminales".

Para que lo veamos mas claro, un ejemplo en la vida real.

Una FRASE del tipo "noseque es nosecuantos" sigue el esquema SUJETO-PREDICADO, y al mismo tiempo SUJETO es un NOMBRE y PREDICADO es VERBO-ADJETIVO. FRASE, SUJETO y PREDICADO son lo que se conoce como elementos no terminales.

En mi desarrollo, usare palabras en minuscula como elementos no terminales y los tokens (terminales) los he puesto en mayusculas.

Empezamos a analizar un programa en ModulaUNED. Está compuesto por la palabra reservada MODULE, un identificador, un punto y coma, las declaraciones de constantes, tipos, variables, procedimientos y funciones, la palabra BEGIN, una serie de sentencias, la palabra END, un identificador y punto y coma.

Por tanto, podemos ir escribiendo que

programa ::= MODULE IDENTIFICADOR PUNTOYCOMA declaraciones BEGIN sentencias END IDENTIFICADOR PUNTOYCOMA;

Como podeis ver, he unificado las declaraciones en un solo grupo, que a su vez está compuesto por otros elementos no terminales:

declaraciones ::= declaracionConstantes declaracionTipos declaracionVariables declaracionProcedimientos;

A partir de ahora solo hay que seguir avanzando.

¿Como se declaran las constantes?

La sintaxis dice que una constante se declara con la palabra CONST, un identificador, IGUAL, un valor, que puede ser un valor numerico o un valor logico (TRUE o FALSE) y un punto y coma

Entonces la declaracion de una constante es

asignacionConstante ::= CONST IDENTIFICADOR IGUAL CONSTANTE_NUMERICA PUNTOYCOMA|CONST IDENTIFICADOR valorBooleano PUNTOYCOMA

valorBooleano ::= TRUE|FALSE;

Aqui, si os fijais, he dado dos posibles interpretaciones al mismo elemento no terminal. Esto nos permite añadir varias posibilidades, incluido que aparezca o no un elemento.

Ahora vamos a definir un nuevo concepto: el vacio (que se representa en algunos sitios como epsilon o como lambda. Para verlo claro, en un listado de constantes puede haber una constante, muchas o ninguna. Tambien existe la posibilidad de definirlo de manera recursiva (a diferencia de en el analizador lexico). Veamos como queda la declaracion de constantes.

declaracionConstantes ::= asignacionConstante declaracionConstantes|/*epsilon*/;

En este caso, si no hay ninguna asume que es
declaracionConstantes = /*epsilon*/
o sea, que no hay nada definido.

En el caso de que haya una sola,

declaracionConstantes = asignacionConstante /*epsilon*/

y si hay varias (lo marco con parentesis):

declaracionConstantes = asignacionConstante (asignacionConstante /*epsilon*/)

Podeis tambien tener la opcion de ponerlo al reves,

declaracionConstantes ::= declaracionConstantes asignacionConstante|/*epsilon*/;

Pero si os fijais existe recursividad a la izquierda. No es lo mas conveniente, ya que puede aparecer un error y será necesario especificar que quereis que se analice por la derecha, aunque desde el punto de vista teorico es perfectamente correcto.

Por hoy es suficiente. Podeis ir pensando como se haría con el resto de elementos.

Tambien podeis ir agregando las lineas correspondientes a los elementos no terminales que creais que vais a usar junto a las lineas de terminal de los tokens.

Un saludo.

No hay comentarios:

Publicar un comentario