Boilerplate forth

This commit is contained in:
Tyler Perkins 2021-09-23 21:25:42 -04:00
parent c454468ffc
commit bdf69a5c1b
7 changed files with 248 additions and 7 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
#ignore all .o files
src/**/*.o
#ignore all swp files
**/*.swp
#ignore all executables, but still keep the bin folder
bin/*
!bin/.gitkeep

View File

@ -4,26 +4,25 @@
# Makefile
#
CC = g++
CC = gcc
FLAGS = -pipe
CFLAGS = -Wall
CFLAGS += -Ofast
CFLAGS += -std=c++17
#CFLAGS += -g
CFLAGS += -g
#CFLAGS += -pg
LIBRARIES =
SRC = $(shell find ./src -name '*.cpp')
OBJ = $(subst .cpp,.o,$(SRC))
SRC = $(shell find ./src -name '*.c')
OBJ = $(subst .c,.o,$(SRC))
BIN = ./bin
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
TARGET = dashboard.out
TARGET = forth
MAKEFLAGS += --jobs=4
@ -31,7 +30,7 @@ all : $(OBJ)
@echo LD $@
@$(CC) $(FLAGS) $(CFLAGS) -o $(BIN)/$(TARGET) $(OBJ) $(LIBRARIES)
.cpp.o :
.c.o :
@echo CC $<
@$(CC) $(FLAGS) $(CFLAGS) $(LIBRARIES) $(DEFINITIONS) -c $< -o $@

65
src/main.c Normal file
View File

@ -0,0 +1,65 @@
///////////////////////////////////////////////////////////////////////////////
// Tyler Perkins
// 9-23-21
// Forth compiler/interpreter
// entry point
//
#include <stdio.h>
#include <string.h>
#include "parse.h"
#include "stack.h"
#define BUFFER_SIZE 1024
void help(int argc, char** argv){
printf("Incorrect usage!\n");
printf("Usage:\n");
printf(" %s [FILE]\n", argv[0]);
printf("File is an optional forth file containing code\n");
printf("If no file is provided you will be dropped into an interactive shell\n");
printf("All operators are using reverse Polish notation\n");
printf("Max line input size is %i", BUFFER_SIZE);
}
int main(int argc, char** argv){
char input[BUFFER_SIZE] = {0};
int retval = 0;
//check arg count
if(argc > 2){
help(argc, argv);
return -1;
} else if(argc == 2){
//TODO implement File parsing
}
printf("Entering shell...\n");
//get user input, with prompt
printf("> ");
fgets(input, BUFFER_SIZE, stdin);
while(strcmp(input, "exit\n")){
retval = parse(input);
if(retval > -1){
printf(" ");
for(int i = 1; i != retval; ++i){
printf(" ");
}
printf("^\n");
printf("Error parsing character at position %d!\n", retval);
} else {
printf("%d\n", peek());
}
printf("> ");
fgets(input, BUFFER_SIZE, stdin);
}
printf("Goodbye\n");
return 0;
}

69
src/parse.c Normal file
View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// Tyler Perkins
// 9-23-21
// parse implementations
//
#include "parse.h"
char ops[] = {'+','-','*','/','\0'};
int parse(const char* input){
short int i = 0;
short int j = 0;
int ret = 0;
char buf[BUFFER_MAX_SIZE] = {'\0'};
while(input[i] != '\0'){
//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];
break;
case '-':
ret = operands[0] - operands[1];
break;
case '*':
ret = operands[0] * operands[1];
break;
case '/':
ret = operands[0] / operands[1];
break;
default:
abort();
}
push(ret);
//TODO parse as token in dictionary
} else { //Is number
ret = atoi(buf);
push(ret);
}
//clean up buf
memset(buf, '\0', j+1);
j = 0;
} else { //not whitespace
buf[j] = input[i];
++j;
}
++i;
}
return -1;
}

23
src/parse.h Normal file
View File

@ -0,0 +1,23 @@
///////////////////////////////////////////////////////////////////////////////
// Tyler Perkins
// 9-23-21
// parse definitions
//
#ifndef _PARSE_H_
#define _PARSE_H_
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "stack.h"
extern char ops[];
//parse a line
int parse(const char*);
#define BUFFER_MAX_SIZE 1024
#endif //!_PARSE_H_

48
src/stack.c Normal file
View File

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////
// Tyler Perkins
// 9-23-21
// stack implementation
//
#include "stack.h"
struct s_node* head = NULL;
unsigned int _head_error = 0;
void push(int val){
struct s_node* temp;
temp = head;
head = (struct s_node*)malloc(sizeof(struct s_node));
head->_val = val;
head->_next = temp;
}
int pop(){
struct s_node* temp;
int retval;
if(head == NULL){
_head_error = POP_EMPTY_STACK;
return 0;
}
temp = head;
head = head->_next;
retval = temp->_val;
free(temp);
return retval;
}
int peek(){
if(head == NULL){
_head_error = PEEK_EMPTY_STACK;
return 0;
}
return head->_val;
}

28
src/stack.h Normal file
View File

@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////
// Tyler Perkins
// 9-23-21
// stack definitions
//
#ifndef _STACK_H_
#define _STACK_H_
#include <stdlib.h>
struct s_node {
int _val;
struct s_node* _next;
};
extern struct s_node* head;
extern unsigned int _head_error;
#define STACK_OK 0x00
#define POP_EMPTY_STACK 0x01
#define PEEK_EMPTY_STACK 0x02
void push(int);
int pop();
int peek();
#endif //!_STACK_H_