JavaCC  Java Compiler Compiler Paradigmas de Linguagens de Programação Adeline de Sousa Silva - adss@cin.ufpe.br
Definições preliminares: Parser Um  parser  é um programa que recebe como entrada um  arquivo fonte  e diz se ele está correto sintaticamente, segundo uma gramática pré-definida. Há parsers bottom-up e top-down Definir um parser ‘na mão’ pode ser uma tarefa muito trabalhosa.
Definições Preliminares: Gerador de  parser Um  gerador de parser  é um programa que recebe como entrada um arquivo de  especificação da gramática  a ser aceita pelo parser (o formato deste arquivo depende do gerador) e retorna um  parser  que reconhece esta gramática.  O formato do arquivo de especificação da gramática depende  muito  do tipo de parser gerado (top-down ou bottom-up)
Geradores de Parsers em Java Nesta aula, iremos abordar o JavaCC, mas existem outros geradores de parser SableCC JLex & Cup O JavaCC  é um dos mais populares na comunidade Java, sendo suportado hoje pela comunidade java.net
JavaCC
JavaCC Gerador de parser 100% Java, o mais utilizado pela comunidade Java. Desenvolvido inicialmente pela Sun, já passou por vários outros desenvolvedores e hoje é mantido pela java.net É um parser top-down Mais fácil de depurar Utiliza uma sintaxe muito próxima de Java Não checa a corretude do código Java inserido. Pode gerar classes que não compilam.
JavaCC Inclui um pré-processador para geração de árvores sintáticas (jjTree) Possui um repositório de gramáticas bastante extenso disponível – inclui linguagens como Java, C, C++, Perl, etc Possui uma interface gráfica fácil de usar Definições léxicas e sintáticas em um único arquivo Não aceita ambigüidades.  Ex: A gramática não pode possuir recursão à esquerda .(ex: expr:= expr ‘+’ expr)
Gramáticas em JavaCC Uma gramática JavaCC possui a seguinte estrutura: Opções do Parser (Não obrigatório) Definição da classe do Parser Definição dos Tokens (Componente Léxico) Terminais Definição das Produções (Componente Sintático) Ações semânticas associadas Não-Terminais
Opções do parser STATIC – diz se os métodos do parser serão estáticos (default: true) LOOKAHEAD – informa o nível de profundidade do lookahead (default: 1) DEBUG_PARSER – instrui o parser a registrar todas as informações durante o parsing do arquivo (default: false) DEBUG_LOOKAHEAD – instrui o parser a registrar também as tentativas de lookahead (default: false)
Mais opções UNICODE_INPUT – informa se a entrada usa a codificaçõo UNICODE  OUTPUT_DIRECTORY – seta o diretório onde os arquivos java serão gerados (o default é o atual) FORCE_LA_CHECK- força a checagem do lookahead em todos os “choice points”, independente da  especificação explícita do lookahead (default: false)
Definição da classe do Parser Este trecho define a classe do Parser. Nesta classe, podem ser definidos métodos e variáveis auxiliares. O formato é o seguinte: PARSER_BEGIN(parser_name)  ... class parser_name ...{  ...  }  ...  PARSER_END(parser_name)
Definição dos tokens Serve para especificar os tipos de tokens e as expressões regulares associadas Nes t a seção são descritas as palavras reservadas TOKEN:  {  < NUMBER: (<DIGIT>)+ ( &quot;.&quot; (<DIGIT>)+ )? >  | < DIGIT: [&quot;0&quot;-&quot;9&quot;] >  | < EOL: &quot;\n&quot; >  }
Definição das produções Obedecem o seguinte formato: tipoRetorno nomeProducao(listaParametros): { código Java } { subProducao1()  { ação semântica correspondente } [lista de subProducoes] } Declaração de variáveis, invocação de métodos, etc Código Java. Em geral, corresponde a montagem da árvore
Exemplo: EBNF Dada a gramática na forma EBNF expr := number        | expr '+' expr        | expr '-' expr        | expr '*' expr        | expr '/' expr        | - expr  number := digit+ ('.' digit+)?  digit := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'  A gramática do JavaCC que o representa é a seguinte (Lembre-se de que o JavaCC não permite recursão à esquerda, por isso, é necessário modificar a gramática antes de traduzí-la ):
Exemplo: JavaCC options  {      LOOKAHEAD=2;  STATIC=false;  } PARSER_BEGIN(Arithmetic)   public class Arithmetic    {    } PARSER_END(Arithmetic)
Exemplo:JavaCC SKIP :  {    &quot; &quot;  | &quot;\r&quot;  | &quot;\t&quot;  }  TOKEN:  {   < NUMBER: (<DIGIT>)+ ( &quot;.&quot; (<DIGIT>)+ )? > | < DIGIT: [&quot;0&quot;-&quot;9&quot;] >  }
Exemplo:JavaCC double expr(): {}  {      term() ( &quot;+&quot; expr() | &quot;-&quot; expr() )*  }  double term(): {}  {      unary() ( &quot;*&quot; term() | &quot;/&quot; term() )*  }
Exemplo:JavaCC double unary(): { }  {  &quot;-&quot; a=element() |  a = element() }  double element(): {}  {  <NUMBER> }
Exercício Altere o exemplos dados para que estes possam reconhecer as seguintes expressões: parênteses “(“ , “)” ->  expr ::= (expr) exponenciação -> expr ::= expr ^ expr Onde a ordem de precedência é: parênteses > exponenciação

