Created
September 8, 2011 17:17
-
-
Save ejamesc/1203972 to your computer and use it in GitHub Desktop.
Ugliest Interpreter Known To Man
This file contains 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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
/* Structs */ | |
typedef struct Variable | |
{ | |
char* identifier; | |
int value; | |
struct Variable* next; | |
} Variable; | |
// Linked list declaration | |
Variable* list = NULL; | |
// Return Variable object if exists, else create and append to LL | |
Variable* lookup_vars(char* name) { | |
Variable* curr = list; | |
while(curr) { | |
if(!strcmp(name,curr->identifier)) return curr; | |
curr = curr->next; | |
} | |
// create new Variable and add to Linked List | |
curr = malloc(sizeof(Variable)); | |
curr->identifier = name; | |
curr->value = 0; | |
curr->next=list; | |
list=curr; | |
} | |
char buffer_arr[256]; | |
/* Prototypes */ | |
void eval(Variable* thisVar, char operator, Variable* var); | |
void evalnum(Variable* thisVar, char operator, int var); | |
/* Utilities */ | |
int in(const char* arr, char c){ | |
int size = strlen(arr),i; | |
for(i=0;i<size;i++) if (arr[i] == c) return 1; | |
return 0; | |
} | |
void print_values() { | |
Variable* curr = list; | |
while(curr) { | |
printf("%s=\t%d\n",curr->identifier,curr->value); | |
curr = curr->next; | |
} | |
} | |
/* transition table => [state][transition] warning: not used; I used switch statements instead */ | |
int trans[7][5] = | |
{ | |
{0,0,0,0,0}, | |
{2,0,0,0,0}, | |
{2,3,0,2,0}, | |
{0,0,4,0,0}, | |
{6,0,0,5,0}, | |
{0,0,0,5,1}, | |
{6,0,0,6,1} | |
}; | |
int main () | |
{ | |
/* Constants */ | |
const char* alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; | |
const char* numeric = "0123456789"; | |
const char* operators = "+-*/"; | |
const char* equals = "="; | |
const char* delim = ";"; | |
const char* alphabet[5] = {alpha,numeric,operators,equals,delim}; | |
/* declarations */ | |
int not_exploded = 1; | |
char input[256]; | |
int count = 0, state = 1, i; | |
int tempnumber = 0; | |
char operator; | |
Variable* thisVar; | |
Variable* tempVar; | |
// read | |
scanf("%s",input); | |
int size = strlen(input); | |
for (i=0;i<size;i++) | |
{ | |
char curr = input[i]; | |
switch (state) | |
{ | |
case 1: | |
//printf("case 1 %c\n", curr); | |
if (in(alphabet[0], curr)) | |
{ | |
buffer_arr[count] = curr; | |
count++; | |
state = 2; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
case 2: | |
//printf("case 2 %c\n", curr); | |
if (in(alphabet[0], curr) | in(alphabet[1], curr)) | |
{ | |
buffer_arr[count] = curr; | |
count++; | |
continue; | |
} else if (in(alphabet[2], curr)) { // operator | |
operator = curr; | |
// snip string and save | |
buffer_arr[count] = '\0'; | |
char* name = (char*) malloc(count + 1); | |
strcpy(name, buffer_arr); | |
lookup_vars(name); | |
// get the new variable | |
thisVar = lookup_vars(name); | |
state = 3; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
case 3: // must be equals sign next | |
//printf("case 3 %c\n", curr); | |
if (in(alphabet[3], curr)) | |
{ | |
state = 4; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
case 4: // if alpha go to 6, number goto 5 | |
//printf("case 4 %c\n", curr); | |
if (in(alphabet[0], curr)) // is alpha | |
{ | |
buffer_arr[0] = '\0';// empty the string | |
count = 0; // reset count | |
buffer_arr[count] = curr; | |
count++; | |
state = 6; | |
continue; | |
} else if (in(alphabet[1], curr)) { // is number | |
tempnumber = tempnumber * 10 + (curr - '0'); | |
state = 5; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
case 5: // case with number | |
//printf("case 5 %c\n", curr); | |
if (in(alphabet[1], curr)) { | |
tempnumber = tempnumber * 10 + (curr - '0'); | |
continue; | |
} else if (in(alphabet[4], curr)) { // end state | |
// calculate number to value of Variable | |
//printf("2ndoperator: %c\n", operator); | |
evalnum(thisVar, operator, tempnumber); | |
state = 1; | |
tempnumber = 0; | |
buffer_arr[count] = '\0'; | |
count = 0; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
case 6: // case with variable | |
//printf("case 6 %c\n", curr); | |
if (in(alphabet[0], curr) | in(alphabet[1], curr)) { | |
buffer_arr[count] = curr; | |
count++; | |
continue; | |
} else if (in(alphabet[4], curr)) { | |
state = 1; | |
// buffer_arr snip | |
buffer_arr[count] = '\0'; | |
printf("Buffer %s\n", buffer_arr); | |
lookup_vars(buffer_arr); | |
tempVar = lookup_vars(buffer_arr); | |
eval(thisVar, operator, tempVar); | |
count = 0; | |
// Set temp val and tempVar to default | |
tempnumber = 0; | |
continue; | |
} else { | |
not_exploded = 0; | |
break; | |
} | |
default: | |
not_exploded = 0; | |
break; | |
} | |
} | |
if (state!=1) not_exploded = 0; | |
if (not_exploded) { | |
printf("State machine success!\n"); | |
print_values(); | |
} | |
else { | |
printf("Syntax error detected\n"); | |
} | |
/*buffer_arr[count] = '\n'; | |
printf("Input: %s\n", input); | |
printf("Buffer: %s", buffer_arr);*/ | |
} | |
void evalnum(Variable* thisVar, char operator, int num) | |
{ | |
//printf("lol\n"); | |
switch (operator) | |
{ | |
case '+': | |
thisVar->value += num; | |
break; | |
case '-': | |
thisVar->value -= num; | |
break; | |
case '*': | |
thisVar->value *= num; | |
break; | |
case '/': | |
thisVar->value /= num; | |
break; | |
} | |
} | |
void eval(Variable* thisVar, char operator, Variable* var) | |
{ | |
switch (operator) | |
{ | |
case '+': | |
thisVar->value += var->value; | |
break; | |
case '-': | |
thisVar->value -= var->value; | |
break; | |
case '*': | |
thisVar->value *= var->value; | |
break; | |
case '/': | |
thisVar->value /= var->value; | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment