Gostaria de começar a usar o ANTLR, mas depois de passar algumas horas analisando os exemplos no site antlr.org , ainda não consigo entender claramente a gramática do processo Java.
Existe algum exemplo simples, algo como uma calculadora de quatro operações implementada com o ANTLR passando pela definição do analisador e todo o caminho até o código-fonte Java?
Respostas:
Nota : esta resposta é para ANTLR3 ! Se você está procurando um exemplo de ANTLR4 , estas perguntas e respostas demonstram como criar um analisador de expressão simples e um avaliador usando ANTLR4 .
Você primeiro cria uma gramática. Abaixo está uma pequena gramática que você pode usar para avaliar expressões criadas usando os 4 operadores matemáticos básicos: +, -, * e /. Você também pode agrupar expressões usando parênteses.
Observe que essa gramática é apenas muito básica: ela não lida com operadores unários (o menos em: -1 + 9) ou decimais como 0,99 (sem um número inicial), para citar apenas duas deficiências. Este é apenas um exemplo que você pode trabalhar em si mesmo.
Aqui está o conteúdo do arquivo de gramática Exp.g :
(As regras do analisador começam com uma letra minúscula e as regras do lexer começam com uma letra maiúscula)
Depois de criar a gramática, você desejará gerar um analisador e um lexer. Faça o download do jar ANTLR e armazene-o no mesmo diretório do seu arquivo de gramática.
Execute o seguinte comando no seu shell / prompt de comando:
Ele não deve produzir nenhuma mensagem de erro e os arquivos ExpLexer.java , ExpParser.java e Exp.tokens agora devem ser gerados.
Para ver se tudo funciona corretamente, crie esta classe de teste:
e compile-o:
e execute-o:
Se tudo correr bem, nada está sendo impresso no console. Isso significa que o analisador não encontrou nenhum erro. Quando você muda e,
"12*(5-6)"
em"12*(5-6"
seguida, recompila e executa, deve ser impresso o seguinte:Ok, agora queremos adicionar um pouco de código Java à gramática para que o analisador realmente faça algo útil. A adição de código pode ser feita colocando
{
e}
dentro de sua gramática com algum código Java simples dentro dele.Mas primeiro: todas as regras do analisador no arquivo de gramática devem retornar um valor duplo primitivo. Você pode fazer isso adicionando
returns [double value]
após cada regra:que precisa de pouca explicação: espera-se que todas as regras retornem um valor duplo. Agora, para "interagir" com o valor de retorno
double value
(que NÃO está dentro de um bloco de código Java simples{...}
) de dentro de um bloco de código, você precisará adicionar um cifrão na frente devalue
:Aqui está a gramática, mas agora com o código Java adicionado:
e como nossa
eval
regra agora retorna um duplo, altere seu ANTLRDemo.java para este:Novamente (re) gere um novo lexer e analisador da sua gramática (1), compile todas as classes (2) e execute ANTLRDemo (3):
e agora você verá o resultado da expressão
12*(5-6)
impressa no seu console!Novamente: esta é uma explicação muito breve. Convido você a navegar no wiki da ANTLR e ler alguns tutoriais e / ou brincar um pouco com o que acabei de publicar.
Boa sorte!
EDITAR:
Esta postagem mostra como estender o exemplo acima para que
Map<String, Double>
seja possível fornecer um que retenha variáveis na expressão fornecida.Para que esse código funcione com uma versão atual do Antlr (junho de 2014), eu precisava fazer algumas alterações.
ANTLRStringStream
precisava se tornarANTLRInputStream
, o valor retornado precisava mudar deparser.eval()
paraparser.eval().value
e eu precisava remover aWS
cláusula no final, porque valores de atributo como$channel
não são mais permitidos para aparecer em ações lexer.fonte
parser.eval()
acontecem? Isso não está claro AQUI ou no ANTLR3 Wiki!eval
é uma regra do analisador que retorna adouble
. Portanto, há umeval()
método que você pode chamar em uma instância de umExpParser
, assim como demonstrei noANTLRDemo.main(...)
. Após gerar um lexer / analisador, basta abrir o arquivoExpParser.java
e você verá que existe umeval()
método retornando adouble
.O mega tutorial da ANTLR de Gabriele Tomassetti é muito útil
Possui exemplos de gramática, exemplos de visitantes em diferentes linguagens (Java, JavaScript, C # e Python) e muitas outras coisas. Altamente recomendado.
EDIT: outros artigos úteis de Gabriele Tomassetti na ANTLR
fonte
Para o Antlr 4, o processo de geração de código java está abaixo: -
Atualize o nome do seu jar no caminho de classe adequadamente.
fonte
Em https://github.com/BITPlan/com.bitplan.antlr, você encontrará uma biblioteca java ANTLR com algumas classes auxiliares úteis e alguns exemplos completos. Está pronto para ser usado com o maven e se você gosta de eclipse e maven.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/exp/Exp.g4
é uma linguagem de expressão simples que pode multiplicar e adicionar operações. https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestExpParser.java possui os testes de unidade correspondentes.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/iri/IRIParser.g4 é um analisador de IRI que foi dividido nas três partes:
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIRIParser.java possui os testes de unidade para isso.
Pessoalmente, achei a parte mais complicada de acertar. Consulte http://wiki.bitplan.com/index.php/ANTLR_maven_plugin
https://github.com/BITPlan/com.bitplan.antlr/tree/master/src/main/antlr4/com/bitplan/expr
contém mais três exemplos que foram criados para um problema de desempenho do ANTLR4 em uma versão anterior. Enquanto isso, esses problemas foram corrigidos conforme mostra o testcase https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIssue994.java .
fonte
a versão 4.7.1 era um pouco diferente: para importação:
para o segmento principal - observe os CharStreams:
fonte