Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ctype.h> //isspace
- #include <math.h> //pow
- #include <stdio.h>
- #include <stdlib.h> //NULL EOF
- // Token types
- enum tokens {
- ADD, SUB, MUL, DIV, MOD, POW,
- OBR, CBR,
- VAL, NON,
- ERR, NEXT,
- EXP
- // More later
- };
- //Token data structure
- typedef struct token {
- //enum tokens type; if doesn't work
- tokens type;
- double value; //item to save the value
- } Token;
- //Scanner states
- enum states{
- INIT,
- ZERO,
- DOT,
- FRACT,
- EXPO,
- PRESHIFT,
- SHIFT
- };
- // SCANNER (LEXICAL ANALYZER)
- Token scanner() {
- Token token = { NON, 0 };
- states state = INIT;
- int c;
- static int last = EOF; //indicator that there was any remember symbol
- if(last != EOF && !isspace(last))
- c = last;
- else
- while(isspace(c = getchar())); //We will skip all the white space characters
- last = EOF;
- switch(c){
- case '+':
- token.type = ADD;
- return token;
- case '-':
- token.type = SUB;
- return token;
- case '*':
- token.type = MUL;
- return token;
- case '/':
- token.type = DIV;
- return token;
- case '%':
- token.type = MOD;
- return token;
- case '^':
- token.type = POW;
- return token;
- case '(':
- token.type = OBR;
- return token;
- case ')':
- token.type = CBR;
- return token;
- case EOF:
- return token;
- default:
- if(isdigit(c))
- break;
- token.type = ERR;
- return token;
- }
- token.type = VAL;
- token.value += c - '0'; //variable that Host the character that host the number
- double fractional = 1;
- int exponential=0;
- int sign = 0;
- for(;;){
- c = getchar();
- switch(state){
- case INIT:
- if(isdigit(c))
- token.value = token.value *10 + c - '0'; //order of our numerical decimal base
- else
- {
- if(c == '.')
- state = DOT;
- else if(c=='e' || c=='E') //EXPONENTIAL PART
- state=EXPO;
- else
- {
- last = c;
- return token;
- }
- }
- break;
- case DOT:
- if(!isdigit(c))
- {
- token.type = ERR;
- return token;
- }
- fractional /= 10;
- token.value += fractional * (c - '0');
- state = FRACT;
- break;
- case FRACT:
- if(isdigit(c))
- {
- fractional /= 10;
- token.value += fractional * (c - '0');
- }else
- //Exponential TODO
- if(c == 'e' || 'E')
- state = EXPO;
- else
- {
- last = c;
- return token;
- }
- break;
- //case TODO after the Exponential part
- case EXPO:
- if(!isdigit(c))
- {
- if(c=='-'){
- if(isdigit(c=getchar())){
- do{
- exponential = exponential*10 + c - '0';
- exponential*=1;
- }while(isdigit(c=getchar()));
- token.value=pow(token.value,exponential);
- return token;
- }
- }
- token.type=ERR;
- return token;
- }
- else{
- do{
- exponential = exponential*10 + c - '0';
- }while(isdigit(c=getchar()));
- token.value=pow(token.value,exponential);
- return token;
- }
- break;
- }//chiusura switch
- }
- return token;
- }
- //pushdown
- typedef struct pushdown Stack;
- struct pushdown{
- Token token;
- Stack *next;
- };
- Stack *pop(Stack *stack){
- if(stack != NULL)
- {
- Stack *tmp = stack->next;
- free(stack);
- stack = tmp;
- }
- return stack;
- }
- void freeStack(Stack *stack){
- while(stack != NULL)
- stack = pop(stack);
- }
- Stack *push(Stack *stack, Token token){
- Stack *tmp;
- if((tmp = (Stack *)malloc(sizeof(Stack))) == NULL)
- {
- freeStack(stack);
- return NULL;
- }
- tmp->token = token;
- tmp->next = stack;
- return tmp;
- }
- /*void printStack(Stack *stack){
- if(stack != NULL){
- if(stack->token.type == VAL || stack->token.type == EXP)
- printf("-[%d|%g]", stack->token.type, stack->token.value);
- printStack(stack->next);
- }
- else
- printf("\n");
- }
- */
- //Top most terminal
- tokens topTerminal(Stack *stack){
- for(; stack != NULL; stack = stack->next)
- if(stack->token.type != EXP){
- return stack->token.type;
- }
- return ERR; //Fatal Error
- }
- //Table values
- enum table { L,G,E,B,A};
- //Precedence Table
- static table precTable[10][10] = {
- // + - * / % ^ ( ) N $
- /* + */ { G, L, L, L, L, L, L, G, L, G },
- /* - */ { G, L, L, L, L, L, L, G, L, G },
- /* * */ { G, L, G, G, G, L, L, G, L, G },
- /* / */ { G, L, G, G, G, L, L, G, L, G },
- /* % */ { G, L, G, G, G, L, L, G, L, G },
- /* ^ */ { G, L, G, G, G, L, L, G, L, G },
- /* ( */ { L, L, L, L, L, L, L, E, L, B },
- /* ) */ { G, G, G, G, G, G, B, G, B, G },
- /* N */ { G, G, G, G, G, G, B, G, B, G },
- /* $ */ { L, L, L, L, L, L, L, B, L, A },
- };
- int main(){
- double value;
- Token token = {NON , 0}; //end marker
- Stack *stack = NULL;
- if((stack = push(stack, token)) == NULL)
- goto mallocError;
- token.type = NEXT;
- // Parser Loop
- for(;;){
- if(token.type == NEXT)
- token = scanner();
- if(token.type == ERR)
- goto lexicalError;
- switch(precTable[topTerminal(stack)][token.type]){
- case L:
- if((stack = push(stack, token))==NULL)
- goto mallocError;
- token.type = NEXT;
- break;
- case E:
- Stack *tmp;
- if((tmp = push(stack, token))==NULL)
- goto mallocError;
- token.type = NEXT;
- stack = tmp;
- break;
- case G:
- switch(topTerminal(stack)){
- case ADD: //E->E + E
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack -> token.value;
- stack = pop(stack);
- if(stack->token.type != ADD)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- stack->token.value += value;
- continue;
- case SUB: //E->E - E | E-> -E
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack->token.value;
- stack = pop(stack);
- if(stack->token.type != SUB)
- goto syntaxError;
- if(stack->next->token.type == EXP)
- {
- stack = pop(stack);
- stack->token.value -= value;
- }
- else
- stack->token.value -= value;
- stack->token.type = EXP;
- continue;
- case MUL: //E->E * E
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack -> token.value;
- stack = pop(stack);
- if(stack->token.type != MUL)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- stack->token.value *= value;
- continue;
- case DIV:
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack->token.value;
- stack = pop(stack);
- if(stack->token.type != DIV)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- stack->token.value /= value;
- continue;
- case MOD:
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack->token.value;
- stack = pop(stack);
- if(stack->token.type != MOD)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- stack->token.value = fmod(stack->token.value, value);
- continue;
- case POW: // E^E
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack->token.value;
- stack = pop(stack);
- if(stack->token.type != POW)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- stack->token.value = pow(stack->token.value, value);
- continue;
- case CBR:
- if(stack->token.type != CBR)
- goto syntaxError;
- stack = pop(stack);
- if(stack->token.type != EXP)
- goto syntaxError;
- value = stack->token.value;
- stack = pop(stack);
- if(stack->token.type != OBR)
- goto syntaxError;
- stack->token.value = value;
- stack->token.type = EXP;
- continue;
- case VAL: //E -> n rules on the notebook near the operand table
- if(stack->token.type != VAL)
- goto syntaxError;
- stack->token.type = EXP;
- continue;
- }
- case B:
- goto syntaxError;
- case A:
- if(stack->token.type == EXP)
- printf("%g\n", stack->token.value);
- freeStack(stack);
- return 0;
- default:
- goto fatalError;
- }
- }
- mallocError:
- perror("malloc error");
- return 4;
- lexicalError:
- fprintf(stderr, "Lexical error\n");
- freeStack(stack);
- return 3;
- syntaxError:
- fprintf(stderr, "Syntax error\n");
- freeStack(stack);
- return 2;
- fatalError:
- fprintf(stderr, "Fatal error\n");
- freeStack(stack);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement