JAVACC pegar a mensagem de erro e continuar analisando o arquivo

8 respostas
L

Boa tarde pessoal preciso da preciosa ajuda de v6, estou fazendo um anlisador lexico e sintatico com javacc eu gostaria de saber como eu faço para ele varre meu arquivo com o codigo e ele falar onde esta o erro e falar qual é o erro e continuar a analise do arquivo mesmo encontrado o erro no meio do caminho

Obrigado galera

8 Respostas

davidbuzatto

Hummm vc precisa mesmo usar o javacc?
Não pode usar o antlr?

Se puder, posso te ajudar.

[]´s

L

e como seria com essa ferramenta???

davidbuzatto

Basicamente o ANTLR é um gerador de analizadores léxicos e sintáticos como o javacc.
www.antlr.org

[]´s

E

lecfribeiro:
Boa tarde pessoal preciso da preciosa ajuda de v6, estou fazendo um anlisador lexico e sintatico com javacc eu gostaria de saber como eu faço para ele varre meu arquivo com o codigo e ele falar onde esta o erro e falar qual é o erro e continuar a analise do arquivo mesmo encontrado o erro no meio do caminho

Obrigado galera

A arte de criar compiladores de modo que eles não parem no primeiro erro é muito complexa; consulte seu livro de teoria de compiladores para ver que isso não é nem um pouco fácil. De modo geral:

a) Você deve remodelar sua gramática de modo que ela aceite alguns erros bem comuns (e isso depende, é claro, da linguagem). Por exemplo, se for escrever um compilador para uma antiga versão do Pascal (onde você não pode pôr um “;” antes da palavra-chave END) então você pode escrever a gramática de modo que ela aceite esse “;”, mas que emita um aviso em vez de simplesmente parar a análise. Como se vê, isso é excessivamente trabalhoso.
b) Você deve ler a documentação do seu compilador de compiladores (pode ser o JavaCC, ou o AntLR, ou sei lá qual ferramenta você for usar) para ver que tipo de técnica deve-se usar no caso de encontrar um erro que você não previu, e que tipo de estratégia você deve adotar. Para cada compilador de compiladores a estratégia é bem diferente, e normalmente é bem complexa. Leia a documentação até formarem-se bolhas nas suas mãos

Conselho: deixe isso para depois. As primeiras versões do Turbo Pascal simplesmente paravam no primeiro erro, e isso era mais que suficiente para esse compilador (um dos primeiros que rodava muito bem no IBM-PC, de saudosa memória.)

C

É realmente necessário que vc continue procurando por erros léxicos e sintáticos após o primeiro erro encontrado?
Se vc estivesse falando sobre erros semânticos, dai vc estaria coberto de razão, mas erros sintáticos eu acho que não valerá o esforço.

davidbuzatto

O analisador sintático gerado pelo ANTLR verifica o código inteiro e gera código de recuperação.

No exemplo no final da minha postagem, que é uma gramática que reconhece expressões matemáticas e as calcula, eu quis que ao ocorrer algum erro (RecognitionException), a excessão fosse passada para baixo na pilha, sendo propagada até que seja tratada por quem chamar o método expressao, que corresponde ao não terminal inicial da gramática e por consequência é a base da pilha de chamadas para o analisador sintático. Quando você não fornece a cláusula catch da produção, o seguinte código é gerado no analisador sintático:

catch (RecognitionException re) {
    reportError(re); // imprime o erro na saída de erro
    recover(input,re); // recupera do erro para continuar a análise sintática
}
Caso o catch da produção seja fornecido, o código gerado dentro do catch do analisador sintático é o mesmo que está entre chaves, no meu caso um "throw exc;" Segue a gramática do ANTLR 3.x.
grammar Expressoes;

/* 
 * Estrutura:
 * E : M ( '+' M | '-' M )*;
 */
expressao returns [ double v ]

        :    e=multExpr { $v = $e.v; } ( 
                 '+' e=multExpr { $v += $e.v; } 
               | '-' e=multExpr { $v -= $e.v; }  
             )*
        ;
        catch [RecognitionException exc] { throw exc; }

/* 
 * Estrutura:
 * M : A ( '*' A | '/' A | '^' A )*;
 */                     
multExpr returns [ double v ]

        :    e=atom { $v = $e.v; } ( 
                 '*' e=atom { $v *= $e.v; } 
               | '/' e=atom { $v /= $e.v; } 
               | '^' e=atom { $v = Math.pow( $v, $e.v ); }
             )*
        ;
        catch [RecognitionException exc] { throw exc; }

atom returns [ double v ]

        :    NUMERO {
                $v = Double.parseDouble( $NUMERO.text );
             }
        |    '(' expressao ')' {
                 $v = $expressao.v;
             }
        ;
        catch [RecognitionException exc] { throw exc; }



NUMERO    :    ('0'..'9')+ '.' ('0'..'9')*
          |    '.' ('0'..'9')+ 
          |    ('0'..'9')+ 
          ;
          
WS        :    ( ' ' | '\t' | '\r' | '\n' ) {$channel=HIDDEN;};
RafaFloripa

cara
tem q mexer no codigo gerado
eh bem complicado, pq toda vez q tu gera sobresescreve
ele eh um pouco amarrado nesse ponto

mas eh possivel

davidbuzatto

Mexer em código gerado? Quem falou isso?
Até onde eu sei, da mesma forma que o ANTLR o JavaCC tbm deixa escrever ações baseadas no reconhecimento de terminais e não terminais.
Não sei na parte de tratamento de erros.

Criado 6 de novembro de 2010
Ultima resposta 10 de nov. de 2010
Respostas 8
Participantes 5