hoc1b: sinal negativo e make
Esta página descreve os arquivos do diretório etapa1b/.
Explicação do programa
Uma das vantagens de usar o yacc/bison é que a definição de alto nível da gramática facilita mudar ou acrescentar novos recursos à linguagem que estamos desenvolvendo.
Para incorporar o sinal de número negativo, será preciso apenas mais duas linhas de código. O código-fonte completo está em hoc1b.y (link).
Mudanças na gramática
A primeira mudança é acresecentar a declaração do token NEGATIVO que vai representar o operador também conhecido como unary minus (menos unário).
%token NUMERO
%left '+' '-' /* associatividade esquerda */
%left '*' '/' /* associatividade esquerda, maior precedência */
%left NEGATIVO /* hoc1b */
Colocar NEGATIVO por último dá a precedência mais alta para esse sinal.
A próxima mudança é incluir uma nova forma nas regras sintáticas de expr:
expr: NUMERO { $$ = $1; }
| '-' expr %prec NEGATIVO { $$ = -$2; } /* hoc1b */
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
/* etc... */
A 2ª linha estabelece que a forma '-' expr terá precedência alta (%prec NEGATIVO), e seu valor será o negativo da expressão ($$ = -$2). A forma da 4ª linha (expr '-' expr) continuará sendo usada quando o sinal '-' aparecer entre duas expressões.
Construir e testar
Use yacc para gerar o código em C, compile, e teste:
$ yacc hoc1b.y
$ cc y.tab.c -o hoc1b
$ ./hoc1b < testes.hoc
4
-7
37.777778
100.4
Para testar o sinal de negativo, incluí a linha -3 - 4 em testes.hoc. Por isso, o resultado -7.
Agora vamos ver como automatizar a construção do programa.
Introdução a make
Toda vez que fazemos uma alteração em um arquivo .y, temos que rodar yacc e depois cc. É inconveniente, mas o pior fazer é uma mudança no arquivo .y, esquecer um desses passos e ficar testando um executável que não foi atualizado, como já aconteceu comigo.
É fácil criar um script no shell para rodar esses comandos, mas é melhor usar a ferramenta make, pois ela foi projetada para construir programas, processa arquivos .y automaticamente, e evita realizar passos desnecessários — por exemplo, não executa o compilador se o arquivo-fonte hoc.y não foi tocado.
Se você executar o comando make hoc1b no diretório etapa1b/, verá esta saída:
$ make hoc1b
yacc hoc1b.y
mv -f y.tab.c hoc1b.c
cc -c -o hoc1b.o hoc1b.c
cc hoc1b.o -o hoc1b
rm hoc1b.o hoc1b.c
Observe os comandos executados por make:
yaccpara processarhoc1b.ye gerary.tab.c;mvpara renomeary.tab.cparahoc1b.c;ccpara compilarhoc1b.ce gerar o arquivo-objetohoc1b.o;ccpara montar o executávelhoc1ba partir dehoc1b.o;rmpara apagarhob1b.oehob1b.c.
Se você rodar make hoc1b de novo, make não faz nada além de avisar que o executável hoc1b já está atualizado:
$ make hoc1b
make: 'hoc1b' is up to date.
Toda essa lógica e muito mais está embutida no make.
Veremos depois como criar um Makefile para configurar as ações do make.
Voltar para o índice de páginas.