Você está na página 1de 8

/*************************************************************

* Parser para uma calculadora

*

* Coded by Leon de Castela

*

* Esse é o parser que que acompanha o tutorial que eu fiz

*

* sobre o assunto.

*

* www.scribd.com/leon_de_castela

*

* www.twitter.com/leon_de_castela

*

*************************************************************/

// Parser.cpp #include <iostream>

#include <stack> // header para a pilha #include <string> #include <stdlib.h> #define INICIO 1 #define ACEITAR 5

#define MORRE #define FIM

#define MORRE #define FIM

0

'='

#define ABRE '(' #define FECHA ')' #define MAXEXP 20 //Códigos de ERRO

#define ER_DIV_ZERO -1

#define ER_EXP

-2

#define ER_NO_EXP

-3

inline int eh_num(char c); inline int eh_oper(char c);

int automato(char* exp); double parse(char*); void posfixo(char*,char*); int prioridade(char,char);

int main(int argc, char** argv){ char exp[20];

cout << "Parser Simples para uma Calculadora\n"; cout << "Coded by Leon de Castela\n"; cout << "Digite = para sair" << endl; cout << "Expressão:";

cin

>> exp;

}

while (exp[0] != FIM){ cout << "=" << parse(exp) << endl; cout << "Expressão:"; cin >> exp;

cout << "Tchau!"; return 0;

}

int automato(char* exp){ char token;

int

i = 0, estado = INICIO;

token = exp[i]; while (token != '\0'){ if (estado == INICIO && eh_num(token)){ estado = INICIO;

}

else if (estado == INICIO && token == ABRE){ estado = 2;

else if (estado == INICIO && eh_oper(token)){ estado = 6;

else if (estado == INICIO && token == FIM){ return ACEITAR;

else if (estado == INICIO && token == FECHA){ return MORRE;

else if (estado == 2 && eh_num(token) ){ estado = 2;

else if (estado == 2 && eh_oper(token) ){ estado = 3;

}

}

}

}

}

}

else if (estado == 2 && token == FIM ){ return MORRE;

else if (estado == 3 && eh_oper(token) ){ return MORRE;

else if (estado == 3 && eh_num(token) ){ estado = 3;

else if (estado == 3 && token == FECHA ){ estado = 4;

else if (estado == 3 && token == FIM ){ return MORRE;

else if (estado == 4 && eh_num(token) ){ return MORRE;

else if (estado == 4 && token == FIM ){ return ACEITAR;

else if (estado == 4 && eh_oper(token) ){ estado = 6;

else if (estado == 6 && eh_oper(token) ){ return MORRE;

}

}

}

}

}

}

}

}

}

else

 

if (estado == 6 && eh_num(token) ){ estado = INICIO;

}

else

if (estado == 6 && token == FIM ){ return ACEITAR;

}

if (estado == 6 && token == ABRE ){ estado = 2;

}

token = exp[++i]; }//while

}

inline int eh_num(char c){ //0x30 e 0x39 são os caracteres de 0 a 9 na tabela ascii if (c >= 0x30 && c <= 0x39) return 1 ;

else return 0;

}

inline int eh_oper(char c){ if (c == 0x2A || c == 0x2B || c == 0x2F || c == 0x2D ) return 1 ;

else return 0;

}

/*************

* posfixo

**********************************************************

*

*

*

Converte uma expressão para a forma posfixa

*

origem = expressão original

*

dest = expressão destino

*

*

*********************************************************/

void posfixo(char *origem, char* dest ){ char token; int pos = 0; int pos_dest = 0; stack<char> pilha; token = origem[pos];

while (token != '\0'){ // se for operador verifica a pilha if (token == ABRE){ pilha.push(token);

}

else if (token == FECHA){ while (pilha.top() != ABRE){

dest[pos_dest] = pilha.top(); pilha.pop(); pos_dest++;

}

if (!pilha.empty()) pilha.pop();

}

else if ( token == FIM){ while (!pilha.empty()){ dest[pos_dest] = pilha.top(); pilha.pop(); pos_dest++;

}

}

else if ( eh_num(token) ){ dest[pos_dest] = token; pos_dest++;

else if ( eh_oper(token) )

}

{ if (pilha.empty())

{ pilha.push(token);

}

else if (prioridade(token, pilha.top())){ pilha.push(token);

}

else{

dest[pos_dest] = pilha.top(); pilha.pop(); pos_dest++;

}

}

token = origem[++pos]; }//while

}

// A mais esperada de todas! double parse(char* exp){ stack<double> pilha; char destino[MAXEXP]; int pos = 0; double res,op1=0,op2=0,aux; char token;

memset(destino,'\0',MAXEXP);

//verificação da sintaxe if (automato(exp) == ACEITAR){ cout << "Expressão correta!\n";

}

else{ cout << "Erro de Sintaxe!\n"; exit(ER_EXP);

cout << "Convertendo expressão " << exp << endl; posfixo(exp, destino); cout << "Calculando expressão " << destino << endl; token = destino[pos]; if (token == '\0' ){ cout << "Tchau!\n"; exit(ER_NO_EXP);

while (token != '\0'){ if (eh_num(token)){ aux = atof (&token); pilha.push(aux);

}

}

}

else if (eh_oper(token)){ if (!pilha.empty()){ op2 = pilha.top(); pilha.pop();

}

if (!pilha.empty()){ op1 = pilha.top();

pilha.pop();

}

switch (token){ case '+' : pilha.push(op1 + op2); break; case '-' : pilha.push(op1 - op2); break; '/' : if (op2 != '0') pilha.push(op1 / op2);

case

case

}

}

else exit(ER_DIV_ZERO); break; '*' : pilha.push(op1 * op2); break;

token = destino[++pos];

}

res = pilha.top(); return res;

}

int prioridade(char op1, char op2){ if (op1 == '+' || op1 == '-' && op2 == '+' || op2 == '-') return 1; else if (op1 == '+' || op1 == '-' && op2 == '*' || op2 == '/') return 0; else if (op1 == '+' || op1 == '-' && op2 == '(') return 1; else if (op1 == '(' && op2 == '+' || op2 == '-') return 0; else if (op1 == '(' && op2 == '*' || op2 == '/') return 0; else if (op1 == '(' && op2 == '(' ) return 1; else if (op1 == '*' || op1 == '/' && op2 == '+' || op2 == '-')

return 1; else if (op1 == '*' || op1 == '/' && op2 == '*' || op2 == '/') return 1; else if (op1 == '*' || op1 == '/' && op2 == '(') return 1;

}