Thursday, 30 July 2009

Creando un Parser para Delphi

En éste artículo os mostraré lo fácil que es generar una pequeña gramática mediante ParserBuilder - COCO/R y crear el proyecto en Delphi para que parsee los datos entrados. En éste caso utilizaré el mismo ejemplo que viene con el ParserBuilder para crear una pequeña calculadora. La descripción del ejemplo para ésta calculadora es la siguiente:

La calculadora tiene un funcionamiento similar al de un intérprete, cuando recibe como entrada una expresión matemática sencilla como por ejemplo “12 + 5”, calcula el resultado de la operación y lo muestra por pantalla.
  • Los tipos de datos que puede manipular la calculadora son entero y real.
  • El formato de los números enteros es el habitual, es decir, un número entero es una secuencia de uno o más dígitos del 0 al 9.
  • El formato de los números reales consiste en un parte entera formada por una secuencia de cero o más dígitos del 0 al 9, a continuación un punto, y seguidamente la parte fraccionaria formada por una secuencia de uno o más dígitos del 0 al 9.
  • Las operaciones disponibles son: suma, resta, multiplicación y división para el tipo de datos real, y suma, resta y multiplicación para el tipo de datos entero. No está permitida ninguna operación aritmética con operandos de tipos diferentes.
  • Todas las operaciones se pueden agrupar con paréntesis.
  • Una expresión termina con un =.
  • El usuario puede introducir espacios en blanco y tabuladores, y todos serán ignorados. Las líneas vacías no están permitidas (una línea en blanco es un error sintáctico).
Utilizando ParserBuilder crearemos un fichero que contendrá la gramática de nuestra calculadora (.ATG). Aquí podréis descargar la versión que he utilizado ParserBuilder v0.9.0.213. Una vez tenemos el fichero en nuestro equipo, descomprimimos el fichero parserbuilder_v0_9_0_213_bin.zip e iniciamos ParserBuilder. Una vez abierto, podemos ver que el ejemplo que abre es la calculadora que vamos a utilizar.

Ahora, si nos dirigimos al final del fichero, podremos ver la gramática utilizada para parsear el lenguaje utilizado.

gramática:

CHARACTERS
digit =  "0123456789" .

TOKENS
num = digit {digit}.

NAMES

IGNORE CHR(1)..CHR(31)
PRAGMAS
PRODUCTIONS
Expr =
        (. Init ; .)
        Expression < fResult >
        "=" (. Final ; .)
        .
Expression <VAR e: INTEGER>
        (. VAR t: INTEGER ; .)
        =
        Term < e >  { '+' Term < t >       (. e := e + t  .)
        | '-' Term < t >                   (. e := e - t  .)
        }
        .
Term <VAR t: INTEGER>
        (. VAR f: INTEGER ; .)
        =
        Factor < t >  { '*' Factor < f >   (. t := t * f  .)
        | '/' Factor < f >                 (. t := t DIV f  .)
        }
        .
Factor <VAR f: INTEGER> =
        num                                (. GetNumber(f)  .)
|
        '(' Expression < f > ')'
        .


Una vez tenemos la gramática creada, generamos el proyecto para delphi:

Si nos fijamos, nos ha creado el código fuente para Delphi:


Ahora si nos dirigimos a la ruta C:\TEMP\parserbuilder_v0_9_0_213\Samples\Expr, encontraremos el proyecto Delphi para iniciarlo.

Al cargar el proyecto ExprTestHarness.dpr observaréis que puede ser que os salte un error debido a que no tenemos instalado el componente TJVDragDrop. Simplemente, ignoramos todos los errores y eliminamos el componente. En éste ejemplo no lo vamos a necesitar.

Et voilà!, ya tenemos nuestra calculadora:


Sobretodo fijaros en en código fuente generado y como crea un Parser y un Scanner para el lenguaje entrado. Espero que os haya gustado el artículo y que os sirva de ayuda!.

0 comments:

Post a Comment