Calculadora usando Lex e Yacc


O lex gera o código em c do analisador léxico, e salva-o com o nome lex.yy.c. Para testar, digite o programa abaixo e salve-o com o nome calc.l:

%{
  #include "y.tab.h"
%}
 
%%
 
[a-z]         { yylval = *yytext - 'a';
                return VARIAVEL;
              }
 
[0-9]+        { yylval = atoi(yytext);
                return INTEIRO;
              }
[-+()=/*\n]   { return *yytext;
              }
[ \t]         ; /* faz nada */
              { yyerror("Caracter desconhecido");
              }
 
%%
 
int yywrap(void)
{
  return 1;
}

Uma vez tendo-se as regras do analisador léxico, o programa Yacc pode ser utilizado para gerar o código com C do analisador sintático. Após executar o Yacc, a saída é gravada em um arquivo de nome y.tab.c e opcionalmente gera-se um arquivo de cabeçalho contendo os tokens, chamado de y.tab.h.

Digite o código abaixo e salve-o com o nome calc.y:

%{
#include <ctype.h>
#include <stdio.h>
%}
 
%token INTEIRO VARIAVEL
%left '+' '-'
%left '*' '/'
 
%{
  int simbolo[26];
%}
 
%%
 
programa:
          programa declaracao '\n'
          |
          ;
declaracao:
          expr                { printf("%d\n", $1); }
          | VARIAVEL '=' expr { simbolo[$1] = $3; }
          ;
expr:
          INTEIRO
          | VARIAVEL          { $$ = simbolo[$1]; }
          | expr '+' expr     { $$ = $1 + $3; }
          | expr '-' expr     { $$ = $1 - $3; }
          | expr '*' expr     { $$ = $1 * $3; }
          | expr '/' expr     { $$ = $1 / $3; }
          | '(' expr ')'      { $$ = $2; }
          ;
 
%%
 
int yyerror(char *s)
{
  fprintf(stderr, "%s\n", s);
  return 0;
}
 
int main(void)
{
  yyparse();
  return 0;
}

Uma vez os arquivos digitados e salvos, no shell do sistema compile os arquivos da seguinte forma:

1>yacc -d calc.y
2>lex calc.l
3>gcc lex.yy.c y.tab.c

Na linha 1, o yacc gera o y.tab.c e o y.tab.h. Na linha 2 o lex gera o lex.yy.c. A linha 3 utiliza o compilador gcc para criar o arquivo binário (ou executável), de nome a.out. Um exemplo de execução do programa é:

> ./a.out
a=2
a+3
5
b=a+4*(2+1)
b
14

  • Exercício para aula: reproduza o experimento. Implemente melhorias.

No windows, pode ocorrer de se ter nomes diferentes. No exemplo abaixo, renomeou-se os arquivos da seguinte forma:

rename calc_tab.h y.tab.h
rename calc_tab.c y.tab.c

E a compilação se dá no prompt conforme a figura abaixo:

_calc-prompt.jpg

Caso necessário, instale os programas:



Nos sistemas windows, é necessário ter disponível o arquivo de configuração bison.simple na pasta. Baixe um exemplo de configuração geral que costuma funcionar para a maioria dos casos aqui: