Init
This commit is contained in:
commit
2a9968c4ce
8 changed files with 302 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.22.1)
|
||||||
|
|
||||||
|
project(hydroforth)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.c)
|
||||||
|
add_executable(hydroforth ${SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(hydroforth PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
59
include/hydroforth/hydroforth.h
Normal file
59
include/hydroforth/hydroforth.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef __HYDROFORTH_H__
|
||||||
|
#define __HYDROFORTH_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "number.h"
|
||||||
|
|
||||||
|
typedef enum HYDROFORTH__WORD_TYPE
|
||||||
|
{
|
||||||
|
PUSH,
|
||||||
|
CHAR_WORD,
|
||||||
|
WORD,
|
||||||
|
} HYDROFORTH__WORD_TYPE;
|
||||||
|
|
||||||
|
typedef union HYDROFORTH__WORD_DATA
|
||||||
|
{
|
||||||
|
int number;
|
||||||
|
char char_word;
|
||||||
|
char *word;
|
||||||
|
} HYDROFORTH__WORD_DATA;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__WORD
|
||||||
|
{
|
||||||
|
HYDROFORTH__WORD_TYPE type;
|
||||||
|
HYDROFORTH__WORD_DATA data;
|
||||||
|
} HYDROFORTH__WORD;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__INTERPRETER
|
||||||
|
{
|
||||||
|
char *src;
|
||||||
|
unsigned long pos;
|
||||||
|
HYDROFORTH__WORD call_stack[256];
|
||||||
|
unsigned char call_stack_len;
|
||||||
|
int stack[256];
|
||||||
|
unsigned char stack_len;
|
||||||
|
} HYDROFORTH__INTERPRETER;
|
||||||
|
|
||||||
|
extern bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
|
||||||
|
extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
|
||||||
|
typedef struct __HYDROFORTH
|
||||||
|
{
|
||||||
|
__HYDROFORTH__NUMBER number;
|
||||||
|
bool (*step)(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
bool (*run)(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
} __HYDROFORTH;
|
||||||
|
|
||||||
|
static const __HYDROFORTH hydroforth = {
|
||||||
|
.number = {
|
||||||
|
.is_digit = hydroforth__number__is_digit,
|
||||||
|
.parse_number = hydroforth__number__parse_number,
|
||||||
|
.parse_number_with_sign = hydroforth__number__parse_number_with_sign,
|
||||||
|
},
|
||||||
|
.step = hydroforth__step,
|
||||||
|
.run = hydroforth__run,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
19
include/hydroforth/number.h
Normal file
19
include/hydroforth/number.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef __HYDROFORTH__NUMBER_H__
|
||||||
|
#define __HYDROFORTH__NUMBER_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern bool hydroforth__number__is_digit(char c);
|
||||||
|
|
||||||
|
extern bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val);
|
||||||
|
|
||||||
|
extern bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val);
|
||||||
|
|
||||||
|
typedef struct __HYDROFORTH__NUMBER
|
||||||
|
{
|
||||||
|
bool (*is_digit)(char c);
|
||||||
|
bool (*parse_number)(const char *const start, unsigned char len, int *const val);
|
||||||
|
bool (*parse_number_with_sign)(const char *const start, unsigned char len, int *const val);
|
||||||
|
} __HYDROFORTH__NUMBER;
|
||||||
|
|
||||||
|
#endif
|
76
src/hydroforth/hydroforth.c
Normal file
76
src/hydroforth/hydroforth.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hydroforth/hydroforth.h"
|
||||||
|
|
||||||
|
bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
|
{
|
||||||
|
const unsigned long start = interpreter->pos;
|
||||||
|
unsigned char len = 0;
|
||||||
|
while (interpreter->src[interpreter->pos] != ' ' && interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos])
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
interpreter->pos++;
|
||||||
|
}
|
||||||
|
printf("START: %lu\nLEN: %u\n", start, len);
|
||||||
|
HYDROFORTH__WORD word;
|
||||||
|
if (len == 1)
|
||||||
|
{
|
||||||
|
if (hydroforth__number__is_digit(interpreter->src[start]))
|
||||||
|
{
|
||||||
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = PUSH,
|
||||||
|
.data = {.number = interpreter->src[start] - '0'},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = CHAR_WORD,
|
||||||
|
.data = {.char_word = interpreter->src[start]},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((interpreter->src[start] == '-' || interpreter->src[start] == '+') &&
|
||||||
|
hydroforth__number__is_digit(interpreter->src[start + 1]))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (hydroforth__number__is_digit(interpreter->src[start]))
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
if (!hydroforth__number__parse_number(interpreter->src + start, len, &n))
|
||||||
|
{
|
||||||
|
printf("RESULT IS FALSE!!!\nNUMBER: %i\n", n);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
printf("NUMBER: %i\n", n);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
while (interpreter->src[interpreter->pos] == ' ' || interpreter->src[interpreter->pos] == '\n')
|
||||||
|
{
|
||||||
|
interpreter->pos++;
|
||||||
|
}
|
||||||
|
if (!interpreter->src[interpreter->pos])
|
||||||
|
{
|
||||||
|
puts("END REACHED!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!hydroforth__step(interpreter))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/hydroforth/number.c
Normal file
49
src/hydroforth/number.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "hydroforth/number.h"
|
||||||
|
|
||||||
|
bool hydroforth__number__is_digit(char c)
|
||||||
|
{
|
||||||
|
return '0' <= c && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
if (start[0] == '0')
|
||||||
|
{
|
||||||
|
if (len > 1)
|
||||||
|
{
|
||||||
|
switch (start[1])
|
||||||
|
{
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return hydroforth__number__parse_number(start + 1, len - 1, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*val = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int n = start[0] - '0';
|
||||||
|
for (unsigned char i = 1; i < len; i++)
|
||||||
|
{
|
||||||
|
n *= 10;
|
||||||
|
n += start[i] - '0';
|
||||||
|
}
|
||||||
|
*val = n;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val)
|
||||||
|
{
|
||||||
|
}
|
89
src/main.c
Normal file
89
src/main.c
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "hydroforth/hydroforth.h"
|
||||||
|
|
||||||
|
struct ReadSrcResult
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
char *const src;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReadSrcResult read_src(FILE *fp)
|
||||||
|
{
|
||||||
|
if (fseek(fp, 0L, SEEK_END) != 0)
|
||||||
|
{
|
||||||
|
fputs("Error seeking to file end!", stderr);
|
||||||
|
return (struct ReadSrcResult){
|
||||||
|
.success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const long bufsize = ftell(fp);
|
||||||
|
if (bufsize == -1)
|
||||||
|
{
|
||||||
|
fputs("Error getting file size!", stderr);
|
||||||
|
return (struct ReadSrcResult){
|
||||||
|
.success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
char *const src = malloc(sizeof(char) * (bufsize + 1));
|
||||||
|
if (fseek(fp, 0L, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
fputs("Error rewinding file to start!", stderr);
|
||||||
|
return (struct ReadSrcResult){
|
||||||
|
.success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const unsigned long new_len = fread(src, sizeof(char), bufsize, fp);
|
||||||
|
if (ferror(fp) != 0)
|
||||||
|
{
|
||||||
|
fputs("Error reading file!", stderr);
|
||||||
|
return (struct ReadSrcResult){
|
||||||
|
.success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
src[new_len + 1] = '\0';
|
||||||
|
|
||||||
|
return (struct ReadSrcResult){
|
||||||
|
.success = true,
|
||||||
|
.src = src,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
fputs("No source file specified!", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE *fp = fopen(argv[1], "rb");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
fputs("Error opening file!", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const struct ReadSrcResult res = read_src(fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (res.success)
|
||||||
|
{
|
||||||
|
HYDROFORTH__INTERPRETER interpreter = {
|
||||||
|
.src = res.src,
|
||||||
|
.pos = 0,
|
||||||
|
};
|
||||||
|
const bool run_res = hydroforth.run(&interpreter);
|
||||||
|
free(res.src);
|
||||||
|
if (!run_res)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(res.src);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
1
test.fth
Normal file
1
test.fth
Normal file
|
@ -0,0 +1 @@
|
||||||
|
40 2 + debug
|
Loading…
Reference in a new issue