Está en la página 1de 14

El analizador sintáctico es una de las fases

de un compilador donde se tiene por


finalidad verificar el ordenar los tokens ,
obtenidos del analizador lexicográfico, a
partir de una gramática de libre contexto.

ANALIZADOR
SINTÁCTICO

ROQUE CALDAS DOMINGUEZ


ANALIZADOR SINTÁCTICO

1. INTRODUCCIÓN

El analizador léxico tiene como entrada el código fuente en forma de una sucesión de caracteres.
El analizador sintáctico tiene como entrada los lexemas que le suministra el analizador léxico y
su función es comprobar que están ordenados de forma correcta (dependiendo del lenguaje que
queramos procesar). Los dos analizadores suelen trabajar unidos e incluso el léxico suele ser una
subrutina del sintáctico. Al analizador sintáctico se le suele llamar párser. El párser genera de
manera teórica un árbol sintáctico. Este árbol se puede ver como una estructura jerárquica que
para su construcción utiliza reglas recursivas. La estructuración de este árbol hace posible
diferenciar entre aplicar unos operadores antes de otros en la evaluación de expresiones. Es
decir, si tenemos esta expresión en Java:

x = x * y – 2;
El valor de x dependerá de si aplicamos antes el operador producto que el operador suma. Una
manera adecuada de saber qué operador aplicamos antes es elegir qué árbol sintáctico generar
de los dos posibles.

Figura 1.1|Árbol sintáctico

Figura 1.2|Árbol sintáctico


ANALIZADOR SINTÁCTICO

En resumen, la tarea del analizador sintáctico es procesar los lexemas que le suministra el
analizador léxico, comprobar que están bien ordenados, y si no lo están, generar los informes
de error correspondientes. Si la ordenación es correcta, se generará un árbol sintáctico teórico.

2. FUNCIONES DEL ANALIZADOR SINTÁCTICO


La función principal del analizador sintáctico es determinar si una cadena de componentes
léxicos puede ser generada por una gramática.

Controla el flujo de tokens reconocidos por parte del analizador léxico y comprueba si la cadena
pude ser generada por la gramática del lenguaje fuente.

Informa de la naturaleza de los errores sintácticos que encuentra e intenta recuperarse de ellos
para continuar la compilación.

3. DISEÑO DE GRAMATICA
Para que un analizador sintáctico funcione, debemos especificar el lenguaje que debe poder
leer. Para especificar este lenguaje, debemos representarlo con unas reglas únicas y bien
formadas de manera que el párser (Analizador sintáctico) funcione de una manera bien definida.
Es decir, el lenguaje debe ser formal (tener unas reglas bien definidas). A estas reglas se le llama
gramática. Por lo tanto, el primer paso para poder implementar un analizador sintáctico es
definir la gramática que debe ser capaz de analizar.

Figura 3.1|Entradas y salidas de las dos primeras fases de la etapa de análisis.

Las gramáticas ofrecen ventajas significativas:

 Una gramática da una especificación sintáctica precisa y fácil de entender de un lenguaje


de programación.
ANALIZADOR SINTÁCTICO

 A partir de algunas clases de gramáticas se puede construir automáticamente un


analizador sintáctico eficiente que determine si un programa fuente está
sintácticamente bien formado.

 El proceso de construcción del analizador sintáctico puede revelar ambigüedades


sintácticas y otras construcciones difíciles de analizar que de otro modo podrían pasar
sin detectar en la fase inicial de diseño de un lenguaje y de su compilador.

La gramática que acepta el analizador sintáctico es una gramática de libre contexto, una
gramática de libre contexto es una especificación para la estructura sintáctica de un lenguaje de
programación. Una especificación así es muy similar a la especificación de la estructura léxica de
un lenguaje utilizando expresiones regulares(patrón), excepto que una gramática libre de
contexto involucra reglas de recursividad. Una gramática describe de forma natural la estructura
jerárquica de muchas construcciones de los lenguajes de programación. Una gramática libre de
contexto G queda definida por una tupla de cuatro elementos (N, T, P, S) donde:

N = No terminales. Elementos del lado izquierdo de producción, antes de la flecha

T= Terminales. Elementos que no generan nada.

P= Reglas de producción. Sentencias que se escriben en la gramática. Cada regla o producción


consta de:

 Cabeza: no terminales (lado izquierdo de la producción).

 : símbolo de producción.se lee “se define como” o “puede tener la forma”

 Cuerpo: cadena de 0 o más símbolos terminales y/o no terminales (lado derecho de


la producción).

S= Axioma inicial. Primer elemento de la gramática.

Las gramáticas libres de contexto permiten describir la mayoría de lenguajes de programación,


de hecho, la sintaxis de la mayoría de lenguajes de programación está definida mediante
gramáticas libres de contextos.

Pongamos un ejemplo de gramática e identificaremos cada uno de los elementos. Sea la


gramática:

E E+T | T  E, T, F son las no terminales.


 id, +, *, (,) son terminales.
T T*F|F
 Hay tres reglas de producción
F id | F |(E)  E es el axioma inicial.
ANALIZADOR SINTÁCTICO

Esta gramática reconoce expresiones aritméticas con los operadores de suma y producto.
Vemos también que hay tres reglas y el axioma inicial es el antecedente de la primera regla de
producción. E es recursiva porque se presenta en ambos lados de la producción.

Ahora veamos con un ejemplo cómo podemos crear una gramática. Para esto recodemos como
se declara una variable en java:

int a;
double b;

1) VAR -> TIPO ID;


2) TIPO -> int | double
3) ID - > id

A. DERIVACIONES UTILIZANDO UNA GRAMÁTICA

DERIVACIÓN: Aplicación de las reglas de producciones de una gramática para obtener una
cadena de terminales.

Una regla de producción puede considerarse como equivalente a una regla de reescritura,
donde el no terminal de la izquierda es sustituida por la pseudocadena del lado derecho de la
producción. Podemos considerar que una pseudocadena es cualquier secuencia de terminales
y/o no terminales.

Dependiendo de por dónde comencemos a reescribir en la pseudocadena, tendremos una


derivación por la izquierda (si comenzamos por la izquierda) o por la derecha (si comenzamos
por la derecha). Si queremos construir una cadena de tokens que sean generadas por una
gramática concreta, podremos hacerlo aplicando las reglas de la gramática según vayan
concordando con los tokens.

Por ejemplo, supongamos que tenemos la siguiente gramática:

𝐸 → 𝐸 + 𝐸 ȁ𝐸 ∗ 𝐸 ȁ𝑛𝑢𝑚ȁ𝑖𝑑ȁ(𝐸)

 Derivación por la izquierda

𝐸 → 𝐸 ∗ 𝐸 → 𝐸 + 𝐸 ∗ 𝐸 → 𝑖𝑑1 + 𝐸 ∗ 𝐸 → 𝑖𝑑1 + 𝑖𝑑2 ∗ 𝐸 → 𝑖𝑑1 + 𝑖𝑑2 ∗ 𝑖𝑑3

Es aquella en la que la reescritura se realiza sobre el no terminal más a la izquierda de la


pseudocadena de partida.

 Derivación por la derecha

𝐸 → 𝐸 ∗ 𝐸 → 𝐸 ∗ 𝑖𝑑3 → 𝐸 + 𝐸 ∗ 𝑖𝑑3 → 𝐸 + 𝑖𝑑2 ∗ 𝑖𝑑3 → 𝑖𝑑1 + 𝑖𝑑2 ∗ 𝑖𝑑3


ANALIZADOR SINTÁCTICO

Es aquella en la que la reescritura se realiza sobre el no terminal más a la derecha de la


pseudocadena de partida.

A partir de estas derivaciones se puede construir sus árboles sintácticos. Pero hay cosas en que
cada posible derivación dará lugar a un árbol sintáctico diferente. Esto significa que la gramática
es ambigua.

Veamos un ejemplo. Supongamos que tenemos la gramática anterior y queremos procesar estos
tokens:

𝑖𝑑1 + 𝑖𝑑2 + 𝑖𝑑3


Hay dos posibles árboles sintácticos:

Figura 3.2|Derivación por la izquierda

Figura 3.3| Derivación por la derecha

Por lo tanto, deduciremos que la gramática es ambigua. Para la implementación de esta


gramática, es necesario esta ambigüedad. El orden en que vamos creando las ramas y las hojas
no da la idea del orden en que se irán procesando las reglas. Por lo tanto, tenemos un
mecanismo secuencial de procesamiento.
ANALIZADOR SINTÁCTICO

La raíz del árbol es el axioma inicial y, según nos convenga, lo dibujaremos en l a cima o en el
fondo del árbol. Como nodos internos del árbol, se sitúan los elementos no terminales de las
reglas de producción que vayamos aplicando, y cada uno de ellos poseerá tantos hijos como
símbolos existan en la parte derecha de la regla aplicada.

4. DIFICULTADES PARA LA CREACIÓN DE GRAMÁTICAS


A. RECURSIVIDAD
La recursividad se expresa por medio de una o más reglas no recursivas, que son la base, y una
o más reglas que son recursivas y que permiten hacer crecer la estructura del lenguaje
aplicándose a sí mismas una y otra vez. Con un ejemplo, lo entenderemos mejor:

Supongamos que queremos expresar la estructura de un número entero compuesto por su signo
seguido por un número indeterminado de números entre el 0 y el 9. Lo podríamos expresar con
estas reglas:

𝐸𝑛𝑡𝑒𝑟𝑜 → 𝑠𝑖𝑔𝑛𝑜

𝐸𝑛𝑡𝑒𝑟𝑜 → 𝐸𝑛𝑡𝑒𝑟𝑜 𝑑𝑖𝑔𝑖𝑡𝑜

Donde dígito representa cualquiera de los números del 0 al 9. Mediante esas dos reglas
podemos representar la estructura de cualquier número entero sea de la longitud que sea.

Una gramática se llama recursiva si es de la forma:

𝐴→𝑎𝐴𝑏

Donde A es un no terminal y a y b son terminales o no terminales. Al ter minal A le llamamos t


erminal recursivo. Si no existe el término a, se trata de una recursividad por la izquierda y si no
existe b es una recursividad por la derecha.

B. LA AMBIGÜEDAD
Cuando una gramática contiene una cadena para la que hay más de un árbol de análisis
sintáctico se dice que es ambigua. Debido a que una gramática de estas características permite
que a partir del mismo código fuente se puedan obtener diferentes códigos intermedios, no es
válida para construir un compilador (habría que ayudar con otras técnicas más complicadas).

Si una gramática tiene alguna de estas características, podremos afirmar que es ambigua:

 Gramáticas con ciclos:

𝑆→𝐴
ANALIZADOR SINTÁCTICO

𝑆→𝑎
𝐴→𝑆

 Gramáticas con alguna regla de la forma:

𝐸 → 𝐸….𝐸

 Gramáticas con unas reglas que ofrezcan caminos alternativos entre dos puntos.

Por ejemplo:

𝑆→𝐵
𝑆→𝐶
𝐵−𝐶

 Producciones recursivas en las que las variables no recursivas de la producción


puedan derivar a la cadena vacía.

Por ejemplo:

𝑆 →𝐴𝐵𝑆
𝑆→𝑆

𝐴 → 𝑎 ȁ€

𝐵 → 𝑏 ȁ€

 Símbolos no terminales que puedan derivar a la cadena vacía y a la misma cadena de


terminales, y que aparezcan juntas en la parte derecha de una regla o en alguna forma
sentencia.

Por ejemplo:

𝐴→𝐴𝐵

𝐴→𝑎ȁ€

𝐵 → 𝑏 ȁ𝑎ȁ€
ANALIZADOR SINTÁCTICO

SUPRESION DE LA AMBIGÜEDAD
A veces, una gramática ambigua se puede reescribir para eliminar la ambigüedad. Como
ejemplo, se eliminará la ambigüedad de la siguiente gramática con “else ambiguo”:

𝑃𝑅𝑂𝑃 → 𝑖𝑓 𝐸𝑋𝑃𝑅 𝑡ℎ𝑒𝑛 𝑃𝑅𝑂𝑃 ห 𝑖𝑓 𝐸𝑋𝑃𝑅 𝑡ℎ𝑒𝑛 𝑃𝑅𝑂𝑃 𝑒𝑙𝑠𝑒 𝑃𝑅𝑂𝑃 ห 𝑜𝑡𝑟𝑎

Aquí, “otra” representa cualquier otra proposición. Esta gramática es ambigua, puesto que la
cadena

𝑖𝑓 𝐸1 𝑡ℎ𝑒𝑛 𝑖𝑓 𝐸2 𝑡ℎ𝑒𝑛 𝑆1 𝑒𝑙𝑠𝑒 𝑆2

Tiene los dos árboles de análisis sintáctico que se muestra a continuación

Figura 4.1|Árbol de análisis sintáctico para la proposición condicional