JavaCC

  • 1.
    JavaCC JavaCompiler Compiler Paradigmas de Linguagens de Programação Adeline de Sousa Silva - adss@cin.ufpe.br
  • 2.
    Definições preliminares: ParserUm parser é um programa que recebe como entrada um arquivo fonte e diz se ele está correto sintaticamente, segundo uma gramática pré-definida. Há parsers bottom-up e top-down Definir um parser ‘na mão’ pode ser uma tarefa muito trabalhosa.
  • 3.
    Definições Preliminares: Geradorde parser Um gerador de parser é um programa que recebe como entrada um arquivo de especificação da gramática a ser aceita pelo parser (o formato deste arquivo depende do gerador) e retorna um parser que reconhece esta gramática. O formato do arquivo de especificação da gramática depende muito do tipo de parser gerado (top-down ou bottom-up)
  • 4.
    Geradores de Parsersem Java Nesta aula, iremos abordar o JavaCC, mas existem outros geradores de parser SableCC JLex & Cup O JavaCC é um dos mais populares na comunidade Java, sendo suportado hoje pela comunidade java.net
  • 5.
  • 6.
    JavaCC Gerador deparser 100% Java, o mais utilizado pela comunidade Java. Desenvolvido inicialmente pela Sun, já passou por vários outros desenvolvedores e hoje é mantido pela java.net É um parser top-down Mais fácil de depurar Utiliza uma sintaxe muito próxima de Java Não checa a corretude do código Java inserido. Pode gerar classes que não compilam.
  • 7.
    JavaCC Inclui umpré-processador para geração de árvores sintáticas (jjTree) Possui um repositório de gramáticas bastante extenso disponível – inclui linguagens como Java, C, C++, Perl, etc Possui uma interface gráfica fácil de usar Definições léxicas e sintáticas em um único arquivo Não aceita ambigüidades. Ex: A gramática não pode possuir recursão à esquerda .(ex: expr:= expr ‘+’ expr)
  • 8.
    Gramáticas em JavaCCUma gramática JavaCC possui a seguinte estrutura: Opções do Parser (Não obrigatório) Definição da classe do Parser Definição dos Tokens (Componente Léxico) Terminais Definição das Produções (Componente Sintático) Ações semânticas associadas Não-Terminais
  • 9.
    Opções do parserSTATIC – diz se os métodos do parser serão estáticos (default: true) LOOKAHEAD – informa o nível de profundidade do lookahead (default: 1) DEBUG_PARSER – instrui o parser a registrar todas as informações durante o parsing do arquivo (default: false) DEBUG_LOOKAHEAD – instrui o parser a registrar também as tentativas de lookahead (default: false)
  • 10.
    Mais opções UNICODE_INPUT– informa se a entrada usa a codificaçõo UNICODE OUTPUT_DIRECTORY – seta o diretório onde os arquivos java serão gerados (o default é o atual) FORCE_LA_CHECK- força a checagem do lookahead em todos os “choice points”, independente da especificação explícita do lookahead (default: false)
  • 11.
    Definição da classedo Parser Este trecho define a classe do Parser. Nesta classe, podem ser definidos métodos e variáveis auxiliares. O formato é o seguinte: PARSER_BEGIN(parser_name) ... class parser_name ...{ ... } ... PARSER_END(parser_name)
  • 12.
    Definição dos tokensServe para especificar os tipos de tokens e as expressões regulares associadas Nes t a seção são descritas as palavras reservadas TOKEN: { < NUMBER: (<DIGIT>)+ ( &quot;.&quot; (<DIGIT>)+ )? > | < DIGIT: [&quot;0&quot;-&quot;9&quot;] > | < EOL: &quot;\n&quot; > }
  • 13.
    Definição das produçõesObedecem o seguinte formato: tipoRetorno nomeProducao(listaParametros): { código Java } { subProducao1() { ação semântica correspondente } [lista de subProducoes] } Declaração de variáveis, invocação de métodos, etc Código Java. Em geral, corresponde a montagem da árvore
  • 14.
    Exemplo: EBNF Dadaa gramática na forma EBNF expr := number       | expr '+' expr       | expr '-' expr       | expr '*' expr       | expr '/' expr       | - expr number := digit+ ('.' digit+)? digit := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' A gramática do JavaCC que o representa é a seguinte (Lembre-se de que o JavaCC não permite recursão à esquerda, por isso, é necessário modificar a gramática antes de traduzí-la ):
  • 15.
    Exemplo: JavaCC options {     LOOKAHEAD=2; STATIC=false; } PARSER_BEGIN(Arithmetic) public class Arithmetic { } PARSER_END(Arithmetic)
  • 16.
    Exemplo:JavaCC SKIP : {   &quot; &quot; | &quot;\r&quot; | &quot;\t&quot; } TOKEN: {  < NUMBER: (<DIGIT>)+ ( &quot;.&quot; (<DIGIT>)+ )? > | < DIGIT: [&quot;0&quot;-&quot;9&quot;] > }
  • 17.
    Exemplo:JavaCC double expr():{} {     term() ( &quot;+&quot; expr() | &quot;-&quot; expr() )* } double term(): {} {     unary() ( &quot;*&quot; term() | &quot;/&quot; term() )* }
  • 18.
    Exemplo:JavaCC double unary():{ } { &quot;-&quot; a=element() | a = element() } double element(): {} { <NUMBER> }
  • 19.
    Exercício Altere oexemplos dados para que estes possam reconhecer as seguintes expressões: parênteses “(“ , “)” -> expr ::= (expr) exponenciação -> expr ::= expr ^ expr Onde a ordem de precedência é: parênteses > exponenciação