Skip to content

Instantly share code, notes, and snippets.

@ejamesc
Created September 8, 2011 17:17
Show Gist options
  • Save ejamesc/1203972 to your computer and use it in GitHub Desktop.
Save ejamesc/1203972 to your computer and use it in GitHub Desktop.
Ugliest Interpreter Known To Man
#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