Figura 4.2| Dos árboles de análisis sintáctico para una frase ambigua
ANALIZADOR SINTÁCTICO

En todo lenguaje de programación con proposiciones condicionales de esta forma, se prefiere


el primer árbol de análisis sintáctico. La regla general es, “emparejar cada else con el then sin
emparejar anterior más cercano”. Esta regla para eliminar ambigüedades se puede incorporar
directamente a la gramatica. La ide es que una proposición que aparezca entre un then si
emparejar seguido de cualquier proposición, porque entonces el else estaría obligado a
concordar con este then no emparejado. Una proposición emparejada es o una proposición if-
then-else que no contenga proposiciones sin emparejar o cualquier otra clase de proposición
no condicional. Así, se puede utilizar la gramática

𝑃𝑅𝑂𝑃 → 𝑃𝑅𝑂𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴ȁ 𝑃𝑅𝑂𝑃𝑁𝑂𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴

𝑃𝑅𝑂𝑃𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴 → 𝑖𝑓 𝑒𝑥𝑝𝑟 𝑡ℎ𝑒𝑛 𝑃𝑅𝑂𝑃𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴 𝑒𝑙𝑠𝑒 𝑃𝑅𝑂𝑃𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴 ȁ 𝑜𝑡𝑟𝑎

𝑃𝑅𝑂𝑃𝑁𝑂𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴 → 𝑖𝑓 𝐸𝑋𝑃𝑅 𝑡ℎ𝑒𝑛 𝑃𝑅𝑂𝑃 ȁ 𝑖𝑓 𝐸𝑋𝑃𝑅 𝑡ℎ𝑒𝑛 𝑃𝑅𝑂𝑃𝑁𝑂𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴 𝑒𝑙𝑠𝑒 𝑃𝑅𝑂𝑃𝑁𝑂𝐸𝑀𝑃𝐴𝑅𝐸𝐽𝐴𝐷𝐴

C. LA ASOCIATIVIDAD
La asociatividad es un concepto que aparece cuando se operan tres o más operandos. La
asociatividad de un operador es por la izquierda si cuando aparecen tres o más operandos se
evalúan de izquierda a derecha. Si es de derecha a izquierda, la asociatividad es por la derecha.

Por ejemplo, si tenemos “6/3/2”, por convención es equivalente a (6/3) /2. Cuando un operando
como 3 tiene operadores a su izquierda y derecha, se necesitan convenciones para decir qué
operador considera ese operando. si el operador “/” tiene asociatividad por la izquierda,
primero se opera “6/3” el resultado se opera con “2” es 1.

Algunos operadores comunes, como el exponenciación. Son asociativos por la derecha. Otro
ejemplo análogo, el operador de asignación “=” en java es asociativo por la derecha: en java, la
expresión a=b=c se trata igual que la expresión a=(b=c).

Las cadenas como a=b=c. Con un operador asociativo por la derecha. Son generados por la
siguiente gramática:

𝐷𝐸𝑅𝐸𝐶𝐻𝐴 → 𝐿𝐸𝑇𝑅𝐴 = 𝐷𝐸𝑅𝐸𝐶𝐻𝐴ȁ𝐿𝐸𝑇𝑅𝐴

𝐿𝐸𝑇𝑅𝐴 → 𝑎ȁ𝑏ȁ𝑐 … ȁ𝑧

El contraste entre un árbol de análisis sintáctico para un operador asociativo por la izquierda
como “/”, y un árbol de análisis sintáctico para un operador asociativo por la derecha como “=”,
El árbol de análisis sintáctico para 6/3/2 desciende hacia la izquierda, mientras que el árbol de
análisis sintáctico a=b=c desciende hacia la derecha.

La manera de reflejar la asociatividad de un operador en una gramática es poniendo


recursividad del mismo lado que el operador en la regla sintáctica donde interviene dicho
operador.
ANALIZADOR SINTÁCTICO

D. LA PRECEDENCIA
La precedencia de un operador indica el orden en que se aplicará respecto a los demás
operadores en caso de poder aplicar más de uno. Es decir, si en una regla podemos aplicar más
de un operador, comenzaremos aplicando el de más precedencia y terminaremos por aplicar el
de menor precedencia. La manera de reflejar la precedencia en una gramática es utilizar para
cada operador una variable en la gramática y situarla más cerca del símbolo inicial cuanto menor
sea la precedencia.

