Add bitshift and file support
This commit is contained in:
parent
bdf69a5c1b
commit
dbf68f5da5
21
README.md
21
README.md
@ -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
|
||||||
|
37
src/main.c
37
src/main.c
@ -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");
|
||||||
|
116
src/parse.c
116
src/parse.c
@ -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);
|
||||||
|
@ -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_
|
||||||
|
Loading…
Reference in New Issue
Block a user