Add bitshift and file support

This commit is contained in:
Tyler Perkins 2021-09-23 22:21:44 -04:00
parent bdf69a5c1b
commit dbf68f5da5
4 changed files with 161 additions and 23 deletions

View File

@ -3,10 +3,29 @@ Forth
A weekend implementation of the Forth programming language A weekend implementation of the Forth programming language
Usage Compile
===== =====
``` ```
make all make all
make clean make clean
``` ```
How to use
==========
These are the currently accepted operators:
+ add
- substract
* multiply
/ divide
. print top of stack
< bit shift left
> bit shift right

View File

@ -23,27 +23,56 @@ void help(int argc, char** argv){
printf("Max line input size is %i", BUFFER_SIZE); printf("Max line input size is %i", BUFFER_SIZE);
} }
void process_file(FILE* in, char* input){
char* fg;
int retval;
while(!(fg = fgets(input, BUFFER_SIZE, in)) || feof(in)){
retval = parse(input);
if(retval > -1){
printf("%s\n ",input);
for(int i = 1; i != retval; ++i){
printf(" ");
}
printf("^\n");
printf("Error parsing character at position %d!\n", retval);
break;
}
}
}
int main(int argc, char** argv){ int main(int argc, char** argv){
char input[BUFFER_SIZE] = {0}; char input[BUFFER_SIZE] = {0};
int retval = 0; int retval = 0;
FILE* in = stdin;
char* fg;
//check arg count //check arg count
if(argc > 2){ if(argc > 2){
help(argc, argv); help(argc, argv);
return -1; return -1;
} else if(argc == 2){ } else if(argc == 2){
//TODO implement File parsing in = fopen(argv[1], "r");
if(in == NULL){
printf("Couldn't open file %s\n", argv[1]);
in = stdin;
}
} }
if(in != stdin){
process_file(in, input);
}
printf("Entering shell...\n"); printf("Entering shell...\n");
//get user input, with prompt //get user input, with prompt
printf("> "); printf("> ");
fgets(input, BUFFER_SIZE, stdin); fg = fgets(input, BUFFER_SIZE, in);
while(strcmp(input, "exit\n")){ while(strcmp(input, "exit\n")){
if(fg == NULL) //ctrl+d
break;
retval = parse(input); retval = parse(input);
if(retval > -1){ if(retval > -1){
printf(" "); printf(" ");
@ -57,7 +86,7 @@ int main(int argc, char** argv){
} }
printf("> "); printf("> ");
fgets(input, BUFFER_SIZE, stdin); fg = fgets(input, BUFFER_SIZE, in);
} }
printf("Goodbye\n"); printf("Goodbye\n");

View File

@ -6,7 +6,89 @@
#include "parse.h" #include "parse.h"
char ops[] = {'+','-','*','/','\0'}; char ops[] = {'+','-','*','/','.','<','>','\0'};
int op_add(){
int ret = 0;
for(int it = 0;it < 2; ++it){
ret += pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
}
push(ret);
return 0;
}
int op_sub(){
int op[2];
for(int it = 0;it < 2; ++it){
op[it] = pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
}
push(op[1] - op[0]);
return 0;
}
int op_mul(){
int ret = 1;
for(int it = 0;it < 2; ++it){
ret *= pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
}
push(ret);
return 0;
}
int op_div(){
int op[2];
for(int it = 0;it < 2; ++it){
op[it] = pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
}
push(op[1]/op[0]);
return 0;
}
int op_pri(){
printf("%d\n", peek());
if(_head_error == PEEK_EMPTY_STACK){
return -1;
}
return 0;
}
int op_right(){
int ret = pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
ret = ret >> 1;
push(ret);
return 0;
}
int op_left(){
int ret = pop();
if(_head_error == POP_EMPTY_STACK){
return -1;
}
ret = ret << 1;
push(ret);
return 0;
}
int parse(const char* input){ int parse(const char* input){
short int i = 0; short int i = 0;
@ -18,35 +100,35 @@ int parse(const char* input){
//collect it into a temporary buffer //collect it into a temporary buffer
if(input[i] == ' ' || input[i] == '\n' || input[i] == '\t'){ if(input[i] == ' ' || input[i] == '\n' || input[i] == '\t'){
if(j == 1 && (strstr(ops,buf) != NULL)){ //if single operator if(j == 1 && (strstr(ops,buf) != NULL)){ //if single operator
int operands[2] = {0};
for(int it = 0;it < 2; ++it){
operands[it] = pop();
if(_head_error == POP_EMPTY_STACK){
printf("Not enough elements on stack!\n");
return i;
}
}
//apply operator //apply operator
switch(buf[0]){ switch(buf[0]){
case '+': case '+':
ret = operands[0] + operands[1]; ret = op_add();
break; break;
case '-': case '-':
ret = operands[0] - operands[1]; ret = op_sub();
break; break;
case '*': case '*':
ret = operands[0] * operands[1]; ret = op_mul();
break; break;
case '/': case '/':
ret = operands[0] / operands[1]; ret = op_div();
break;
case '.':
ret = op_pri();
break;
case '<':
ret = op_left();
break;
case '>':
ret = op_right();
break; break;
default: default:
abort();
} }
push(ret); if(ret == -1){
return i;
}
//TODO parse as token in dictionary //TODO parse as token in dictionary
} else { //Is number } else { //Is number
ret = atoi(buf); ret = atoi(buf);

View File

@ -18,6 +18,14 @@ extern char ops[];
//parse a line //parse a line
int parse(const char*); int parse(const char*);
int op_add();
int op_sub();
int op_mul();
int op_div();
int op_pri();
int op_right();
int op_left();
#define BUFFER_MAX_SIZE 1024 #define BUFFER_MAX_SIZE 1024
#endif //!_PARSE_H_ #endif //!_PARSE_H_