_____________________________________________________________________________

Ejemplo: Sintaxis de expresiones

utilizando una tabla que muestre la asociatividad y procedencia de operadores se puede


construir una gramática para expresiones aritmética. Se empieza con los cuatro operadores
aritmético básico y una tabla de precedencias, mostrando los operadores en orden de
procedencia creciente, con los operadores de la misma precedencia en la misma línea.

asociativos por la izquierda: + -

asociativos por la derecha: * /

SOLUCIÓN A LA PROCEDENCIA:

se crean dos no terminales EXPR y TERMINO para los dos niveles de precedencia, y un no
terminal adicional factor para generar unidades básicas en las expresiones. Ponemos primero
las reglas con menor procedencia “+” y “- “y al final de mayor precedencia “*” y “/”

Las unidades básicas de las expresiones son de momento dígitos y expresiones entre paréntesis.

𝐹𝐴𝐶𝑇𝑂𝑅 → 𝑑𝑖𝑔𝑖𝑡𝑜 ȁ (𝐸𝑋𝑃𝑅)

ahora, considérese los operadores binarios * y /, que tienen mayor procedencia.

𝑇𝐸𝑅𝑀𝐼𝑁𝑂 → 𝑇𝐸𝑅𝑀𝐼𝑁𝑂"*"𝐹𝐴𝐶𝑇𝑂𝑅ห 𝑇𝐸𝑅𝑀𝐼𝑁𝑂"/"𝐹𝐴𝐶𝑇𝑂𝑅ห𝐹𝐴𝐶𝑇𝑂𝑅

de manera similar, <expr> genera listas de términos separados

EXPR→ 𝐸𝑋𝑃𝑅 " + " 𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ 𝑇𝐸𝑅𝑀𝐼𝑁𝑂" − "𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝑇𝐸𝑅𝑀𝐼𝑁𝑂

por lo tanto, la gramática resultante es:

𝐸𝑋𝑃𝑅 → 𝐸𝑋𝑃𝑅" + "𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝐸𝑋𝑃𝑅" − "𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝑇𝐸𝑅𝑀𝐼𝑁𝑂

𝑇𝐸𝑅𝑀𝐼𝑁𝑂 → 𝑇𝐸𝑅𝑀𝐼𝑁𝑂" ∗ "𝐹𝐴𝐶𝑇𝑂𝑅 ห 𝑇𝐸𝑅𝑀𝐼𝑁𝑂"/"𝐹𝐴𝐶𝑇𝑂𝑅 ห𝐹𝐴𝐶𝑇𝑂𝑅

𝐹𝐴𝐶𝑇𝑂𝑅 → 𝑑𝑖𝑔𝑖𝑡𝑜 ȁ(𝐸𝑋𝑃𝑅)

es posible que un analizador sintáctico descendiente recursivo entre en un bucle indefinido.

𝐸𝑋𝑃𝑅−> 𝐸𝑋𝑃𝑅 + 𝑇𝐸𝑅𝑀𝐼𝑁𝑂


ANALIZADOR SINTÁCTICO

LA GRAMÁTICA PRESENTA RECURSIVIDAD:

Hay un problema con producciones recursivas por la izquierda en la que el símbolo situado más
a la izquierda del lado derecho de la producción es el mismo que el no terminal del lado izquierdo
de la producción.

SOLUCIÓN A LA RECURSIVIDAD POR LA IZQUIERDA:

se puede eliminar una producción recursiva por la izquierda reescribiendo la producción

𝐴 → 𝐴𝑎 ȁ𝑏

donde a y b son secuencias de terminales y no terminales que no comienzan con A como en


nuestro ejemplo

𝐸𝑋𝑃𝑅 → 𝐸𝑋𝑃𝑅"+"𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝑇𝐸𝑅𝑀𝐼𝑁𝑂

𝐴 = 𝐸𝑋𝑃𝑅 , 𝑎 = " + "𝑇𝐸𝑅𝑀𝐼𝑁𝑂 𝑦 𝑏 = 𝑇𝐸𝑅𝑀𝐼𝑁𝑂

se remplaza A por b

𝐸𝑋𝑃𝑅 → 𝑇𝐸𝑅𝑀𝐼𝑁𝑂 "+ " TERMINO

EL RESULTADO FINAL:

𝐸𝑋𝑃𝑅 → 𝑇𝐸𝑅𝑀𝐼𝑁𝑂" + "𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝑇𝐸𝑅𝑀𝐼𝑁𝑂" − "𝑇𝐸𝑅𝑀𝐼𝑁𝑂ȁ𝑇𝐸𝑅𝑀𝐼𝑁𝑂

𝑇𝐸𝑅𝑀𝐼𝑁𝑂 → 𝐹𝐴𝐶𝑇𝑂𝑅" ∗ "𝐹𝐴𝐶𝑇𝑂𝑅 ห 𝐹𝐴𝐶𝑇𝑂𝑅"/"𝐹𝐴𝐶𝑇𝑂𝑅 ห𝐹𝐴𝐶𝑇𝑂𝑅

𝐹𝐴𝐶𝑇𝑂𝑅 → 𝑑𝑖𝑔𝑖𝑡𝑜 ȁ(𝐸𝑋𝑃𝑅)

5. ANALIZADOR SINTÁCTICO EN JAVACC

Se trata de una herramienta que facilita la construcción de analizadores léxicos y sintácticos por
el método de las funciones recursivas, aunque permite una notación relajada muy parecida a la
BNF.

 Genera analizadores descendentes, permitiendo el uso de gramáticas de propósito


general y la utilización de atributos tanto sintetizados como heredados durante la
construcción del árbol sintáctico.

 Las especificaciones léxicas y sintácticas se ubican en un solo archivo. De esta manera la


gramática puede ser leída y mantenida más fácilmente. No obstante, cuando se
introducen acciones semánticas, recomendamos el uso de ciertos comentarios para
mejorar la legibilidad.
ANALIZADOR SINTÁCTICO

Los programas JavaCC se suelen almacenar en ficheros con extensión .jj

Al aplicar el comando javacc Ejemplo.jj produce ficheros de salida relacionados con el analizador
sintáctico:

 Ejemplo.java: es el analizador sintáctico.

 EjemploTokenManager.java: es el analizador lexicográfico.

 Token.java: clase que implementa el objeto a través del cual se comunican el analizador
léxico y el sintáctico.

AREA DE FUNCIONES BNF: Como ya se ha comentado, JavaCC genera un analizador


sintáctico descendente implementado a base de funciones recursivas, de manera que cada
no terminal de nuestra gramática será convertido una función diferente, cuya
implementación será generado por javaCC. Esta tiene la siguiente estructura:

𝑡𝑖𝑝𝑜𝑅𝑒𝑡𝑜𝑟𝑛𝑜1 𝑓𝑢𝑛𝑐𝑖𝑜𝑛𝐽𝑎𝑣𝑎 (𝑝𝑎𝑟𝑎𝑚1 ):

{ 𝑐𝑜𝑑𝑖𝑔𝑜𝐽𝑎𝑣𝑎1 }

{ 𝑒𝑥𝑝𝑟𝐵𝑁𝐹1 }

𝑡𝑖𝑝𝑜𝑅𝑒𝑡𝑜𝑟𝑛𝑜2 𝑓𝑢𝑛𝑐𝑖𝑜𝑛𝐽𝑎𝑣𝑎 (𝑝𝑎𝑟𝑎𝑚2 ):

{ 𝑐𝑜𝑑𝑖𝑔𝑜𝐽𝑎𝑣𝑎2 }

{ 𝑒𝑥𝑝𝑟𝐵𝑁𝐹2 }

Dado que cada no terminal se convertirá en una función en Java, el desarrollador no sólo
debe indicar su nombre, sino la cabecera completa de dicha función. Este hecho es de
fundamental importancia puesto que:

JavaCC permite el intercambio de atributos entre reglas BNF mediante el paso de


parámetros y la obtención de resultados en el momento de hacer uso de un no terminal (o
lo que es lo mismo invocar a la función que lo implementa) lo que equivale,
respectivamente, a enviar atributos hacia abajo y hacia arriba en el árbol sintáctico.

6. REFERENCIAS

 Compiladores Principios, técnicas y herramientas. Alfred V. Aho, Ravi Sethi,


Jeffrey D. Ullman Adisson Wesley.

 Compiladores Conceptos fundamentales. Teufel, Schmidt, Teufel. Adisson


Wesley Iberoamericana.

 Modern compiler implementation in C. Appel. Cambridge


ANALIZADOR SINTÁCTICO

 Teoría de Autómatas y Lenguajes Formales. Dean Kelley. PrenticeHall Cambridge

También podría gustarte