Skip to content

Instantly share code, notes, and snippets.

@shawntan
Created September 5, 2011 16:20
Show Gist options
  • Save shawntan/1195374 to your computer and use it in GitHub Desktop.
Save shawntan/1195374 to your computer and use it in GitHub Desktop.
Interpreter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Symbol linked list*/
typedef struct Symbol{
char* identifier;
int value;
struct Symbol* next;
} Symbol;
Symbol* list = NULL;
Symbol* lookup_symbols(char* varn) {
Symbol* curr = list;
while(curr) {
if(!strcmp(varn,curr->identifier)) return curr;
curr = curr->next;
}
curr = malloc(sizeof(Symbol));
curr->identifier = varn;
curr->value = 0;
curr->next=list;
list=curr;
}
void print_symbols() {
Symbol* curr = list;
while(curr) {
printf("%s=\t%d\n",curr->identifier,curr->value);
curr = curr->next;
}
}
/*end of Symbol crap*/
typedef void (*action)(char);
struct Context{
int current_state;
char buffer[256];
unsigned char buf_c;
char operator;
char* var_name;
int value;
} Context;
/*Utility methods*/
int in(char* arr, char c){
int size = strlen(arr),i;
for(i=0;i<size;i++) if (arr[i] == c) return 1;
return 0;
}
void clear_buffer(){
Context.buffer[Context.buf_c] = '\0';
Context.buf_c=0;
}
void eval() {
Symbol* variable = lookup_symbols(Context.var_name);
switch(Context.operator) {
case '+': variable->value+=Context.value;break;
case '*': variable->value*=Context.value;break;
case '/': variable->value/=Context.value;break;
case '-': variable->value-=Context.value;break;
}
}
/*end*/
/*State transition methods*/
void write_buf(char a){
Context.buffer[Context.buf_c]=a;
Context.buf_c++;
}
void clear_push_to_table(char a){
clear_buffer();
Context.var_name = (char*) malloc(strlen((Context.buffer))+1);
strcpy(Context.var_name,Context.buffer);
Context.operator = a;
}
void clear_push_to_int(char a) {
clear_buffer();
Context.value = atoi(Context.buffer);
eval();
}
void clear_push_lookup_table(char a) {
clear_buffer();
Context.value = lookup_symbols(Context.buffer)->value;
eval();
}
void noop(char a){}
void explode(char a){
printf("Explode!\n");
exit(1);
}
/*state transition methods*/
const unsigned int STATES = 6;
const unsigned int ALPHABET = 5;
action** fun;
unsigned int** delta;
char** alphabet;
void construct_dfa() {
unsigned int i=0;
unsigned int alpha,num,op,delim,eq;
alphabet = (char**)malloc(ALPHABET*(sizeof alphabet));
alphabet[alpha=i++]="_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
alphabet[num=i++]="0123456789";
alphabet[op=i++]="+-*/";
alphabet[delim=i++]=";";
alphabet[eq=i++]="=";
delta = malloc((STATES+1)*(sizeof delta));
fun = malloc((STATES+1)*(sizeof fun));
unsigned int d=ALPHABET*(sizeof(*delta));
unsigned int f=ALPHABET*(sizeof(*fun));
for(i=0;i<STATES+1;i++) {
delta[i] = memset(malloc(d),0,d);
fun[i] = malloc(f);
int j=0;
for(j=0;j<ALPHABET;j++) fun[i][j] = explode;
}
delta[1][alpha] = delta[2][alpha] = delta[2][num] = 2;
delta[2][op] = 3;
delta[3][eq] = 4;
delta[4][num] = delta[5][num] = 5;
delta[4][alpha] = delta[6][alpha] = delta[6][num] = 6;
delta[5][delim] = delta[6][delim] = 1;
fun[1][alpha] = fun[2][alpha] = fun[2][num] = write_buf;
fun[2][op] = clear_push_to_table;
fun[3][eq] = noop;
fun[4][alpha] = fun[4][num] = fun[5][num] = fun[6][alpha] = fun[6][num] = write_buf;
fun[5][delim] = clear_push_to_int;
fun[6][delim] = clear_push_lookup_table;
}
int main() {
construct_dfa();
Context.current_state = 1;
while(1) {
char t = fgetc(stdin);
if(t=='\n') break;
int i=0;
while(i<ALPHABET && !in(alphabet[i],t)) i++;
printf("%d -'%c'-> %d\n",Context.current_state,t,delta[Context.current_state][i]);
(*(fun[Context.current_state][i]))(t);
Context.current_state = delta[Context.current_state][i];
}
print_symbols();
int i;
int j;
for(i=0;i<6;i++) {
for(j=0;j<5;j++) printf(" %d",delta[i][j]);
printf("\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment