Created
June 20, 2011 14:13
-
-
Save carlosbrando/1035669 to your computer and use it in GitHub Desktop.
Um analisador recursivo descendente bem simples.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "..\h\parser.h" | |
/* Variáveis para controlar a analise da expressão */ | |
char *prog; /* contém a expressão a ser analisada */ | |
char token[80]; | |
char tok_type; | |
/* Esse array armazena as variáveis de A-Z disponíveis no parser */ | |
double vars[26] = { | |
0.0, 0.0, 0.0, 0.0, 0.0, | |
0.0, 0.0, 0.0, 0.0, 0.0, | |
0.0, 0.0, 0.0, 0.0, 0.0, | |
0.0, 0.0, 0.0, 0.0, 0.0, | |
0.0, 0.0, 0.0, 0.0, 0.0, 0.0 | |
}; | |
/* main(void) { | |
printf("A resposta é %.2f\n", parser("a=1")); | |
printf("A resposta é %.2f\n", parser("a+10")); | |
} */ | |
double parser_expression(char *expression) { | |
double answer; | |
char p[100]; | |
prog = p; | |
strcpy(prog, expression); | |
eval_exp(&answer); | |
return answer; | |
} | |
/* Ponto de entrada do analisador */ | |
void eval_exp(double *answer) { | |
get_token(); | |
if (!*token) { | |
serror(2); | |
return; | |
} | |
eval_exp1(answer); | |
if (*token) | |
serror(0); /* o último token deve ser nulo */ | |
} | |
/* Processa uma atribuição */ | |
void eval_exp1(double *result) { | |
int slot, ttok_type; | |
char temp_token[80]; | |
if (tok_type == VARIAVEL) { | |
/* salva token antigo */ | |
strcpy(temp_token, token); | |
ttok_type = tok_type; | |
/* calcula o índice da variável */ | |
slot = toupper(*token) - 'A'; | |
get_token(); | |
if (*token != '=') { | |
putback(); /* devolve token atual */ | |
/* restaura token antigo - nenhuma atribuição */ | |
strcpy(token, temp_token); | |
tok_type = ttok_type; | |
} else { | |
get_token(); | |
eval_exp2(result); | |
vars[slot] = *result; | |
return; | |
} | |
} | |
eval_exp2(result); | |
} | |
/* Soma ou subtrai dois termos */ | |
void eval_exp2(double *answer) { | |
register char op; | |
double temp; | |
eval_exp3(answer); | |
while ((op = *token) == '+' || op == '-') { | |
get_token(); | |
eval_exp3(&temp); | |
switch(op) { | |
case '-': | |
*answer = *answer - temp; | |
break; | |
case '+': | |
*answer = *answer + temp; | |
break; | |
} | |
} | |
} | |
/* Multiplica ou divide dois fatores */ | |
void eval_exp3(double *answer) { | |
register char op; | |
double temp; | |
eval_exp4(answer); | |
while ((op = *token) == '*' || op == '/' || op == '%') { | |
get_token(); | |
eval_exp4(&temp); | |
switch(op) { | |
case '*': | |
*answer = *answer * temp; | |
break; | |
case '/': | |
*answer = *answer / temp; | |
break; | |
case '%': | |
*answer = (int) *answer % (int) temp; | |
break; | |
} | |
} | |
} | |
/* Processa um expoente */ | |
void eval_exp4(double *answer) { | |
double temp, ex; | |
register int t; | |
eval_exp5(answer); | |
while (*token == '^') { | |
get_token(); | |
eval_exp4(&temp); | |
ex = *answer; | |
if (temp == 0.0) | |
*answer = 1.0; | |
return; | |
} | |
for (t = temp - 1; t > 0; --t) | |
*answer = (*answer) * (double)ex; | |
} | |
/* Avalia um + ou - unário */ | |
void eval_exp5(double *answer) { | |
register char op; | |
op = 0; | |
if ((tok_type == DELIMITADOR) && *token == '+' || *token == '-') { | |
op = *token; | |
get_token(); | |
} | |
eval_exp6(answer); | |
if (op == '-') | |
*answer = -(*answer); | |
} | |
/* Processa uma operação entre parênteses */ | |
void eval_exp6(double *answer) { | |
if (*token == '(') { | |
get_token(); | |
eval_exp2(answer); | |
if (*token != ')') | |
serror(1); | |
get_token(); | |
} else { | |
atom(answer); | |
} | |
} | |
/* Obtém o valor de um número ou variável */ | |
void atom(double *answer) { | |
switch(tok_type) { | |
case VARIAVEL: | |
*answer = find_var(token); | |
get_token(); | |
return; | |
case NUMERO: | |
*answer = atof(token); | |
get_token(); | |
return; | |
default: | |
serror(0); /* erro de sintaxe na expressão */ | |
} | |
} | |
/* Devolve um token à stream de entrada */ | |
void putback(void) { | |
char *t; | |
t = token; | |
for (; *t; t++) | |
prog--; | |
} | |
/* Apresenta um erro de sintaxe */ | |
void serror(int error) { | |
static char *e[] = { | |
"Erro de sintaxe", | |
"Falta parênteses", | |
"Nenhuma expressão presente" | |
}; | |
printf("%s\n", e[error]); | |
} | |
/* Devolve o próximo token */ | |
void get_token(void) { | |
register char *temp; | |
tok_type = 0; | |
temp = token; | |
*temp = '\0'; | |
/* final da expressão */ | |
if (!prog) return; | |
/* ignora espaços em branco */ | |
while (isspace(*prog)) ++prog; | |
if (strchr("+-*/%^=()", *prog)) { | |
tok_type = DELIMITADOR; | |
*temp++ = *prog++; /* avança para o próximo char */ | |
} else if (isalpha(*prog)) { | |
while (!isdelim(*prog)) *temp++ = *prog++; | |
tok_type = VARIAVEL; | |
} else if (isdigit(*prog)) { | |
while (!isdelim(*prog)) *temp++ = *prog++; | |
tok_type = NUMERO; | |
} | |
*temp = '\0'; | |
} | |
/* Devolve verdadeiro se c é um delimitador */ | |
int isdelim(char c) { | |
if (strchr(" +-*/%^=()", c) || c == 9 || c == '\r' || c == 0) | |
return 1; | |
return 0; | |
} | |
/* Devolve o valor de uma variável */ | |
double find_var(char *s) { | |
if (!isalpha(*s)) { | |
serror(1); | |
return 0; | |
} | |
return vars[toupper(*s) - 'A']; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _PARSER_H_ | |
#define _PARSER_H_ | |
#define DELIMITADOR 1 | |
#define VARIAVEL 2 | |
#define NUMERO 3 | |
/* Funções */ | |
void eval_exp(double *); | |
void eval_exp2(double *); | |
void eval_exp3(double *); | |
void eval_exp4(double *); | |
void eval_exp5(double *); | |
void eval_exp6(double *); | |
void atom(double *); | |
void putback(void); | |
void serror(int); | |
void get_token(void); | |
int isdelim(char); | |
double find_var(char *); | |
void eval_exp1(double *); | |
double parser_expression(char *); | |
#endif /* _PARSER_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment