Vous êtes sur la page 1sur 13

FUNDAMENTOS DE CIENCIAS DE LA COMPUTACION

SableCC
Luis Gajardo lgajardo@ubiobio.cl

Qu es SableCC?
SableCC fue creado por Etienne Gagnon como tesis de magister en la Universidad de McGill. Es un entorno orientado a objeto que permite la construccin de compiladores usando el lenguaje Java. Los compiladores construidos son de tipo Ascendentes (Bottom-Up). SableCC provee: Generador de Lexer (analizador lxico) usando AFD. Generador de Parser (analizador sintctico) usando gramticas LALR(1). Genera las clases que representan el rbol de parsing. Genera un visitador para el rbol. Generador de Pretty-printer SableCC es multiplataforma. El sitio web de este proyecto es http://www.sablecc.org

Instalacin de SableCC
Descargar el archivo sablecc-2.18.2.zip desde la plataforma PVA. La distribucin sirve tanto para Windows como para Linux. En Windows: Descomprimir el archivo en la raz del disco C (u otro seleccionado) Agregar a la variable PATH la siguiente ruta: c:\sablecc-2.18.2\bin Editar el archivo sablecc.bat ubicado dentro de la carpeta bin y escribir dentro de el la siguiente ruta absoluta: c:\sablecc-2.18.2\lib\sablecc.jar Ejecutar sablecc desde cualquier directorio. En Linux: Descomprimir el archivo en HOME Agregar a la variable PATH la siguiente ruta: $HOME/sablecc-2.18.2/bin Editar el archivo sablecc ubicado en la carpeta bin y colocar la ruta absoluta a sablecc.jar.

Etapas de desarrollo con SableCC

Pasos para usar SableCC


Para construir un compilador con SableCC se requieren los siguientes pasos: 1. Crear un archivo de especificacin de SableCC que contenga la definicin lxica y gramatical del lenguaje a construir. 2. Ejecutar SableCC con el archivo con la especificacin para generar el entorno de desarrollo. 3. Crear una o ms clases, posiblemente heredadas de las clases de SableCC. 4. Crear una clase Compiler o similar con un mtodo main() para el compilador construido, la cual activar el lexer, parser y clases adicionales de usuario. 5. Compilar el compilador con Javac.

Archivo de especificacin de SableCC


Es un archivo de texto ASCII. Contiene las definicin lxicas (tokens) y especificacin de producciones de la gramtica.

[<package declaration>] [<helper declarations>] [<states declarations>] [<token declarations>] [<ignored tokens>] [<productions>] States declarations tpicamente no se utiliza.

SableCC

Package declaration
Permite definir el directorio raz a partir del cual SableCC generar los archivos y subdirectorios de nuestro proyecto. Ejemplo: Package tarea.java.cc.simplyc; Esto generar la siguiente estructura de directorios:

Estos directorios son generados por SableCC

Helper declarations
Supongamos que tenemos la siguiente expresin regular, definida en la seccin Token declarations: id = [a .. z] ([a .. z] | [0 .. 9])* Desearamos tener una forma ms abreviada y cmoda de representar lo mismo. Si declaramos la siguiente expresin regular en Token declarations: id = letter (letter | digit)* Entonces podramos usar las siguientes definiciones para letter y digit: letter = [a .. z]; digit = [0 .. 9]; De esta forma la seccin Helper declarations nos permite definir expresiones que nos ayudan a definir otras ms complejas.

Helper declarations
Otros ejemplos:
a = a | A ; b = b | B ; e = e | E ; g = g | G ; w = w | W; cr = 13 ; // retorno de carro o enter lf = 10 ; // alimentacin de lnea tab = 9 ; // tabulador ascii_char = [32 .. 127] ; blank = ; digit = [0 .. 9] ; letter = [[a .. z] + [A .. Z]] ; l_brace = { ; r_brace = } ; l_paren_star = (* ; r_paren_star = *) ;

