Trabalho de Compiladores (v.2)
                                     Prof. Dr. Erwin Doescher


Análise Léxica: Deve reconhecer os seguintes elementos da linguagem

Palavras reservadas: else if int char return void while puts gets
Símbolos especiais: + – * / < <= > >= == != = ; , { } [ ] ( )

tokens: ID NUM string else if int char return void while puts gets relop

Definições regulares:
ID → letra ( letra | digito | _ )*
NUM → digito digito*
relop → <= | < | > | >= | == | !=
letra → [ a – z ]
digito → [ 0 – 9 ]
escape → " | ' | n | t
simbolos → [][@!#$%&()_+={}~?/;:.>,<|] | "-" | ' | ^
interno → letra | digito| escape | simbolos | espaço
string → "(interno|*)* "
comentarios → / *(/ * | interno| n)**/ | //.*n

Análise Sintática:

programa → lista_decl
lista_decl → lista_decl decl | decl
decl → var_decl | fun_decl

var_decl → tipo_var lista_id_var ;
lista_id_var → lista_id_var, id_var | id_var
id_var → ID | ID [ NUM ] | *ID | *ID [ NUM ]
tipo_var → int | char

fun_decl → tipo_var ID ( params ) composto_decl | void ID ( params ) composto_decl
params → param_lista | void
param_lista → param_lista, param | param
param → tipo_var id_param
id_param → ID | ID [ ] | *ID | *ID [ ]
tipo_fun → tipo_var | void

composto_decl → { local_decl statement_lista }
local_decl → local_decl var_decl | 
statement_lista → statement_lista statement | 
statement → puts_decl | gets_decl |expr_decl | composto_decl | sel_decl | iter_decl | retorno_decl

puts_decl → puts (ID); | puts (string);
gets_decl → gets (ID);
expr_decl → expr ; | ;
sel_decl → if ( expr ) statement
           | if ( expr ) statement else statement
iter_decl → while ( expr ) statement
retorno_decl → return ; | return expr ;
expr → var = expr | simples_expr
var → ID | ID [ expr ]
simples_expr → soma_expr relop soma_expr | soma_expr
relacional → <= | < | > | >= | == | !=
soma_expr → soma_expr soma termo | termo
soma → + | –
termo → termo mult fator | fator
mult → * | /
fator → ( expr ) | var | chamada | NUM

chamada → ID ( args )
args → arg_lista | 
arg_lista → arg_lista, expr | expr


Sugestão de roteiro de implementação:
   1. Defina o atributo dos tokens a serem enviados do analisador léxico para o sintático
   2. Defina os atributos dos símbolos gramaticais para o analisador sintático, definindo-os em
       uma estrutura
   3. Defina o atributo para o analisador implementado com o Yacc como sendo a união dos tipos
       definidos nos itens 1) e 2)
   4. Antes de implementar o arquivo do analisador léxico, defina os tokens necessários no
       arquivo do analisador sintático
   5. Faça o analisador léxico
   6. Defina as regras de produção no arquivo do analisador sintático, deixando provisoriamente
       as regras semânticas em branco
   7. Defina as regras semânticas usadas para inserir variáveis na tabela de símbolos
   8. Faça a verificação de tipos das regras de produção que necessitarem
   9. Defina o tipo de armazenamento a ser usado para o código intermediário: vetor fixo, vetor
       dinâmico ou lista ligada
   10. Crie as funções auxiliares necessárias para concatenar dois fragmentos de código
       intermediário em um único
   11. Crie as funções para gerar temporários e rótulos únicos
   12. Defina as regras semânticas para gerar o código de 3 endereços de cada produção.
   13. Implemente as otimizações básicas simples
   14. Implemente a rotina que leia o vetor de código intermediário e escreva o programa em
       linguagem de montagem correspondente (código alvo).


Prazos:
04/11/2010 – Analisador Léxico e Sintático com a inserção de dados na tabela de símbolos e
Verificação de tipos
18/11/2010 – Geração do código intermediário
25/11/2010 – Otimizações simples de código
02/12/2010 – (Final) Geração de código alvo
Obs.: A produção do if gera um conflito empilha/reduz:

sel_decl → if ( expr ) statement
          | if ( expr ) statement else statement

Para resolver o conflito é preciso dar uma precedência maior para o if … else.

Isto pode ser feito no yacc definindo as precedências:

%nonassoc menor_que_else
%nonassoc eles

no começo do arquivo e definindo a produção como:


sel_decl : if '(' expr ')' statement            %prec menor_que_else
         | if '(' expr ')' statement else statement
         ;

Trabalho

  • 1.
    Trabalho de Compiladores(v.2) Prof. Dr. Erwin Doescher Análise Léxica: Deve reconhecer os seguintes elementos da linguagem Palavras reservadas: else if int char return void while puts gets Símbolos especiais: + – * / < <= > >= == != = ; , { } [ ] ( ) tokens: ID NUM string else if int char return void while puts gets relop Definições regulares: ID → letra ( letra | digito | _ )* NUM → digito digito* relop → <= | < | > | >= | == | != letra → [ a – z ] digito → [ 0 – 9 ] escape → " | ' | n | t simbolos → [][@!#$%&()_+={}~?/;:.>,<|] | "-" | ' | ^ interno → letra | digito| escape | simbolos | espaço string → "(interno|*)* " comentarios → / *(/ * | interno| n)**/ | //.*n Análise Sintática: programa → lista_decl lista_decl → lista_decl decl | decl decl → var_decl | fun_decl var_decl → tipo_var lista_id_var ; lista_id_var → lista_id_var, id_var | id_var id_var → ID | ID [ NUM ] | *ID | *ID [ NUM ] tipo_var → int | char fun_decl → tipo_var ID ( params ) composto_decl | void ID ( params ) composto_decl params → param_lista | void param_lista → param_lista, param | param param → tipo_var id_param id_param → ID | ID [ ] | *ID | *ID [ ] tipo_fun → tipo_var | void composto_decl → { local_decl statement_lista } local_decl → local_decl var_decl |  statement_lista → statement_lista statement |  statement → puts_decl | gets_decl |expr_decl | composto_decl | sel_decl | iter_decl | retorno_decl puts_decl → puts (ID); | puts (string); gets_decl → gets (ID); expr_decl → expr ; | ; sel_decl → if ( expr ) statement | if ( expr ) statement else statement iter_decl → while ( expr ) statement
  • 2.
    retorno_decl → return; | return expr ; expr → var = expr | simples_expr var → ID | ID [ expr ] simples_expr → soma_expr relop soma_expr | soma_expr relacional → <= | < | > | >= | == | != soma_expr → soma_expr soma termo | termo soma → + | – termo → termo mult fator | fator mult → * | / fator → ( expr ) | var | chamada | NUM chamada → ID ( args ) args → arg_lista |  arg_lista → arg_lista, expr | expr Sugestão de roteiro de implementação: 1. Defina o atributo dos tokens a serem enviados do analisador léxico para o sintático 2. Defina os atributos dos símbolos gramaticais para o analisador sintático, definindo-os em uma estrutura 3. Defina o atributo para o analisador implementado com o Yacc como sendo a união dos tipos definidos nos itens 1) e 2) 4. Antes de implementar o arquivo do analisador léxico, defina os tokens necessários no arquivo do analisador sintático 5. Faça o analisador léxico 6. Defina as regras de produção no arquivo do analisador sintático, deixando provisoriamente as regras semânticas em branco 7. Defina as regras semânticas usadas para inserir variáveis na tabela de símbolos 8. Faça a verificação de tipos das regras de produção que necessitarem 9. Defina o tipo de armazenamento a ser usado para o código intermediário: vetor fixo, vetor dinâmico ou lista ligada 10. Crie as funções auxiliares necessárias para concatenar dois fragmentos de código intermediário em um único 11. Crie as funções para gerar temporários e rótulos únicos 12. Defina as regras semânticas para gerar o código de 3 endereços de cada produção. 13. Implemente as otimizações básicas simples 14. Implemente a rotina que leia o vetor de código intermediário e escreva o programa em linguagem de montagem correspondente (código alvo). Prazos: 04/11/2010 – Analisador Léxico e Sintático com a inserção de dados na tabela de símbolos e Verificação de tipos 18/11/2010 – Geração do código intermediário 25/11/2010 – Otimizações simples de código 02/12/2010 – (Final) Geração de código alvo
  • 3.
    Obs.: A produçãodo if gera um conflito empilha/reduz: sel_decl → if ( expr ) statement | if ( expr ) statement else statement Para resolver o conflito é preciso dar uma precedência maior para o if … else. Isto pode ser feito no yacc definindo as precedências: %nonassoc menor_que_else %nonassoc eles no começo do arquivo e definindo a produção como: sel_decl : if '(' expr ')' statement %prec menor_que_else | if '(' expr ')' statement else statement ;