void prints(char *); void printd(int); void inputs(char *, int); int inputd(); void *malloc(int); int INT_TOKEN; int STR_TOKEN; int VAR_TOKEN; int SUBSTRING; int STRFUNC; int PLUS; int MINUS; int MULTIPLY; int DIVIDE; int EQUALS; int GREATER_THAN; int LESS_THAN; int NOT_EQUALS; int AND; int OR; //Variable types int INTVAR; int STRVAR; int PRINT; int INPUT; int INPUTSTR; int RUN; int END; int IF; int WHILE; int LET; int DIM; int GOSUB; int GOTO; int RETURN; int LIST; int error; void init_tokens(){ INT_TOKEN = 1; STR_TOKEN = 2; SUBSTRING = 3; STRFUNC = 4; PLUS = 5; MINUS = 6; MULTIPLY = 7; DIVIDE = 8; EQUALS = 9; GREATER_THAN = 10; LESS_THAN = 11; NOT_EQUALS = 12; AND = 13; OR = 14; VAR_TOKEN = 15; INTVAR = 0; STRVAR = 1; PRINT = 1; INPUT = 2; INPUTSTR = 3; RUN = 4; END = 5; IF = 6; WHILE = 7; DIM = 8; GOSUB = 9; GOTO = 10; RETURN = 11; LIST = 12; } int alpha(char c){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } int digit(char c){ return c >= '0' && c <= '9'; } void skip_whitespace(char **c){ while(**c && (**c == ' ' || **c == '\t' || **c == '\n')) *c = *c + 1; } int strcmp(char *a, char *b){ while(*a && *a == *b){ a = a + 1; b = b + 1; } return *b - *a; } void *create_variable(int type, void *values, int num_elements){ void **output; output = kmalloc(POINTER_SIZE*3); output[0] = (void *) type; output[1] = values; output[2] = (void *) num_elements; return output; } void get_word(char *buffer, char **c, int buffer_length){ skip_whitespace(c); while(buffer_length && (alpha(**c) || digit(**c) || **c == '_')){ *buffer = **c; buffer = buffer + 1; *c = *c + 1; buffer_length = buffer_length - 1; } if(!buffer_length) buffer = buffer - 1; *buffer = 0; } int order_of_operations(int token_type){ if(token_type == PLUS || token_type == MINUS){ return 4; } else if(token_type == MULTIPLY || token_type == DIVIDE){ return 5; } else if(token_type == EQUALS || token_type == GREATER_THAN || token_type == LESS_THAN){ return 3; } else if(token_type == AND){ return 2; } else if(token_type == OR){ return 1; } return 0; } void *create_token(int type, void *value1, void *value2){ void *output; output = kmalloc(POINTER_SIZE*3); ((int *) output)[0] = type; ((void **) output)[1] = value1; ((void **) output)[2] = value2; return output; } int get_int(char **c){ int invert; int output; if(**c == '-'){ invert = 1; *c = *c + 1; } else { invert = 0; } output = 0; while(**c >= '0' && **c <= '9'){ output = output*10 + **c - '0'; *c = *c + 1; } if(invert) output = -output; return output; } char *get_str(char **c){ int str_len; char *temp; char *output; str_len = 0; temp = *c; while(*temp && *temp != '"'){ str_len = str_len + 1; temp = temp + 1; } output = kmalloc(CHAR_SIZE*(str_len + 1)); temp = output; while(**c && **c != '"'){ *temp = **c; *c = *c + 1; temp = temp + 1; } *temp = 0; return output; } void *get_expression(char **c); void free_expression(void *); void *get_var(char **c){ char *buffer; void *index; buffer = kmalloc(32); get_word(buffer, c, 32); skip_whitespace(c); if(**c == '['){ *c = *c + 1; index = get_expression(c); if(**c == ']') *c = *c + 1; } else { index = (void *) 0; } return create_token(VAR_TOKEN, buffer, index); } void *get_function(char **c, int *err){ char buffer[32]; char *temp; void *arg1; void *arg2; void *arg3; void **output; *err = 0; temp = *c; get_word(buffer, &temp, 32); if(!strcmp(buffer, "SUBSTR")){ *c = temp; skip_whitespace(c); if(**c == '('){ *c = *c + 1; } else { return (void *) 0; } arg1 = get_expression(c); if(**c == ',' && (int) arg1){ *c = *c + 1; } else { if((int) arg1) free_expression(arg1); *err = 1; return (void *) 0; } arg2 = get_expression(c); if(**c == ',' && (int) arg2){ *c = *c + 1; } else { free_expression(arg1); if(arg2) free_expression(arg2); *err = 1; return (void *) 0; } arg3 = get_expression(c); if(**c == ')' && (int) arg3){ *c = *c + 1; } else { free_expression(arg1); free_expression(arg2); if((int) arg3) free_expression(arg3); *err = 1; return (void *) 0; } output = kmalloc(POINTER_SIZE*4); output[0] = (void *) SUBSTRING; output[1] = arg1; output[2] = arg2; output[3] = arg3; return output; } else if(!strcmp(buffer, "STR")){ *c = temp; skip_whitespace(c); if(**c == '('){ *c = *c + 1; } else { return (void *) 0; } arg1 = get_expression(c); if(**c == ')' && (int) arg1){ *c = *c + 1; } else { if((int) arg1) free_expression(arg1); *err = 1; return (void *) 0; } output = kmalloc(POINTER_SIZE*2); output[0] = (void *) STRFUNC; output[1] = arg1; return output; } else { return (void *) 0; } } void *get_value(char **c){ char *str; void *output; int err; skip_whitespace(c); if(**c == '-' || (**c >= '0' && **c <= '9')){ return create_token(INT_TOKEN, (void *) get_int(c), (void *) 0); } else if(**c == '('){ *c = *c + 1; output = get_expression(c); if(**c == ')') *c = *c + 1; return output; } else if(alpha(**c)){ output = get_function(c, &err); if(err) return (void *) 0; if(!output) return get_var(c); return output; } else if(**c == '"'){ *c = *c + 1; str = get_str(c); if(**c == '"') *c = *c + 1; return create_token(STR_TOKEN, str, (void *) 0); } return (void *) 0; } int get_operation(char **c){ skip_whitespace(c); if(**c == '+'){ *c = *c + 1; return PLUS; } else if(**c == '-'){ *c = *c + 1; return MINUS; } else if(**c == '*'){ *c = *c + 1; return MULTIPLY; } else if(**c == '/'){ *c = *c + 1; return DIVIDE; } else if(**c == '='){ *c = *c + 1; return EQUALS; } else if(**c == '>'){ *c = *c + 1; return GREATER_THAN; } else if(**c == '<'){ *c = *c + 1; return LESS_THAN; } else if(**c == '!' && *(*c + 1) == '='){ *c = *c + 2; return NOT_EQUALS; } else if(**c == '&'){ *c = *c + 1; return AND; } else if(**c == '|'){ *c = *c + 1; return OR; } return 0; } void *get_expression_recursive(void *output, char **c){ void *value; int current_operation; int next_operation; char *temp; while(current_operation = get_operation(c)){ value = get_value(c); if(!(int) value){ free_expression(output); return (void *) 0; } temp = *c; next_operation = get_operation(&temp); if(order_of_operations(next_operation) > order_of_operations(current_operation)){ value = get_expression_recursive(value, c); } if((int) value){ output = create_token(current_operation, output, value); } else { free_expression(output); return (void *) 0; } } return output; } void *get_expression(char **c){ void *value; value = get_value(c); if(!(int) value){ return (void *) 0; } return get_expression_recursive(value, c); } void free_expression(void *expr){ if(((int *) expr)[0] == INT_TOKEN){ kfree(expr); } else if(((int *) expr)[0] == STR_TOKEN){ kfree(((void **) expr)[1]); kfree(expr); } else if(((int *) expr)[0] == VAR_TOKEN){ if((int) ((void **) expr)[2]) free_expression(((void **) expr)[2]); kfree(((void **) expr)[1]); kfree(expr); } else if(((int *) expr)[0] == PLUS || ((int *) expr)[0] == MINUS || ((int *) expr)[0] == MULTIPLY || ((int *) expr)[0] == DIVIDE || ((int *) expr)[0] == EQUALS || ((int *) expr)[0] == NOT_EQUALS || ((int *) expr)[0] == GREATER_THAN || ((int *) expr)[0] == LESS_THAN || ((int *) expr)[0] == AND || ((int *) expr)[0] == OR){ free_expression(((void **) expr)[1]); free_expression(((void **) expr)[2]); kfree(expr); } else if(((int *) expr)[0] == SUBSTRING){ free_expression(((void **) expr)[1]); free_expression(((void **) expr)[2]); free_expression(((void **) expr)[3]); kfree(expr); } else if(((int *) expr)[0] == STRFUNC){ free_expression(((void **) expr)[1]); kfree(expr); } } void list_expression(void *expr){ if(((int *) expr)[0] == INT_TOKEN){ printd(((int *) expr)[1]); } else if(((int *) expr)[0] == STR_TOKEN){ prints("\""); prints(((char **) expr)[1]); prints("\""); } else if(((int *) expr)[0] == VAR_TOKEN){ prints(((char **) expr)[1]); if(((void **) expr)[2]){ prints("["); list_expression(((void **) expr)[2]); prints("]"); } } else if(((int *) expr)[0] == PLUS){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" + ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == MINUS){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" - ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == MULTIPLY){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" * ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == DIVIDE){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" / ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == EQUALS){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" = ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == NOT_EQUALS){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" != ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == GREATER_THAN){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" > ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == LESS_THAN){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" < ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == AND){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" & ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == OR){ prints("("); list_expression(((void **) expr)[1]); prints(")"); prints(" | ("); list_expression(((void **) expr)[2]); prints(")"); } else if(((int *) expr)[0] == SUBSTRING){ prints("SUBSTR("); list_expression(((void **) expr)[1]); prints(", "); list_expression(((void **) expr)[2]); prints(", "); list_expression(((void **) expr)[3]); prints(")"); } else if(((int *) expr)[0] == STRFUNC){ prints("STR("); list_expression(((void **) expr)[1]); prints(")"); } } void **parse_print(char **c){ void **output; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) PRINT; output[1] = get_expression(c); skip_whitespace(c); if(!(int) output[1]){ kfree(output); return (void **) 0; } else if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_print(void **statement){ prints("PRINT "); list_expression(statement[1]); } void **parse_input(char **c){ void **output; skip_whitespace(c); if(!alpha(**c)) return (void **) 0; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) INPUT; output[1] = get_var(c); skip_whitespace(c); if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_input(void **statement){ prints("INPUT "); list_expression(statement[1]); } void **parse_inputstr(char **c){ void **output; skip_whitespace(c); if(!alpha(**c)) return (void **) 0; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) INPUTSTR; output[1] = get_var(c); skip_whitespace(c); if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_inputstr(void **statement){ prints("INPUTSTR "); list_expression(statement[1]); } void **parse_let(char **c){ void **output; skip_whitespace(c); if(!alpha(**c)) return (void **) 0; output = kmalloc(POINTER_SIZE*3); output[0] = (void *) LET; output[1] = get_var(c); skip_whitespace(c); if(**c != '='){ free_expression(output[1]); kfree(output); return (void **) 0; } *c = *c + 1; skip_whitespace(c); output[2] = get_expression(c); if(**c || !(int) output[2]){ free_expression(output[1]); if((int) output[2]) free_expression(output[2]); kfree(output); return (void **) 0; } return output; } void list_let(void **statement){ prints("LET "); list_expression(statement[1]); prints(" = "); list_expression(statement[2]); } void **parse_dim(char **c){ void **output; skip_whitespace(c); if(!alpha(**c)) return (void **) 0; output = kmalloc(POINTER_SIZE*3); output[0] = (void *) DIM; output[1] = get_var(c); skip_whitespace(c); if(**c != ','){ free_expression(output[1]); kfree(output); return (void **) 0; } *c = *c + 1; skip_whitespace(c); output[2] = get_expression(c); skip_whitespace(c); if(**c || !(int) output[2]){ free_expression(output[1]); if((int) output[2]) free_expression(output[2]); kfree(output); return (void **) 0; } return output; } void list_dim(void **statement){ prints("DIM "); list_expression(statement[1]); prints(", "); list_expression(statement[2]); } void **parse_if(char **c){ void **output; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) IF; output[1] = get_expression(c); skip_whitespace(c); if(!(int) output[1]){ kfree(output); return (void **) 0; } else if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_if(void **statement){ prints("IF "); list_expression(statement[1]); } void **parse_goto(char **c){ void **output; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) GOTO; output[1] = get_expression(c); skip_whitespace(c); if(!(int) output[1]){ kfree(output); return (void **) 0; } else if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_goto(void **statement){ prints("GOTO "); list_expression(statement[1]); } void **parse_gosub(char **c){ void **output; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) GOSUB; output[1] = get_expression(c); skip_whitespace(c); if(!(int) output[1]){ kfree(output); return (void **) 0; } else if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_gosub(void **statement){ prints("GOSUB "); list_expression(statement[1]); } void **parse_while(char **c){ void **output; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) WHILE; output[1] = get_expression(c); skip_whitespace(c); if(!(int) output[1]){ kfree(output); return (void **) 0; } else if(**c){ free_expression(output[1]); kfree(output); return (void **) 0; } return output; } void list_while(void **statement){ prints("WHILE "); list_expression(statement[1]); } void **parse_run(char **c){ void **output; skip_whitespace(c); if(**c) return (void **) 0; output = kmalloc(POINTER_SIZE); output[0] = (void *) RUN; return output; } void list_run(void **statement){ prints("RUN"); } void **parse_end(char **c){ void **output; char buffer[32]; skip_whitespace(c); if(!**c){ output = kmalloc(POINTER_SIZE*2); output[0] = (void *) END; output[1] = (void *) 0; return output; } get_word(buffer, c, 32); skip_whitespace(c); if(**c) return (void **) 0; output = kmalloc(POINTER_SIZE*2); output[0] = (void *) END; if(!strcmp(buffer, "IF")) output[1] = (void *) IF; else if(!strcmp(buffer, "WHILE")) output[1] = (void *) WHILE; else { kfree(output); return (void **) 0; } return output; } void list_end(void **statement){ if(statement[1] == (void *) IF){ prints("END IF"); } else if(statement[1] == (void *) WHILE){ prints("END WHILE"); } else { prints("END"); } } void **parse_return(char **c){ void **output; skip_whitespace(c); if(!**c){ output = kmalloc(POINTER_SIZE); output[0] = (void *) RETURN; return output; } return (void **) 0; } void list_return(void **statement){ prints("RETURN"); } void **parse_list(char **c){ void **output; skip_whitespace(c); if(!**c){ output = kmalloc(POINTER_SIZE); output[0] = (void *) LIST; return output; } return (void **) 0; } void list_list(void **statement){ prints("LIST"); } void **get_statement(char **c){ char buffer[32]; get_word(buffer, c, 32); if(!strcmp(buffer, "PRINT")) return parse_print(c); else if(!strcmp(buffer, "INPUT")) return parse_input(c); else if(!strcmp(buffer, "INPUTSTR")) return parse_inputstr(c); else if(!strcmp(buffer, "RUN")) return parse_run(c); else if(!strcmp(buffer, "END")) return parse_end(c); else if(!strcmp(buffer, "IF")) return parse_if(c); else if(!strcmp(buffer, "WHILE")) return parse_while(c); else if(!strcmp(buffer, "LET")) return parse_let(c); else if(!strcmp(buffer, "DIM")) return parse_dim(c); else if(!strcmp(buffer, "GOTO")) return parse_goto(c); else if(!strcmp(buffer, "GOSUB")) return parse_gosub(c); else if(!strcmp(buffer, "RETURN")) return parse_return(c); else if(!strcmp(buffer, "LIST")) return parse_list(c); else return (void **) 0; } void free_statement(void **statement){ if((int) statement[0] == PRINT){ free_expression(statement[1]); kfree(statement); } else if((int) statement[0] == INPUT){ if(((int *) statement[1])[2]) free_expression(((void **) statement[1])[2]); kfree(((void **) statement[1])[1]); kfree(statement[1]); kfree(statement); } else if((int) statement[0] == RUN){ kfree(statement); } else if((int) statement[0] == END){ kfree(statement); } else if((int) statement[0] == IF){ free_expression(statement[1]); kfree(statement); } else if((int) statement[0] == WHILE){ free_expression(statement[1]); kfree(statement); } else if((int) statement[0] == LET){ free_expression(statement[1]); free_expression(statement[2]); kfree(statement); } else if((int) statement[0] == DIM){ free_expression(statement[1]); free_expression(statement[2]); kfree(statement); } else if((int) statement[0] == GOTO){ free_expression(statement[1]); kfree(statement); } else if((int) statement[0] == GOSUB){ free_expression(statement[1]); kfree(statement); } else if((int) statement[0] == LIST){ kfree(statement); } }