Como construir um compilador utilizandoferramentas Java
Aula 8 – Recuperação de Erros Sintáticos
Prof. Marcio [email protected]
Como construir um compilador utilizando ferramentas Java – p. 1/22
O que temos até agora
A.S. lê entrada.
Se entrada estiver de acordo com a gramática,execução termina OK.
Se existir algum erro sintático, uma execeção é lançada.
ParseException é tratada no método main.
Uma mensagem de erro é dada.
Como construir um compilador utilizando ferramentas Java – p. 2/22
Tratamento da exceçãotry {
parser.program();
}
catch (ParseException e)
{
System.err.println(e.getMessage());
parser.contParseError = 1;
}
finally {
System.out.println(parser.token_source.foundLexError() +
" Lexical Errors found");
System.out.println(parser.contParseError +
" Syntactic Errors found");
}
Como construir um compilador utilizando ferramentas Java – p. 3/22
A saída é...X++ Compiler - Version 1.0 - 2004
Reading from file bintree-erro-sintatico.x . . .
Encountered "mes" at line 21, column 4.
Was expecting one of:
"[" ...
";" ...
"." ...
">" ...
"<" ...
"==" ...
"<=" ...
">=" ...
"!=" ...
0 Lexical Errors found
1 Syntactic Errors found
Como construir um compilador utilizando ferramentas Java – p. 4/22
Recuperação de errosEncountered "mes" at line 21, column 4.
Was expecting one of:
"[" ...
";" ...
"." ...
">" ...
"<" ...
"==" ...
"<=" ...
">=" ...
"!=" ...
Encountered "<" at line 27, column 14.
Was expecting one of:
<int_constant> ...
<string_constant> ...
"null" ...
<IDENT> ...
"(" ...
"+" ...
"-" ...
Como construir um compilador utilizando ferramentas Java – p. 5/22
Recuperação de errosEncountered "right" at line 43, column 14.
Was expecting one of:
"(" ...
"[" ...
"," ...
";" ...
Encountered "1" at line 69, column 14.
Was expecting one of:
"[" ...
"." ...
"=" ...
<IDENT> ...
0 Lexical Errors found
4 Syntactic Errors found
Como construir um compilador utilizando ferramentas Java – p. 6/22
Método de resincronização (do pânico)S → aAcd
A → gh
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Método S não deve ser afetado por esse erro sintático.
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Método S não deve ser afetado por esse erro sintático.
O método A deve ressincronizar a entrada com onão-terminal que se espera reconhecer (S).
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Método S não deve ser afetado por esse erro sintático.
O método A deve ressincronizar a entrada com onão-terminal que se espera reconhecer (S).
Consumir tokens até que apareça algum que possibilitea continuidade da análise.
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Método S não deve ser afetado por esse erro sintático.
O método A deve ressincronizar a entrada com onão-terminal que se espera reconhecer (S).
Consumir tokens até que apareça algum que possibilitea continuidade da análise.
Método A precisa saber até onde ler.
Como construir um compilador utilizando ferramentas Java – p. 7/22
Método de resincronização (do pânico)S → aAcd
A → gh
Analisar: agabcd
Método S não deve ser afetado por esse erro sintático.
O método A deve ressincronizar a entrada com onão-terminal que se espera reconhecer (S).
Consumir tokens até que apareça algum que possibilitea continuidade da análise.
Método A precisa saber até onde ler.
Usar FOLLOW de A.
Como construir um compilador utilizando ferramentas Java – p. 7/22
Um pouco melhor
S → aAcd | bAef
A → gh
Como construir um compilador utilizando ferramentas Java – p. 8/22
Um pouco melhor
S → aAcd | bAef
A → gh
FOLLOW(A) = {c, e}
Como construir um compilador utilizando ferramentas Java – p. 8/22
Um pouco melhor
S → aAcd | bAef
A → gh
FOLLOW(A) = {c, e}
Se estivermos utilizando a primeira produção de S,desejaremos utilizar o c para fazer a recuperação deerros, e não o e.
Como construir um compilador utilizando ferramentas Java – p. 8/22
Um pouco melhor
S → aAcd | bAef
A → gh
FOLLOW(A) = {c, e}
Se estivermos utilizando a primeira produção de S,desejaremos utilizar o c para fazer a recuperação deerros, e não o e.
Devemos permitir que a cada chamada de A sejainformado, por meio de um parâmetro, qual é o token desincronização a ser utilizado.
Como construir um compilador utilizando ferramentas Java – p. 8/22
No JavaCC
Construções try/catch
Dessa forma, caso não haja um casamento esperado, ométodo pode fazer a ressincronização.
Um erro de sintaxe é sinalizado com um ParseException
Como construir um compilador utilizando ferramentas Java – p. 9/22
Tratamento de errovoid A(){}{
try {"g" "h"
}catch (ParseException e){
// tratamento de erro}
}
Como construir um compilador utilizando ferramentas Java – p. 10/22
Chamada a não-terminaisvoid A(){}{
try {"g" B() "h"
}catch (ParseException e){
// tratamento de erros de A ou de B}
}
Como construir um compilador utilizando ferramentas Java – p. 11/22
Chamada a não-terminais
Nesse último caso, o não-terminal B pode ou nãoimplementar o tratamento de erro.
Se tratar, o método A não muda.
Se não tratar, um erro pode ser propagado e tratado emA.
Para cada chamada de não-terminal que trata dos errosdeve ser passado um conjunto de ressincronização.
Como construir um compilador utilizando ferramentas Java – p. 12/22
Esquema geralvoid S(){
RecoverySet x = new RecoverySet(<c>),y = new RecoverySet(<e>);
}{
( <a> A(x) <c> <d> |<b> A(y) <e> <f>
)}
Como construir um compilador utilizando ferramentas Java – p. 13/22
Esquema geralvoid A(RecoverySet r){}{
try {<g> <h>
}catch (ParseException e){
consumeUntil(r, e, "A");}
}
Como construir um compilador utilizando ferramentas Java – p. 14/22
Método consumeUntil
Dá mensagem sobre recuperação de erros (ver main);
Como construir um compilador utilizando ferramentas Java – p. 15/22
Método consumeUntil
Dá mensagem sobre recuperação de erros (ver main);
Se conjunto de sincronização não null, vai consumindoos tokens da entrada até achar algum no conjunto.
Como construir um compilador utilizando ferramentas Java – p. 15/22
Método consumeUntil
Dá mensagem sobre recuperação de erros (ver main);
Se conjunto de sincronização não null, vai consumindoos tokens da entrada até achar algum no conjunto.
Se um <EOF> for achado, lança outro tipo de exceçãoParseEOFException
Como construir um compilador utilizando ferramentas Java – p. 15/22
Método consumeUntil
Dá mensagem sobre recuperação de erros (ver main);
Se conjunto de sincronização não null, vai consumindoos tokens da entrada até achar algum no conjunto.
Se um <EOF> for achado, lança outro tipo de exceçãoParseEOFException
Por isso, todos os métodos devem declarar esse tipo deexceção.
Como construir um compilador utilizando ferramentas Java – p. 15/22
Método consumeUntil
Dá mensagem sobre recuperação de erros (ver main);
Se conjunto de sincronização não null, vai consumindoos tokens da entrada até achar algum no conjunto.
Se um <EOF> for achado, lança outro tipo de exceçãoParseEOFException
Por isso, todos os métodos devem declarar esse tipo deexceção.
Incremnta número de erros encontrados.
Como construir um compilador utilizando ferramentas Java – p. 15/22
Do começovoid program()
throws ParseEOFException : {
RecoverySet g = new RecoverySet(EOF);
}
{
try {
[ classlist(g) ] <EOF>
}
catch (ParseException e) {
consumeUntil(g, e, "program");
}
}
Como construir um compilador utilizando ferramentas Java – p. 16/22
RecoverySet
Implementa um conjunto de inteiros, com algumasoperações específicas
Construtor RecoverySet(int)
boolean contains(int)
RecoverySet union(RecoverySet)
RecoverySet add(in)
RecoverySet remove(in)
String toString()
Como construir um compilador utilizando ferramentas Java – p. 17/22
classlistvoid classlist(RecoverySet g)
throws ParseEOFException : {
RecoverySet f = First.classlist.union(g);
}
{
classdecl(f) [ classlist(g) ]
}
Não há recuperação de erros.
Não há possibilidade de erros sintático.
Uso dos conjuntos da classe First
Como construir um compilador utilizando ferramentas Java – p. 18/22
classbodyvoid classbody(RecoverySet g) throws ParseEOFException : {
RecoverySet f1 = new RecoverySet(RBRACE),
f2 = new RecoverySet(SEMICOLON),
f3 = First.methoddecl.union(f1),
f4 = First.constructdecl.union(f3),
f5 = First.vardecl.union(f4);
}
{
try {
<LBRACE>
[classlist(f5)]
(LOOKAHEAD(3) vardecl(f2) <SEMICOLON>)*(constructdecl(f4))*(methoddecl(f3))*
<RBRACE>
}
catch (ParseException e) {
consumeUntil(g, e, "classbody");
}
}
Como construir um compilador utilizando ferramentas Java – p. 19/22
Algumas exceçõesvoid lvalue(RecoverySet g) throws ParseEOFException :
{}
{
try {
<IDENT> (
<LBRACKET> expression(null) <RBRACKET> |
<DOT> <IDENT> [<LPAREN> arglist(null) <RPAREN>]
)*}
catch (ParseException e) {
consumeUntil(g, e, "lvalue");
}
}
É o ponto “mais baixo” onde se realiza
recuperação de erros.
a[i + * 3].x = 123;
Como construir um compilador utilizando ferramentas Java – p. 20/22
Expressionvoid expression(RecoverySet g)
throws ParseEOFException :
{}
{
try {
numexpr()
[(<LT>|<GT>|<LE>|<GE>|<EQ>|<NEQ>)
numexpr()]
}
catch (ParseException e) {
consumeUntil(g, e, "expression");
}
}
Como construir um compilador utilizando ferramentas Java – p. 21/22
Algumas melhorias
A forma de cálculo do conjunto de sincronização ébastante simples.
Esse conjunto é muito importante no sucesso darecuperação.
Nem sempre é eficiente.
Uma análise caso-a-caso pode melhorar a eficiência daestratégia.
Ver descrição no capítulo 5.
Como construir um compilador utilizando ferramentas Java – p. 22/22