Etapa 4: Gramática e Gerador ANTLR4

Objetivos

  • Substituir o parser manual por um gerador de parsers industrial (ANTLR4).
  • Aprender a linguagem de descrição de gramáticas .g4.
  • Utilizar o padrão Visitor para converter a árvore concreta do ANTLR (ParseTree) na sua AST.

Fundamentação Teórica

Ferramentas como ANTLR geram automaticamente o código do Lexer e Parser a partir de uma especificação formal. Isso reduz erros e facilita a manutenção. No entanto, o ANTLR gera uma Parse Tree (Árvore Concreta), que contém todos os tokens (vírgulas, parênteses). Nosso objetivo é transformar isso na nossa AST (mais limpa) que definimos na Etapa 1.

Atividades Práticas

1. Preparação

  • Instale o plugin do ANTLR4 na sua IDE.
  • Adicione a dependência do ANTLR4 Runtime no pom.xml.
<dependency>
    <groupId>org.antlr</groupId>
    <artifactId>antlr4-runtime</artifactId>
    <version>4.13.1</version>
</dependency>

2. Definindo a Gramática (MiniPascal.g4)

Crie o arquivo na pasta src/main/antlr4/br/com/compiler/parser. Exemplo de estrutura:

grammar MiniPascal;

// Parser Rules
program: 'program' ID ';' varDecl? block '.' EOF;

varDecl: 'var' (ID (',' ID)* ':' type ';')+;

type: 'integer' | 'boolean' | 'string';

// ... outras regras (command, expression, etc) ...

// Lexer Rules
ID: [a-zA-Z][a-zA-Z0-9]*;
NUMBER: [0-9]+;
WS: [ \t\r\n]+ -> skip;

3. Gerando o Código

Execute o comando Maven (ou use o plugin da IDE) para gerar as classes Java (MiniPascalLexer, MiniPascalParser, MiniPascalBaseVisitor, etc).

4. Implementando o Visitor

Crie uma classe MyVisitor que estende MiniPascalBaseVisitor<AstNode>. Você deve sobrescrever os métodos visit para construir seus nós.

Exemplo:

public class MyVisitor extends MiniPascalBaseVisitor<AstNode> {
    
    @Override
    public AstNode visitAssignment(MiniPascalParser.AssignmentContext ctx) {
        // ctx.ID() retorna o token do identificador
        Identifier id = new Identifier(ctx.ID().getText());
        // ctx.expression() retorna o contexto da expressão filho
        Expression expr = (Expression) visit(ctx.expression());
        
        return new AssignmentCommand(id, expr);
    }
    
    @Override
    public AstNode visitBinaryExpr(MiniPascalParser.BinaryExprContext ctx) {
        Expression left = (Expression) visit(ctx.expression(0));
        Expression right = (Expression) visit(ctx.expression(1));
        String op = ctx.op.getText();
        return new BinaryExpression(left, right, op);
    }
}

O que entregar

  • Arquivo MiniPascal.g4 completo.
  • Classe MyVisitor implementando a conversão.
  • Atualize seu programa principal para usar o ANTLR Lexer/Parser, passar pelo Visitor e imprimir a AST. A saída deve ser idêntica (ou superior) à da Etapa 3.
Back to top