23
Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez 2 03/06/2015 GENERADOR DE ANALIZADOR SINTÁCTICO YACC Yacc es un programa para generar analizadores sintácticos. Las siglas del nombre significan Yet Another Compiler-Compiler, es decir, "Otro generador de compiladores más". Genera un analizador sintáctico (la parte de un compilador que comprueba que la estructura del código fuente se ajusta a la especificación sintáctica del lenguaje) basado en una gramática analítica escrita en una notación similar a la BNF. Yacc genera el código para el analizador sintáctico en el Lenguaje de programación C. Fue desarrollado por Stephen C. Johnson en AT&T para el sistema operativo Unix. Después se escribieron programas compatibles, por ejemplo Berkeley Yacc, GNU bison, MKS yacc y Abraxas yacc (una versión actualizada de la versión original de AT&T que también es software libre como parte del proyecto de OpenSolaris de Sun). Cada una ofrece mejoras leves y características adicionales sobre el Yacc original, pero el concepto ha seguido siendo igual. Yacc también se ha reescrito para otros lenguajes, incluyendo Ratfor, EFL, ML, Ada, Java, y Limbo. Puesto que el analizador sintáctico generado por Yacc requiere un analizador léxico, se utiliza a menudo conjuntamente con un generador de analizador léxico, en la mayoría de los casos lex o Flex, alternativa del software libre. El estándar de IEEE POSIX P1003.2 define la funcionalidad y los requisitos a Lex y Yacc. La versión Yacc de AT&T se convirtió en software libre; el código fuente está disponible con las distribuciones estándares del Plan 9 y de OpenSolaris. Es correcto decir que yacc es una herramienta que sirve para generar un programa, capaz de analizar gramaticalmente una entrada dada por lex, a partir de una especificación. Esta especificación, debe contener los tokens reconocidos y

Generador de Analizador Sintáctico YACC y JavaCC - Copia

  • Upload
    vaz-vez

  • View
    101

  • Download
    1

Embed Size (px)

DESCRIPTION

Generador de Analizador Sintáctico YACC y JavaCC

Citation preview

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    2

    03/06/2015

    GENERADOR DE ANALIZADOR SINTCTICO YACC

    Yacc es un programa para generar analizadores sintcticos. Las siglas del nombre

    significan Yet Another Compiler-Compiler, es decir, "Otro generador de

    compiladores ms". Genera un analizador sintctico (la parte de un compilador

    que comprueba que la estructura del cdigo fuente se ajusta a la especificacin

    sintctica del lenguaje) basado en una gramtica analtica escrita en una notacin

    similar a la BNF. Yacc genera el cdigo para el analizador sintctico en el

    Lenguaje de programacin C.

    Fue desarrollado por Stephen C. Johnson en AT&T para el sistema operativo Unix.

    Despus se escribieron programas compatibles, por ejemplo Berkeley Yacc, GNU

    bison, MKS yacc y Abraxas yacc (una versin actualizada de la versin original de

    AT&T que tambin es software libre como parte del proyecto de OpenSolaris de

    Sun). Cada una ofrece mejoras leves y caractersticas adicionales sobre el Yacc

    original, pero el concepto ha seguido siendo igual. Yacc tambin se ha reescrito

    para otros lenguajes, incluyendo Ratfor, EFL, ML, Ada, Java, y Limbo.

    Puesto que el analizador sintctico generado por Yacc requiere un analizador

    lxico, se utiliza a menudo conjuntamente con un generador de analizador lxico,

    en la mayora de los casos lex o Flex, alternativa del software libre. El estndar de

    IEEE POSIX P1003.2 define la funcionalidad y los requisitos a Lex y Yacc.

    La versin Yacc de AT&T se convirti en software libre; el cdigo fuente est

    disponible con las distribuciones estndares del Plan 9 y de OpenSolaris.

    Es correcto decir que yacc es una herramienta que sirve para generar un

    programa, capaz de analizar gramaticalmente una entrada dada por lex, a partir de

    una especificacin. Esta especificacin, debe contener los tokens reconocidos y

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    3

    03/06/2015

    los tipos de datos de los mismos si es que se ocupan para realizar operaciones

    sobre ellos, y una especificacin de gramtica en un formato similar a BNF

    (Backus Naus Form), que va desde el smbolo no terminal ms general a cada una

    de las opciones terminales.

    Ejemplo:

    Numero + Numero - Numero En el ejemplo podemos ver que es un smbolo no terminal que est

    compuesto por un "Numero" terminal seguido de un smbolo '+' o '-' terminales

    seguido por un no terminal, que a su vez puede ser otro nmero u

    otra expresin ms compleja.

    Es importante notar que esta especificacin es recursiva sobre pero

    no es ambigua, es decir, siempre se llegara a un terminal.

    Una especificacin yacc se divide en tres secciones diferentes de manera similar a

    lex, la de definiciones, la de reglas, y la de subrutinas, que van igualmente

    separadas por un '%%', mismas que pueden incluir cdigo de C encerrado entre

    un %{ y un %}.

    Ejemplo 1.1 (Mini calculadora)

    A continuacin, vamos a analizar un ejemplo sencillo de una verdadera

    especificacin de yacc, que es la gramtica para una calculadora sencilla que

    permite hacer operaciones como suma, resta, multiplicacin, divisin y exponente.

    %{ #include %} %union{ double dval;

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    4

    03/06/2015

    } %token NUMBER %token PLUS MINUS TIMES DIVIDE POWER %token LEFT_PARENTHESIS RIGHT_PARENTHESIS %token END %left PLUS MINUS %left TIMES DIVIDE %left NEG %right POWER %type Expression %start Input %% Input: Line | Input Line ; Line: END | Expression END { printf("Result: %f\n",$1); } ; Expression: NUMBER { $$=$1; } | Expression PLUS Expression { $$=$1+$3; } | Expression MINUS Expression { $$=$1-$3; } | Expression TIMES Expression { $$=$1*$3; } | Expression DIVIDE Expression { $$=$1/$3; } | MINUS Expression %prec NEG { $$=-$2; } | Expression POWER Expression { $$=pow($1,$3); } | LEFT_PARENTHESIS Expression RIGHT_PARENTHESIS { $$=$2; } ; %% int yyerror(char *s) { printf("%s\n",s); } int main(void) { yyparse(); }

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    5

    03/06/2015

    Definiciones

    En esta primera seccin, al igual que en lex, incluimos las libreras que usaremos

    en el programa, definiciones de los tokens, tipos de datos y precedencia de la

    gramtica.

    %union

    Esta definicin, se traduce a una unin de C que a su vez dar el tipo de dato a

    una variable global de nombre yylval que ser de donde yacc tomara los datos a

    procesar, en la unin se definen miembros cuyos correspondientes tipos de datos

    sern usados para dar el tipo de dato a los tokens como se explicara en la

    siguiente seccin. %union se traduce de la siguiente forma:

    En yacc : %union{ double dval; } En C : typedef union { double dval; } YYSTYPE;

    Con esta definicin, yacc declara algunas uniones de este tipo, de las cuales la

    ms importante es:

    YYSTYPE yylval;

    que ser usada en la especificacin de lex, del mismo programa para asignarle

    valor a los tokens que yacc usara para realizar operaciones. Esta estructura puede

    llegar a ser muy compleja, y para saber de qu tipo es cada token devuelto por

    yylex(), se usan las definiciones %token y %type.

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    6

    03/06/2015

    %token y %type

    %token sirve para definir los tokens que hay, y si es necesario, el tipo de dato que

    usan, todos los tokens son tomados como smbolos terminales, lo cual veremos

    mejor reflejado en la seccin de reglas, estos tambin tienen el objetivo de servir

    como etiquetas que yylex() regresa a yacc para identificar el token que se ha ledo

    recientemente.

    Su uso es como sigue:

    %token [] ETIQUETA1 [ETIQUETA2 ... ETIQUETAn]

    Donde todo lo que esta entre [ y ] es opcional.

    : Indica el miembro al que sern mapeados los tokens en la

    union yylval dentro de lex.

    ETIQUETAS: Estos son los nombres con los que se identificaran los tokens

    mismos, que sern traducidos en C como nmeros en instrucciones #define del

    preprocesador de C.

    %type es anlogo a %token, solo que este define el tipo de dato para smbolos no

    terminales de nuestra gramtica, la nica diferencia es que el tipo de dato a usar

    es obligatorio.

    En nuestro ejemplo:

    %token NUMBER

    %token PLUS MINUS TIMES DIVIDE POWER

    %token LEFT_PARENTHESIS RIGHT_PARENTHESIS

    %token END

    %type Expression

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    7

    03/06/2015

    La primera lnea indica que el token NUMERO ser del tipo de miembro de dval,

    es decir, un double.

    Las siguientes tres lneas, son para definir algunos tokens mas que sern usados

    en la gramtica, pero no necesitan un tipo de dato ni un miembro en yylval

    asociado.

    En la ltima lnea definimos el tipo de dato que usara nuestro no terminal

    Expression.

    %left y %right

    El siguiente paso, es definir el tipo de precedencia de nuestros tokens operadores,

    en este punto tenemos dos factores, la precedencia por s misma, y la agrupacin

    de los operadores.

    Precedencia

    La precedencia es asignada en orden inverso al que aparecen, es decir, el ltimo

    operador declarado, tiene mayor precedencia que el anterior y as sucesivamente.

    Asociatividad

    %left y %right indican si el operador se agrupa a la derecha o a la izquierda, por

    ejemplo, en el caso de POWER (Exponente) debe asociarse a la derecha, por que

    buscamos que se resuelva de ese modo, de derecha a izquierda, por ejemplo:

    Buscamos que

    4^3^5^2^9

    Sea evaluado as :

    4^(3^(5^(2^9)))

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    8

    03/06/2015

    Por lo contrario, las sumas y restas queremos resolverlas de izquierda a derecha:

    Buscamos que

    4-3+5+2-9

    Sea evaluado as:

    (((4-3)+5)+2)-9

    Usar este tipo de declaraciones es importante para disminuir la posibilidad de

    ambigedades en el lenguaje generado.

    %start

    En algunos casos es conveniente indicarle a yacc cul es el smbolo (no terminal)

    inicial a la hora de hacer el paseo, es decir, el smbolo que se trata de reducir, si

    esta opcin no es especificada, yacc toma al primer smbolo de la seccin de

    reglas como smbolo inicial.

    En nuestro ejemplo, se presentan ambos casos, nuestro smbolo inicial "Input" se

    encuentra al inicio del archivo y tambin est declarado como smbolo inicial.

    %start Input

    Reglas

    En esta parte finalmente llegamos a la definicin de la gramtica, ac podemos

    observar que cada smbolo se define con su nombre, seguido de dos puntos ":"

    seguidos de varios smbolos que conformaran su composicin gramatical que en

    caso de tener varias opciones, son separados por "|" (or) indicando que se tienen

    varias opciones para reducir ese smbolo y para terminar cada regla, un ";".

    Ejemplo:

    Si tomamos la gramtica que definimos al principio de esta seccin:

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    9

    03/06/2015

    Numero + Numero - Numero

    Y la transformamos a una regla de yacc, se vera como esto:

    Expresion: NUMERO '+' Expresion {$$ = $1 + $3;} | NUMERO '-' Expresion {$$ = $1 - $3;} | NUMERO {$$ = $1;} ;

    En el ejemplo ya transformado a una regla gramatical de yacc, podemos ver que

    ya se especifica que hacer con los smbolos de la gramtica una vez que son

    resueltos en la parte de cdigo de C. En este ejemplo, Expresion es el smbolo no

    terminal que se est definiendo de manera recursiva, el valor que tomara una vez

    resuelto es el valor asignado a la variable $$, que traducida a C es una variable

    mapeada al smbolo no terminal, $1, $2 y $3 son variables que son mapeadas al

    valor de los smbolos de cada lnea de cada regla, estas son numeradas de

    izquierda a derecha.

    Ejemplo:

    En este segmento de regla:

    Expresion: NUMERO '+' Expresion

    Expresion equivale a $$ NUMERO equivale a $1 '+' equivale a $2 y

    Expresion (la parte recursiva) equivale a $3

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    10

    03/06/2015

    Todo esto claro, en la parte de acciones en C para cada lnea de la regla en yacc.

    En el ejemplo tambin podemos encontrar el uso de %prec que sirve para cambiar

    la precedencia de un operador dependiendo del contexto en el ejemplo, le

    estamos dando una ms alta precedencia a la operacin "menos" cuando est en

    un contexto unario, que a la mayora de los operadores excepto el POWER

    (exponente):

    .

    .

    .

    | MINUS Expression %prec NEG { $$=-$2; }

    .

    .

    Reduccin

    Yacc reduce sus reglas generando un parse tree (no literalmente), y va

    resolviendo cada regla completa tan pronto como puede, lo cual nos trae un

    detalle de diseo de gramticas en yacc, y es la diferencia entre especificar la

    recursividad por la derecha o por la izquierda, para expresiones muy sencillas que

    generen un parse tree pequeo no hay ningn problema pero para casos donde la

    reduccin es compleja, puede desbordar la pila ya que cuando la recursin es

    derecha, para resolverla, tiene que guardar los datos de la izquierda, y si estos

    son demasiados, no puede manejarlos.

    Por lo contrario, cuando la recursin es izquierda, no tiene que guardar datos que

    no va a utilizar por que recorre el rbol de izquierda a derecha y resuelve las

    reglas tan pronto como puede.

    En el ejemplo anterior tenemos la recursin por la derecha, un anlogo recurrente

    por la izquierda seri como este:

    Expresion: Expresion '+' NUMERO {$$ = $1 + $3;} | Expresion '-' NUMERO {$$ = $1 - $3;} | NUMERO {$$ = $1;} ;

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    11

    03/06/2015

    Especificacin de Lex para el ejemplo1.1

    Para que el Ejemplo1.1 pueda funcionar, al igual que cualquier otro programa en

    yacc, necesita un tokenizer, y a continuacin tenemos su tokenizer

    correspondiente escrito en lex.

    %{

    #include "y.tab.h"

    #include

    #include

    %}

    white [ \t]+

    digit [0-9]

    integer {digit}+

    %%

    {white} { /* Ignoramos espacios en blanco */ }

    "exit"|"quit"|"bye" {printf("Terminando programa\n");exit(0);}

    {integer} {

    yylval.dval=atof(yytext);

    return(NUMBER);

    }

    "+" return(PLUS);

    "-" return(MINUS);

    "*" return(TIMES);

    "/" return(DIVIDE);

    "^" return(POWER);

    "(" return(LEFT_PARENTHESIS);

    ")" return(RIGHT_PARENTHESIS);

    "\n" return(END);

    %%

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    12

    03/06/2015

    Acerca de la seccin de definiciones de este lexer, lo unico relevante que

    podemos mencionar es la lnea de C que dice:

    #include "y.tab.h"

    Esta lnea incluye al archivo y.tab.h que contiene algunas de las definiciones de

    yacc que lex necesita para poder interactuar con l, entre las ms importantes se

    encuentran definidas todas las etiquetas de los tokens, como PLUS, MINUS,

    NUMBER, etctera. Estas constantes son los valores que yylex() regresara a

    yyparse() (la funcin del parser de yacc) para identificar el tipo de token que recin

    se ha ledo.

    En la seccin de reglas, en la parte del cdigo, podemos ver como al final de cada

    regla, se hace un return especificando la etiqueta que fue declarada como %token

    o cmo %left/%rigth en la especificacin yacc.

    Para compilar y correr este ejemplo en sistemas UNIX o similares:

    $ lex ejem1.1.l

    $ yacc -d ejem1.1.y

    $ cc -o ejem1.1 lex.yy.c y.tab.c -ly -ll -lm

    $ ejem1.1

    25*5-5

    Result: 120.000000

    5^2*2

    Result: 50.000000

    5^(2*2)

    Result: 625.000000

    bye

    Terminando programa

    $

    Subrutinas

    En esta ltima seccin, es posible re implementar, siguiendo la misma idea de lex,

    algunas funciones que pueden ser tiles en algn momento dado o declarar

    nuevas funciones para usar dentro de nuestro cdigo o nuestras reglas, no hay

    mucho que reimplementat a este nivel (yacc) a menos que sea con propsitos

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    13

    03/06/2015

    realmente especficos. Las funciones ms comnmente implementadas son main()

    e yyerror(), la primera se usa para personalizar el programa con mensajes antes o

    despus del parser, o para llamarlo varias veces en el cdigo y la segunda la

    ocupa yyparse() cada vez que encuentra un error de sintaxis, en este ejemplo, se

    incluyen ambas con su contenido mnimo.

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    14

    03/06/2015

    GENERADOR DE ANALIZADOR SINTCTICO JAVACC

    JavaCC (Java Compiler Compiler) es un generador de analizadores sintcticos de

    cdigo abierto para el lenguaje de programacin Java. JavaCC es similar a Yacc

    en que genera un parser para una gramtica presentada en notacin BNF, con la

    diferencia de que la salida es en cdigo Java. A diferencia de Yacc, JavaCC

    genera analizadores descendentes (top-down), lo que lo limita a la clase de

    gramticas LL(K) (en particular, la recursin desde izquierda no se puede usar). El

    constructor de rboles que lo acompaa, JJTree, construye rboles de abajo hacia

    arriba (bottom-up).

    JavaCC est licenciado bajo una licencia BSD.

    En 1996, Sun Microsystems liber un parser llamado Jack. Los desarrolladores

    responsables de Jack crearon su propia compaa llamada Metamata y cambiaron

    el nombre Jack a JavaCC. Metamata se convirti en WebGain. Despus de

    queWebGain finalizara sus operaciones, JavaCC se traslad a su ubicacin

    actual.

    JavaCC integra las funciones de anlisis lxico y anlisis sintctico en una sola

    herramienta, obteniendo a la salida cdigo java a diferencia de lex/yacc cuya

    salida es cdigo C-.

    Antes que nada veamos un ejemplo sobre el cual se va a ir haciendo un

    seguimiento de cada uno de los distintos puntos que vayamos comentando. En l

    se muestra una gramtica reconocedora de una calculadora. Ms adelante, en

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    15

    03/06/2015

    este mismo captulo, lo modificaremos con el objetivo de mostrar mayores

    funcionalidades que aporta JavaCC.

    La principal diferencia con lex/yacc es que los analizadores sintcticos generados

    por JavaCC son analizadores sintcticos descendentes de tipo LL(k), mientras

    que los analizadores sintcticos generados por yacc son de tipo ascendente

    LALR. Otra diferencia bastante importante es que las especificaciones lxicas

    pueden estar incluidas dentro de la especificacin de la gramtica. Por ejemplo,

    podemos escribir algo como esto:

    sentenciaIf : {} { "if" "(" expresion() ")" sentencia() } .

    y automticamente se ocupa de generar tokens para if y para (.

    Tambin es necesario resear que el anlisis lxico en JavaCC genera

    combinaciones de autmatas finitos deterministas (AFD) y autmatas finitos no

    deterministas (AFND); por contra, lex siempre genera autmatas finitos

    deterministas.

    ESTRUCTURA GENERAL DE UN PROGRAMA EN JAVACC

    El fichero de entrada comienza con una lista de opciones, la cual es opcional.

    Seguidamente nos encontramos la unidad de compilacin java la cual se

    encuentra encerrada entre PARSER_BEGIN(nombre) y PARSER_END(nombre).

    Despus nos encontramos con una lista de reglas de produccin (cada una de

    estas partes son claramente distinguibles en el ejemplo 2.1.).

    El nombre que sigue a PARSER_BEGIN y a PARSER_END debe ser el mismo, y

    ste identifica al analizador sintctico que va a ser generado con posterioridad.

    Por ejemplo si nuestro nombre es Gramtica, se generan los siguientes archivos:

    Gramatica.java: El analizador sintctico.

    GramaticaTokenManager.java: gestor de tokens para el analizador lxico.

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    16

    03/06/2015

    GramaticaConstants.java: El analizador lxico no maneja los tokens por el

    Opciones_javacc

    PARSER_BEGIN ()

    Unidad de compilacin java

    PARSER_END ()

    (reglas de produccion)*

    Nombre que especificamos nosotros en el cdigo, sino que a cada uno de ellos le

    asigna un nmero. En este archivo se encuentra cada uno de los tokens junto con

    el nmero que le ha sido asignado por el analizador lxico.

    OPCIONES

    1

    La seccin options, si est presente, comienza con la palabra reservada options

    seguida de una lista de una o ms opciones entre llaves. La misma opcin no

    debe establecerse ms de una vez. En el ejemplo 2.1. Slo se ha usado una de

    las opciones

    (

    LOOKAHEAD=1).

    Las opciones pueden ser especificadas tanto en el archivo de la gramtica como

    en la lnea de comandos. En caso de estar presentes en el archivo, stas deben

    aparecer al principio precedidas por la palabra options. Y en el caso en que se

    especifiquen en la lnea de comandos, stas tienen mayor prioridad que las

    especificadas en el cdigo.

    opciones::= [ options { (valores_de_las_opciones)* }]

    Los nombres de las opciones van en maysculas.

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    17

    03/06/2015

    A continuacin se detallan brevemente las opciones ms importantes y las

    funciones que realizan:

    LOOKAHEAD: Indica la cantidad de tokens que son tenidos en cuenta por

    el parser antes de tomar una decisin de parsing. El valor por defecto es 1,

    con lo cual se trabaja con parser LL(1), aunque el nmero puede variar para

    alguna/s produccin/es en particular. Cuanto ms pequeo sea el nmero

    de tokens del lookahead, ms veloz ser el parser.

    Valor por defecto: 1

    CHOICE_AMBIGUITY_CHECK: Es el nmero de tokens que se consideran

    en las elecciones de chequeo por ambigedad, de la forma "A | B | ...". Por

    ejemplo: si existen dos tokens prefijos comunes para A y B, pero no tres;

    entonces por medio de esta opcin, JavaCC permite usar un lookahead de

    3 con propsitos de desambiguacin. La utilizacin de esta opcin provee

    mayor informacin y flexibilidad ante las ambigedades, pero a costo de un

    mayor tiempo de procesamiento.

    Valor por defecto: 2

    STATIC: Si el valor es true, todos los mtodos y clases variables se

    especifican como estticas en el parser generado y en el token manager.

    Esto permite la presencia de un nico objeto parser, pero mejora la

    actuacin del procedimiento de parsing. Para ejecutar mltiples parsers

    durante la ejecucin de un programa Java, debe invocarse el mtodo

    ReInit() para reinicializar el parser, si es que haba sido definido como

    esttico. Si el parser no es esttico, puede utilizarse el operador "new" para

    construir los parsers que sean necesarios; los mismos, podran ser usados

    simultneamente en threads diferentes.

    Valor por defecto: true

    DEBUG_PARSER: Esta opcin se utiliza para obtener informacin de

    debugging desde el parser generado. Si el valor de la opcin es true, el

    parser genera un trace de sus acciones. Dichos traces pueden

    deshabilitarse por medio de la invocacin del mtodo disable_tracing() en la

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    18

    03/06/2015

    clase del parser generado, y, recprocamente, pueden habilitarse con el

    mtodo enable_tracing().

    Valor por defecto: false

    IGNORE_CASE: Si su valor es true, el token manager generado no efecta

    diferencia entre letras maysculas y minsculas en las especificaciones de

    tokens y los archivos de entrada. Es muy usado para escribir gramticas

    para lenguajes como HTML.

    Valor por defecto: false.

    FORCE_LA_CHECK: Esta opcin determina los controles de chequeo de

    ambigedad de lookahead ejecutados por JavaCC. Cuando el valor es

    false, el chequeo de ambigedad del lookahead se ejecuta para todos los

    puntos de eleccin donde se usa el lookahead de 1 por defecto. El chequeo

    de ambigedad de lookahead no se ejecuta en los puntos donde existe una

    especificacin explcita de lookahead, o si la opcin LOOKAHEAD tiene un

    valor distinto de 1.

    Valor por defecto: false.

    COMMON_TOKEN_ACTION: Si el valor de esta opcin es true, todas las

    invocaciones del mtodo "getNextToken()" del token manager, causan una

    llamada al mtodo definido "CommonTokenAction()" despus de que el

    token haya sido ledo por el token manager. El usuario debe definir este

    mtodo en la seccin TOKEN_MGR_DECLS. La signatura de este mtodo

    es:

    Valor por defecto: false.

    OUTPUT_DIRECTORY: Es una opcin cuyo valor por defecto es el void

    CommonTokenAction(Token t) directorio actual. Controla dnde son

    generados los archivos de salida.

    Valor por defecto: directorio actual.

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    19

    03/06/2015

    REGLAS DE PRODUCCIN

    Existen cuatro tipos de reglas de produccin en JavaCC: las reglas de produccin

    javacode y BNF se usan para definir la gramtica a partir de la cual va a generarse

    el analizador sintctico. Las Reglas de produccin mediante expresiones

    regulares, se usan para definir los tokens de la gramtica el token manager es

    generado a partir de esta informacin-. La seccin token manager decls se usa

    para introducir declaraciones en el analizador sintctico que se generar con

    posterioridad.

    Reglas de produccin Javacode

    Las reglas de produccin JAVACODE son una forma de escribir cdigo Java para

    una regla de produccin en lugar de las tpicas expansiones EBNF. Esto suele ser

    til cuando tenemos la necesidad de reconocer algo que no es de contexto libre o

    algo para lo cual es difcil escribir una gramtica que lo reconozca. Para ello nos

    serviremos de los mtodos que el propio parser nos proporciona con tal fin, a

    saber:

    getToken(),

    jj_concume_token(), getNextToken(),etc. A continuacin se muestra un ejemplo de

    uso de JAVACODE. En el ejemplo 2.3., el no terminal skipToMatchingBrace

    consume tokens de la entrada hasta que encuentra una }.

    JAVACODE

    void skipToMatchingBrace(){

    Token tok;

    int nesting=1;

    while(true){

    tok=getToken(1);

    if(tok.kind==LBRACE)

    nesting++;

    if(tok.kind==RBRACE){

    nesting--;

    if(nesting==0)

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    20

    03/06/2015

    break;

    }

    tok=getNextToken();

    }

    }

    Cuando usamos este tipo de reglas de produccin tenemos que tener muchsimo

    cuidado ya que es muy fcil especificar bastante ms de lo que realmente se

    quiere.

    Este tipo de reglas son problemticas cuando las utilizamos en lugares donde el

    analizador sintctico tiene que hacer una eleccin. Supongamos que la regla de

    produccin anterior es referenciada desde sta:

    Reglas de produccin BNF

    Las reglas de produccin BNF son la forma estndar de especificar gramticas en

    JavaCC. Sobre ella diferenciaremos cada uno de los puntos que a continuacin se

    exponen:

    void unario() :

    { }

    {

    }

    elemento()

    | elemento()

    Cada regla de produccin BNF consta de una parte izquierda la cual consiste en la

    especificacin de un no terminal. Las reglas de produccin BNF definen este no

    terminal en funcin de expansiones BNF que se encuentran en la parte derecha.

    El no terminal se escribe exactamente de la misma forma en que se declara un

    mtodo en

    Java, (en el ejemplo 2.6. void unario():) . Ya que cada no terminal se traduce a

    un mtodo en el analizador sintctico, la forma de escribir el no terminal hace que

    esta asociacin sea obvia. El nombre del no terminal es el nombre del mtodo, y

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    21

    03/06/2015

    los parmetros y el valor de retorno son los medios para pasar valores arriba y

    abajo dentro del rbol sintctico. parse tree- (Esto se mostrar ms adelante).

    La parte derecha de una regla de produccin BNF tiene dos partes: La primera

    parte es un conjunto de declaraciones y cdigo Java ( bloque Java). Este cdigo

    es generado al principio del mtodo relacionado con el no terminal. Por lo tanto,

    cada vez que el no terminal es usado en el proceso de anlisis, este cdigo es

    ejecutado.

    La segunda parte est formada por las expansiones BNF.

    bnf_production::= java_return_type java_identifier ( java_parameter_list ) :

    java_block

    { expansion_choices }

    Reglas de produccin mediante expresiones regulares

    Las expresiones regulares se usan para definir entidades lxicas las cuales van a

    ser procesadas por el token manager. Una regla de produccin de este tipo

    comienza con la especificacin de los estados lxicos a los cuales es aplicable.

    regular_expr_production::= [lista_de_estados_lexicos]

    regexpr_kind[ [ IGNORE CASE ] ] :

    { regexpr_spec ( | regexpr_spec )* }

    Existe un estado lxico estndar llamado DEFAULT. Si la lista de estados lxicos

    se omite, la expresin regular se aplica al estado DEFAULT.

    lista_de_estados_lexicos::=

    |

    La lista de estados lxicos describe el conjunto de estados lxicos, para los cuales

    la expresin regular es aplicable. Si sta es , entonces la expresin

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    22

    03/06/2015

    regular se puede aplicar a todos los estados lxicos. En otro caso se aplicar a

    todos los estados lxicos cuyo identificador se encuentre en la lista de

    identificadores del interior de los parntesis angulares.

    A continuacin se especifica el tipo de regla de produccin. Existen cuatro tipos

    basadas en expresiones regulares:

    o TOKEN: La expresin regular de esta regla de produccin describe tokens

    de la gramtica. El token manager crea un objeto de tipo Token para cada

    una de las entradas que se ajusten a dicha expresin regular, y luego lo

    retorna al analizador sintctico.

    o SPECIAL_TOKEN: La expresin regular de esta regla de produccin

    describe tokens especiales. Los tokens especiales son iguales que los

    tokens slo que no tienen importancia durante el anlisis sintctico. Son

    muy tiles cuando hay que procesar entidades lxicas, del tipo de

    comentarios, las cuales no tienen ninguna importancia para el anlisis

    sintctico, pero son una parte muy importante del fichero de entrada.

    o SKIP: Cualquier entrada que se ajuste a la expresin regular especificada

    en esta seccin ser ignorada por el token manager.

    o MORE: A veces es necesario ir construyendo el token que vamos a pasar al

    analizador sintctico de forma gradual. Las entradas que se ajustan a la

    expresin regular son guardadas en un buffer hasta que llega el siguiente

    o TOKEN o SPECIAL_TOKEN. Despus todos los valores almacenados en el

    buffer son concatenados para formar un solo TOKEN o SPECIAL_TOKEN y

    es entonces cuando se enva al analizador sintctico. En el caso en que

    una entrada encajara con una expresin regular especificada en la seccin

    SKIP, el contenido del buffer es desechado.

    VERSIONES:

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    23

    03/06/2015

    Title + Description + Tags

    Updated

    Date

    Size Actions

    beta Beta / Nightly Versions Tags: beta nightly javacc

    about 1 year ago

    contrib Contributions, including grammars Tags: --

    over 4 years ago

    oldversions Older versions of JavaCC Tags: --

    over 4 years ago

    releases JavaCC releases Tags: --

    almost 2 years ago

    javacc-5.0.tar.gz javacc-5.0.tar.gz Tags: --

    over 4 years ago 461.6 KB

    javacc-5.0.zip javacc-5.0.zip Tags: --

    over 4 years ago 627.3 KB

    javacc-5.0src.tar.gz javacc-5.0src.tar.gz Tags: --

    over 4 years ago 791.1 KB

    javacc-5.0src.zip javacc-5.0src.zip Tags: --

    over 4 years ago 1.1 MB

    javacc-6.0.zip This is the binary distribution of JavaCC 6.0.1 - with few bug fixes. Tags: javacc 6.0 c++ code parser lexer 6.0.1

    about 1 year ago 726.7 KB

    JavacCC-6.0src.zip JavaCC 6.0 source distribution Tags: javacc c++ parser lexer genertor

    about 1 year ago 1.2 MB

  • Jose Alfredo Jimenez Cornejo Romeo H. Vazquez Velazquez

    24

    03/06/2015

    Conclusin

    Como hemos visto un generador de analizadores sintcticos es un programa que

    toma como su entrada una especificacin de la sintaxis de un lenguaje en alguna

    forma, y produce como su salida un procedimiento de anlisis sintctico para ese

    lenguaje, tambin sabemos ahora que un generador de analizadores sintcticos

    ampliamente utilizado que incorpora el algoritmo de anlisis sintctico LR(1) se

    conoce como Yacc, este no es directamente un analizador sino un generador de

    analizadores. A partir de un fichero fuente en yacc, se genera un fichero fuente en

    C que contiene el analizador sintctico.

    Por otra parte el generador de analizadores sintcticos JavaCC integra las

    funciones de anlisis lxico y anlisis sintctico en una sola herramienta,

    obteniendo a la salida cdigo java a diferencia de lex/yacc cuya salida es cdigo

    C.

    La principal diferencia con lex/yacc es que los analizadores sintcticos generados

    por JavaCC son analizadores sintcticos descendentes de tipo LL(k), mientras que

    los analizadores sintcticos generados por yacc son de tipo ascendente LALR.

    Otra diferencia bastante importante es que las especificaciones lxicas pueden

    estar incluidas dentro de la especificacin de la gramtica.

    De manera general JavaCC es similar a Yacc en que genera un parser para una

    gramtica presentada en notacin BNF, con la diferencia de que la salida es en

    cdigo Java. A diferencia de Yacc, JavaCC genera analizadores descendentes

    (top-down), lo que lo limita a la clase de gramticas LL(K) (en particular, la

    recursin desde izquierda no se puede usar).

    Otra diferencia bastante importante es que las especificaciones lxicas pueden

    estar incluidas dentro de la especificacin de la gramtica.

    JavaCC es quiz el generador de parsers usado con aplicaciones Java ms

    popular.

    Referencias: http://www.lcc.uma.es/~galvez/theme/IntroduccionAJavaCC.pdf http://www.udb.edu.sv/udb/archivo/guia/informatica-ingenieria/compiladores/2014/ii/guia-5.pdf http://es.wikipedia.org/wiki/JavaCC http://es.wikipedia.org/wiki/Yacc