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
|
||||
|
||||
Usage
|
||||
Compile
|
||||
=====
|
||||
|
||||
```
|
||||
make all
|
||||
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
|
||||
|
39
src/main.c
39
src/main.c
@ -23,30 +23,59 @@ void help(int argc, char** argv){
|
||||
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){
|
||||
char input[BUFFER_SIZE] = {0};
|
||||
int retval = 0;
|
||||
|
||||
FILE* in = stdin;
|
||||
char* fg;
|
||||
|
||||
//check arg count
|
||||
if(argc > 2){
|
||||
help(argc, argv);
|
||||
return -1;
|
||||
} 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");
|
||||
|
||||
//get user input, with prompt
|
||||
printf("> ");
|
||||
fgets(input, BUFFER_SIZE, stdin);
|
||||
fg = fgets(input, BUFFER_SIZE, in);
|
||||
|
||||
while(strcmp(input, "exit\n")){
|
||||
if(fg == NULL) //ctrl+d
|
||||
break;
|
||||
|
||||
|
||||
retval = parse(input);
|
||||
if(retval > -1){
|
||||
printf(" ");
|
||||
printf(" ");
|
||||
for(int i = 1; i != retval; ++i){
|
||||
printf(" ");
|
||||
}
|
||||
@ -57,7 +86,7 @@ int main(int argc, char** argv){
|
||||
}
|
||||
|
||||
printf("> ");
|
||||
fgets(input, BUFFER_SIZE, stdin);
|
||||
fg = fgets(input, BUFFER_SIZE, in);
|
||||
}
|
||||
|
||||
printf("Goodbye\n");
|
||||
|
116
src/parse.c
116
src/parse.c
@ -6,7 +6,89 @@
|
||||
|
||||
#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){
|
||||
short int i = 0;
|
||||
@ -18,35 +100,35 @@ int parse(const char* input){
|
||||
//collect it into a temporary buffer
|
||||
if(input[i] == ' ' || input[i] == '\n' || input[i] == '\t'){
|
||||
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
|
||||
switch(buf[0]){
|
||||
case '+':
|
||||
ret = operands[0] + operands[1];
|
||||
ret = op_add();
|
||||
break;
|
||||
case '-':
|
||||
ret = operands[0] - operands[1];
|
||||
ret = op_sub();
|
||||
break;
|
||||
case '*':
|
||||
ret = operands[0] * operands[1];
|
||||
ret = op_mul();
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
push(ret);
|
||||
if(ret == -1){
|
||||
return i;
|
||||
}
|
||||
//TODO parse as token in dictionary
|
||||
} else { //Is number
|
||||
ret = atoi(buf);
|
||||
|
@ -18,6 +18,14 @@ extern char ops[];
|
||||
//parse a line
|
||||
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
|
||||
|
||||
#endif //!_PARSE_H_
|
||||
|
Loading…
Reference in New Issue
Block a user