Token declarations
Permite definir los tokens o smbolos terminales ms importantes de nuestra gramtica. Se debe decidir que declaraciones colocar en Helper y cuales en Token, aunque podramos tenerlas todas en Tokens. Ejemplos:
Tokens while = 'while'; begin = 'begin'; end = 'end'; do = 'do'; if = 'if'; then = 'then'; else = 'else'; semi = ';'; assign = '='; whitespace = (' ' | '\t' | '\n')+; id = ['a'..'z'](['a'..'z']|['0'..'9'])*;

Ignored tokens
Permite indicar cules tokens ignorar. Ejemplo:
Ignored tokens blank comment
Helper tab = 9 cr = 13 lf = 10 eol = cr lf | cr | lf blank = ( | tab | eol)+

ignorar los espacios en blanco

La definicin de blank y comment puede ubicarse en la seccin Helper. Tpicamente un lenguaje de programacin ignora los comentarios y no forman parte del proceso de compilacin, es decir, no son procesados por lo cual en este caso esta seccin es muy til.

Productions
En esta seccin se definen las producciones de la gramtica del lenguaje. Esta definicin se realiza utilizando el formato BNF (Backus Naur Form) Ejemplo:
Productions expression = {plus} expression plus number | {minus} expression minus number | {number} number;

Permite definir alternativas

Otorga un nombre a cada alternativa de la produccin

Ejemplo: archivo de especificacin de SableCC


Ejemplo: expresiones calculadora (suma, resta, multiplicacin y divisin) (45 + 36/2) * 3 + 5 * 2 Nuestro archivo puede llamarse as: postfix.grammar En este archivo pondremos una declaracin de Pakage, que corresponde al directorio raz para los archivos generados por SableCC, en este caso lo llamaremos postfix (Postfijo). Bajo la seccin Tokens agregamos definiciones lxicas para los nmeros, operadores aritmticos, parntesis y espacios en blanco. Bajo la seccin Ignored Tokens ponemos los espacios en blanco, para especificar que ellos son ignorados por el parser. Bajo la seccin Productions colocamos el listado de producciones de la gramtica. Se precede a cada alternativa de la produccin con un nombre encerrado entre llaves.

Ejemplo: archivo de especificacin de SableCC

Este archivo debe ser guardado en el directorio raz de nuestro proyecto.

Ejemplo: Ejecutar SableCC


Para generar el entorno de desarrollo ejecutamos el siguiente comando: $java SableCC postfix.grammar

Finalmente, miramos el contenido del directorio postfix. Dentro de el deberan haber 4 subdirectorios llamados lexer, parser, node y analysis.

Ejemplo: Crear clase Compiler


Ahora tenemos que crear una clase Compiler, desde la cual iniciar todas las etapas del procesamiento. Esta clase debe contener el mtodo esttico main() en el cual se lee la entrada y se ejecutan en secuencia cada una de las etapas: anlisis lxico, sintctico y semntico.

Ejemplo: Crear clase Compiler

Ejemplo: Compilar y ejecutar el compilador


Para compilar el programa:

Para ejecutar el compilador

ctrl

enter

Si la expresin es aceptada, entonces el compilador no debera hacer nada, ya que an no hemos programado la semntica asociada. Si la expresin no es aceptada debera retornar algn error o error (mensajes en ingls, creados automticamente por SableCC) incluso terminar abruptamente debido a que tampoco hemos implementado el manejo de errores.

Ejemplo: rbol de parsing


SableCC construye automticamente un conjunto de clases que representan los nodos del rbol de parsing. Un ejemplo del rbol real que se crea en memoria para un programa analizado es el siguiente:

Clases creadas por SableCC


Las clases generadas automticamente por SableCC se organizan en 4 directorios:
contiene las clases que implementan un patrn de diseo llamado Visitor (visitador) que permite recorrer todos los nodos del rbol realizando alguna analaysis actividad que defina el usuario. La clase DepthFirstAdapter constituye la clase abstracta base del visitador, extendindola podemos reescribir los mtodos que necesitemos para realizar alguna accin sobre algn nodo especfico. contiene la clase Lexer, entre otras, la cual implementa el analizador lxico, este es el primero que debe ser invocado al comenzar la compilacin. contiene todas las clases que representan la gramtica, estas clases se utilizan para construir el rbol de parsing.

lexer

node

contiene la clase Parser, entre otras, la cual permite realizar el anlisis sintctico (chequeando el programa de entrada contra las producciones de la parser gramtica).

10

Clases del rbol generado


Por defecto SableCC provee dos clases para recorrer el rbol: DepthFirstAdapter: que lo recorre primero en profundidad y ReversedDepthFirstAdapter: que lo recorre primero en horizontal y luego en vertical (o profundidad). Consideremos la primera clase del rbol (la raz) llamada Start.

Start PExpr EOF

Esta clase posee dos atributos, Una expresin PExpr y un fin de archivo EOF. La clase Start siempre ser la primera, no importa la gramtica que utilicemos.

Clases del rbol generado


Los mtodos que visitan esta clase (Start) se ubican en el archivo DepthFirstAdapter y tienen la siguiente forma:
public class DepthFirstAdapter extends AnalysisAdapter { public void inStart(Start node) { defaultIn(node); } public void outStart(Start node) { defaultOut(node); } public void defaultIn(Node node) { } public void defaultOut(Node node) { } public void caseStart(Start node) { inStart(node); node.getPExpr().apply(this); node.getEOF().apply(this); outStart(node); } ...

La palabra case se antepone a todos los mtodos que representan un nodo del rbol en el Visitor. En este caso caseStart visita a una instancia de la clase Start del rbol: 1. Primero se invoca a un mtodo (in) que ejecuta todo lo que queramos hacer antes de ingresar a los hijos de esta clase. 2. Luego se visitan los hijos 3. Finalmente se invoca a otro mtodo (out) que ejecuta todo lo que queramos hacer antes de salir de la clase.

11

Ejemplo: recorrer el rbol generado


Un ejemplo sencillo podra recorrer el rbol realizando alguna accin sobre el rbol de anlisis generado. Especficamente podramos traducir la expresin aritmtica ingresada en infijo a postfija (de ah el nombre del analizador generado).

infijo posfijo Para realizar esto crearemos una clase traductora llamada Translation (ubicada en postfix), la cual extender de DepthFirstAdapter (el visitador base). Luego sobre-escribiremos aquellas clases en las cuales se tenga que traducir alguna parte de la expresin.

Ejemplo: recorrer el rbol generado


El recorrido sera el siguiente: 1 3 9 5 8 7 4 6 10
Debemos imprimir los operadores al salir de cada expresin, para esto SableCC, provee un mtodo al que antepone la palabra out que significa que lo que va dentro de el se ejecuta justo antes de dejar ese nodo.

TLPar No imprime nada

12

Ejemplo: recorrer el rbol generado


package postfix; import postfix.analysis.*; import postfix.node.*; Se deben importar las clases para el anlisis (visitor) y las clases del rbol

Se deben extender del class Translation extends DepthFirstAdapter { Visitor Base

4 public void caseTNumber(TNumber node) { 6 //Cuando encontremos un nmero, lo imprimimos System.out.print(node); 7 }

Sobre escritura del mtodo que representa a un nmero

public void outAPlusExpr(APlusExpr node) { //Al salir de {plus} en Expr, imprimimos el signo + System.out.print(node.getPlus()); } public void outAMinusExpr(AMinusExpr node) { //Al salir de {minus} en Expr, imprimimos el signo System.out.print(node.getMinus()); }

Ejemplo: recorrer el rbol generado


public void outAMultFactor(AMultFactor node) { //Al salir de {mult} en Factor, imprimimos asterisco System.out.print(node.getMult()); } public void outADivFactor(ADivFactor node) { //Al salir de {div} en Factor, imprimimos slash (/) System.out.print(node.getDiv()); } public void outAModFactor(AModFactor node) { //Al salir de {mod} en Factor, imprimimos mod System.out.print(node.getMod()); } }

Los mtodos que no aparecen aqu no fueron sobre escritos y por lo tanto permanecen igual que en la clase DepthFirstAdapter.

13

Vous aimerez peut-être aussi