Pessoal,
Escrevi a gramática abaixo (é a minha primeira, deve estar uma porcaria e ainda não terminei todos as regras!). Mas por agora o problema que estou tendo é que ela está aceitando expressões como AGL(L1)1+2AGL(L2), quando deveria dar erro pois AGL(L1)1 não deveria ser válido… bom, não sei como resolver. Se puder dar uma olhada e me indicar uma solução, algum material, etc, ficaria muito grato!
grammar expressaoMC;
// Expressao
expression : term ( ( PLUS | MINUS ) term ) * ;
// Termos
term : factor ( ( MULT | DIV ) factor ) * ;
// Fatores
factor : NUMBER | function ;
// Funcoes
function : functionPM
| functionNum
| functionLog ;
functionPM :
( ‘ACB’
| ‘ACL’
| ‘AGB’
)
( LPAREN pm RPAREN
) ;
functionNum :
( ‘MAX’
| ‘MIN’
)
( LPAREN expression SEMI expression RPAREN
) ;
functionLog : ‘SE’ LPAREN expression SEMI expression SEMI expression RPAREN;
// Tipos (parametros para funcoes)
pm :
( ‘L’
| ‘B’
) NUMBER ;
NUMBER : ( ‘0’ … ‘9’ ) + ;
// Operadores matematicos
PLUS : ‘+’ ;
MINUS : ‘-’ ;
MULT : ‘*’ ;
DIV : ‘/’ ;
LPAREN : ‘(’ ;
RPAREN : ‘)’ ;
// Operadores relacionais
EQUALS : ‘=’ ;
GT : ‘>’ ;
GET : ‘>=’ ;
LT : ‘<’ ;
LET : ‘<=’ ;
// Operadores logicos
AND : ‘E’ ;
OR : ‘OU’ ;
// Operador de subexpressao
SUB : ‘!’ ;
// Espaco em branco
WS :
( ‘\t’
| ’ ’
| ‘\r’
| ‘\n’
| ‘\u000C’
) + { $channel = HIDDEN; } ;
// SEPARADORES
SEMI : ‘;’ ;
Boa noite schranko, tudo bem?
Bom eu não dei uma olhada na definição da sua gramatica pois estou sem tempo, mas queria comentar sobre a parte do material, existe um livro chamado
Como Construir um Compilador Utilizando Ferramentas Java
http://novatec.com.br/livros/compilador/
Que descreve a criação de uma linguagem chamada x++ utilizando ferramentas java como javacc http://javacc.java.net/ para geração de um parser (ele parece um pouco com o sablecc http://sablecc.org/ se eu me lembro bem), e o jasmin http://jasmin.sourceforge.net/ que converte um formato intermediario para bytecode da jvm.
O livro é bem didatico, não sei se é um requisito para você usar ANTLR mas pelo menos vale a pena dar uma olhada nele pois ele apresenta conceitos interessantes correlatos a compiladores.
Como você disse que essa é sua primeira gramatica vale a pena você começar por alguma coisa mais simples como uma gramatica para aceitar expressões matematicas simples só com numeros mesmo e ir melhorando aos poucos. Só um detalhe esse livro é um pouco antigo por isso deve ser um pouco dificil de achar mas da uma pesquisada.
Existe tambem esse outro livro:
Livro Compiladores - Princípios, Técnicas e Ferramentas
Bom mas você tambem pode talvez usar (se você puder) alguma linguagem funcional como Haskell que são muito boas para essas coisas, aqui no forum tem post falando sobre isso.
Mais uma coisa http://cameraweb.ccuec.unicamp.br/group/mo403
Espero ter te ajudado de alguma forma, se eu tiver tempo tento dar uma olhada na sua gramatica.
Boa Sorte
abaldove, obrigado. EU ate conheco um pouco sobre compiladores, mas estou tendo problema em definir a gramatica que aceite corretamente expressoes como a que eu passei.
No caso, uma parte dessa gramatica ja reconhece expressores matematicas, meu problema e justamente quando junto as duas coisas (expressoes matematicas e funcoes). Se puder dar uma olhada eu agradeco!
Oi schranko,
Não é AGL é ACL certo? Então, o que está acontecendo que é o parser começa a avaliar a expressão e para depois de ACL(L1), dando a expressão como verdadeira.
Estou fazendo umas modificações, vou ver se consigo resolver.
[]'s
Fiz uma versão simplificada da sua gramática e adicionei parênteses nas expressões.
Tirei as outras funções para facilitar meus testes.
Agora basta vc inseri-las novamente e testar.
Para que o parser leia toda a string de entrada, vc precisa usar o token EOF no final da regra de entrada (expression no seu caso), assim o parser só vai parar quando escontrar o fim do arquivo ou o fim da string.
Dá uma olhada como ficou.
[code]
grammar expressaoMC;
expression : term ( ( ‘+’ | ‘-’ ) term )* EOF ;
term : factor ( ( '’ | ‘/’ ) factor ) ;
factor : NUMBER | LPAREN expression RPAREN | functions ;
functions : functionPM ;
functionPM : ( ‘ACB’ | ‘ACL’ | ‘AGB’ ) LPAREN ( ‘L’ | ‘B’ ) NUMBER RPAREN ;
NUMBER : ( ‘0’ … ‘9’ )+ ;
LPAREN : ‘(’ ;
RPAREN : ‘)’ ;
WS :
( ‘\t’
| ’ ’
| ‘\r’
| ‘\n’
| ‘\u000C’
) + { $channel = HIDDEN; } ;[/code]
[]'s
Ah, desculpa a demora para responder. Ontem eu estava bem ocupado.
[]'s
David, muito obrigado. Entendi sua solução, contudo obtive mais um erro aqui…
Ao avaliar a expressão (1+2)+3 ocorre o seguinte erro: line 1:4 missing EOF at ‘)’ - porque isso ocorre?
Com relação a “demorar”, não se desculpe! eu que me desculpo por minha ignorância ahahah
Oi Angelo,
Parece que resolvi. Adicionei mais uma produção que gera expression EOF.
Seu exemplo funcionou. Tentei um mais complexo e deu certo tbm ( color=blue+500/4[/color] )
Dá uma olhada:
[code]grammar expressaoMC;
start : expression EOF ;
expression : term ( ( ‘+’ | ‘-’ ) term )* ;
term : factor ( ( '’ | ‘/’ ) factor ) ;
factor : NUMBER | LPAREN expression RPAREN | functions ;
functions : functionPM ;
functionPM : ( ‘ACB’ | ‘ACL’ | ‘AGB’ ) LPAREN ( ‘L’ | ‘B’ ) NUMBER RPAREN ;
NUMBER : ( ‘0’ … ‘9’ ) + ;
LPAREN : ‘(’ ;
RPAREN : ‘)’ ;
WS :
( ‘\t’
| ’ ’
| ‘\r’
| ‘\n’
| ‘\u000C’
) + { $channel = HIDDEN; } ;[/code]
[]'s
David, funcionou, mas agora está aceitando novamente aquelas expressões no início do problema. ACL(L1)1+2ACL(L2) 
Vou dar uma olhada aqui…
Obrigado!
OK David, mesmo assim obrigado. Se puder me ajudar só com mais uma dúvida então. O que preciso é personalizar as mensagens de erro de sintaxe. Sei que dá para implementar a gramática separada do código Java ou junta. Eu preciso de alguma forma interceptar os erros do ANTLR e enviar uma mensagem personalizada para cada erro. Como eu faria isso? Você poderia me explicar ou me enviar alguma referência ou exemplo de código? Muito obrigado pela sua atenção!
Oi Angelo,
Aqui explica como faz http://www.antlr.org/wiki/display/ANTLR3/Custom+Syntax+Error+Recovery
Algo q vc poderia tentar fazer é algo assim:
[code]grammar expressaoMC;
/@header {
import caminho.SuaExcecaoQueHerdaDeRecognitionException;
}/
@members {
class MinhaExcecao extends RecognitionException {
private String info;
private RecognitionException origem;
public MinhaExcecao( String info, RecognitionException origem ) {
super();
this.info = info;
this.origem = origem;
}
@Override
public String toString() {
return info + " " + origem.token.getText();
}
}
}
start : expression EOF ;
expression : term ( ( ‘+’ | ‘-’ ) term )* ;
term : factor ( ( '’ | ‘/’ ) factor ) ;
factor : NUMBER | LPAREN expression RPAREN | functions ;
functions : functionPM ;
functionPM : ( ‘ACB’ | ‘ACL’ | ‘AGB’ ) LPAREN ( ‘L’ | ‘B’ ) NUMBER RPAREN ;
catch [ RecognitionException re ] {
throw new MinhaExcecao( "Erro em ", re );
}
NUMBER : ( ‘0’ … ‘9’ ) + ;
LPAREN : ‘(’ ;
RPAREN : ‘)’ ;
WS :
( ‘\t’
| ’ ’
| ‘\r’
| ‘\n’
| ‘\u000C’
) + { $channel = HIDDEN; } ;[/code]
Crie a exceção que herda de RecognitionException ao invés de declará-la dentro da gramática.
Ai, quando por usar o parser, vc captura essa excessão que vai conter o erro personalizado.
[]'s