Complete rewrite
This commit is contained in:
parent
115dc530e1
commit
cd77044bf5
24 changed files with 4650 additions and 836 deletions
284
include/ansi_lib.h
Normal file
284
include/ansi_lib.h
Normal file
|
@ -0,0 +1,284 @@
|
|||
// https://github.com/Constantin-Alexandru/ANSI-Library
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ANSII_LIB_H
|
||||
#define ANSII_LIB_H
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS 1
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
|
||||
#define WIN_ERR exit(GetLastError())
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief The handle for the standard output stream.
|
||||
*
|
||||
*/
|
||||
static HANDLE stdOutHandle;
|
||||
|
||||
/**
|
||||
* @brief The initial state of the output stream.
|
||||
*
|
||||
*/
|
||||
static DWORD outModeInitial;
|
||||
|
||||
/**
|
||||
* @brief Sets the Windows console to allow virtual terminal codes.
|
||||
*
|
||||
*/
|
||||
inline void setupConsole(void){
|
||||
DWORD outMode = 0;
|
||||
stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
if(stdOutHandle == INVALID_HANDLE_VALUE) { WIN_ERR; }
|
||||
|
||||
if(!GetConsoleMode(stdOutHandle, &outMode)) { WIN_ERR; }
|
||||
|
||||
outModeInitial = outMode;
|
||||
|
||||
// Allow virtual terminal codes.
|
||||
outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
|
||||
if(!SetConsoleMode(stdOutHandle, outMode)) { WIN_ERR; }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the console to the inital state without the virtual terminal codes.
|
||||
*
|
||||
*/
|
||||
inline void resetConsole(void){
|
||||
|
||||
//Resets the console attributes to white text and black background.
|
||||
printf("\x1b[0m");
|
||||
|
||||
//Resets the console mode to it's initial state.
|
||||
if(!SetConsoleMode(stdOutHandle, outModeInitial)) { WIN_ERR; }
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief Resets the console to the inital state without the virtual terminal codes.
|
||||
*
|
||||
*/
|
||||
inline void resetConsole(void){
|
||||
//Resets the console attributes to white text and black background.
|
||||
printf("\x1b[0m");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ===================================== COLOUR/GRAPHICS MODE ===================================== */
|
||||
|
||||
/**
|
||||
* @brief The codes of the Colour Sequences.
|
||||
*
|
||||
*/
|
||||
enum Colours{
|
||||
//Text Colours
|
||||
TXT_BLACK = 30,
|
||||
TXT_RED = 31,
|
||||
TXT_GREEN = 32,
|
||||
TXT_YELLOW = 33,
|
||||
TXT_BLUE = 34,
|
||||
TXT_MAGENTA = 35,
|
||||
TXT_CYAN = 36,
|
||||
TXT_WHITE = 37,
|
||||
|
||||
TXT_DEFAULT = 39,
|
||||
|
||||
//Background Colours
|
||||
BKG_BLACK = 40,
|
||||
BKG_RED = 41,
|
||||
BKG_GREEN = 42,
|
||||
BKG_YELLOW = 43,
|
||||
BKG_BLUE = 44,
|
||||
BKG_MAGENTA = 45,
|
||||
BKG_CYAN = 46,
|
||||
BKG_WHITE = 47,
|
||||
|
||||
BKG_DEFAULT = 49
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sets the text colour using the 8 ANSII values inside the Colours enum.
|
||||
* @param code the colour code accepts values from the Colour enum.
|
||||
*
|
||||
*/
|
||||
#define SET_8_VALUE_COLOUR(code) printf("\x1b[%dm", code)
|
||||
|
||||
/**
|
||||
* @brief Sets the text colour using the 0 - 255 range.
|
||||
* @param code the colour code accepts values from the 0 - 255 range.
|
||||
*
|
||||
*/
|
||||
#define SET_256_TXT_COLOUR(code) printf("\x1b[38;5;%dm", code)
|
||||
/**
|
||||
* @brief Sets the background colour using the 0 - 255 range.
|
||||
* @param code the colour code accepts values from the 0 - 255 range.
|
||||
*
|
||||
*/
|
||||
#define SET_256_BKG_COLOUR(code) printf("\x1b[38;5;%dm", code)
|
||||
|
||||
/**
|
||||
* @brief Sets the text colour using RGB values.
|
||||
* @param r the red channel only accepts values from the 0-255 range.
|
||||
* @param g the green channel only accepts values from the 0-255 range.
|
||||
* @param b the blue channel only accepts values from the 0-255 range.
|
||||
* @b NOTE: Only works on some terminals.
|
||||
*/
|
||||
#define SET_RGB_TXT_COLOUR(r, g, b) printf("\x1b[38;2;%d;%d;%dm", r, g, b)
|
||||
|
||||
/**
|
||||
* @brief Sets the background colour using RGB values.
|
||||
* @param r the red channel only accepts values from the 0-255 range.
|
||||
* @param g the green channel only accepts values from the 0-255 range.
|
||||
* @param b the blue channel only accepts values from the 0-255 range.
|
||||
* @b NOTE: Only works on some terminals.
|
||||
*/
|
||||
#define SET_RGB_BKG_COLOUR(r, g, b) printf("\x1b[48;2;%d;%d;%dm", r, g, b)
|
||||
|
||||
/**
|
||||
* @brief The codes of the Graphics Sequences.
|
||||
*
|
||||
*/
|
||||
enum GRAPHIC_CODE{
|
||||
//Graphic sequences.
|
||||
BOLD_MODE = 1,
|
||||
DIM_MODE = 2,
|
||||
ITALIC_MODE = 3,
|
||||
UNDERLINE_MODE = 4,
|
||||
BLINKING_MODE = 5,
|
||||
INVERSE_MODE = 7,
|
||||
HIDDEN_MODE = 8,
|
||||
STRIKETHROUGH_MODE = 9,
|
||||
//Only works on some terminals.
|
||||
DOUBLE_UNDERLINE_MODE = 21,
|
||||
|
||||
//Reset sequences.
|
||||
BOLD_MODE_RESET = 22,
|
||||
DIM_MODE_RESET = BOLD_MODE_RESET,
|
||||
ITALIC_MODE_RESET = 23,
|
||||
UNDERLINE_MODE_RESET = 24,
|
||||
BLINKING_MODE_RESET = 25,
|
||||
INVERSE_MODE_RESET = 27,
|
||||
HIDDEN_MODE_RESET = 28,
|
||||
STRIKETHROUGH_MODE_RESET = 29,
|
||||
//Only works on some terminals
|
||||
DOUBLE_UNDERLINE_MODE_RESET = UNDERLINE_MODE_RESET
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sets the graphic mode using the codes inside the GRAPHIC_MODE enum
|
||||
* @param code The code from the GRAPHIC_MODE enum
|
||||
*
|
||||
*/
|
||||
#define SET_GRAPHIC_MODE(code) printf("\x1b[%dm", code)
|
||||
|
||||
/**
|
||||
* @brief Resets all graphics modes and colours.
|
||||
*
|
||||
*/
|
||||
#define RESET_GRAPHICS_MODES printf("\x1b[0m")
|
||||
|
||||
/* ===================================== CURSOR MODE ===================================== */
|
||||
|
||||
/**
|
||||
* @brief Moves cursor to the (line, column) position.
|
||||
* @param line The line to move the cursor to.
|
||||
* @param column The column to move the cursor to.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_TO_POS(line, column) printf("\x1b[%d;%dH", line, column)
|
||||
|
||||
/**
|
||||
* @brief Moves cursor up by a number of lines.
|
||||
* @param lines The number of lines to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_UP_BY_LINES(lines) printf("\x1b[%dA", lines)
|
||||
/**
|
||||
* @brief Moves cursor down by a number of lines.
|
||||
* @param lines The number of lines to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_DOWN_BY_LINES(lines) printf("\x1b[%dB", lines)
|
||||
|
||||
/**
|
||||
* @brief Moves cursor right by a number of columns.
|
||||
* @param columns The number of columns to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_RIGHT_BY_COLUMNS(columns) printf("\x1b[%dC", columns)
|
||||
/**
|
||||
* @brief Moves cursor left by a number of columns.
|
||||
* @param columns The number of columns to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_LEFT_BY_COLUMS(columns) printf("\x1b[%dD", columns)
|
||||
|
||||
/**
|
||||
* @brief Moves cursor down by a number of lines, at the beginning of the line.
|
||||
* @param lines The number of lines to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_BEGINNING_LINE_DOWN_BY_LINES(lines) printf("\x1b[%dE", lines)
|
||||
/**
|
||||
* @brief Moves cursor up by a number of lines, at the beginning of the line.
|
||||
* @param lines The number of lines to move the cursor by.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_BEGINNING_LINE_UP_BY_LINES(lines) printf("\x1b[%dF", lines)
|
||||
|
||||
/**
|
||||
* @brief Moves cursor to column.
|
||||
* @param column The column where the cursor is moved.
|
||||
*
|
||||
*/
|
||||
#define MOVE_CURSOR_TO_COLUMN(column) printf("\x1b[%dG", column)
|
||||
|
||||
/* ===================================== ERASE MODE ===================================== */
|
||||
|
||||
/**
|
||||
* @brief The codes of the Erase Sequence.
|
||||
*
|
||||
*/
|
||||
enum ERASE_CODE{
|
||||
ERASE_TO_END = 0,
|
||||
ERASE_TO_BEGINNING = 1,
|
||||
ERASE_ALL = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Erases the screen based on the value from the ERASE_CODE enum.
|
||||
* @param code The code from the ERASE_CODE enum.
|
||||
*
|
||||
*/
|
||||
#define ERASE_IN_SCREEN(code) printf("\x1b[%dJ", code)
|
||||
/**
|
||||
* @brief Erases the line based on the value from the ERASE_CODE enum.
|
||||
* @param code The code from the ERASE_CODE enum.
|
||||
* @b NOTE: The cursor won't move positions after the erase.
|
||||
*
|
||||
*/
|
||||
#define ERASE_IN_LINE(code) printf("\x1b[%dK", code)
|
||||
|
||||
/**
|
||||
* @brief Erases the visible screen
|
||||
*
|
||||
*/
|
||||
#define ERASE_SCREEN printf("\x1b[H\x1b[J")
|
||||
|
||||
#endif
|
13
include/hydroforth/hash.h
Normal file
13
include/hydroforth/hash.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef __HF__HASH_H__
|
||||
#define __HF__HASH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t hf__hash_t;
|
||||
|
||||
extern hf__hash_t hf__hash_mem(const unsigned char *start,
|
||||
const unsigned char *const end);
|
||||
|
||||
extern hf__hash_t hf__hash_str(const char *str);
|
||||
|
||||
#endif
|
30
include/hydroforth/hashmap.h
Normal file
30
include/hydroforth/hashmap.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef __HF__HASHMAP_H__
|
||||
#define __HF__HASHMAP_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hydroforth.h"
|
||||
|
||||
struct hf__hashmap__node {
|
||||
hf__hash_t hash;
|
||||
void *value;
|
||||
struct hf__hashmap__node *next;
|
||||
};
|
||||
|
||||
struct hf__hashmap {
|
||||
struct hf__hashmap__node **arr;
|
||||
size_t cap;
|
||||
};
|
||||
|
||||
extern void hf__hashmap__insert(struct hf__hashmap *const hashmap,
|
||||
const hf__hash_t hash, void *value);
|
||||
|
||||
extern void **hf__hashmap__get(const struct hf__hashmap *const hashmap,
|
||||
const hf__hash_t hash);
|
||||
|
||||
typedef void (*hf__hashmap__free_value_t)(void *);
|
||||
|
||||
extern void hf__hashmap__free(struct hf__hashmap *const hashmap,
|
||||
const hf__hashmap__free_value_t free_value);
|
||||
|
||||
#endif
|
|
@ -1,124 +1,66 @@
|
|||
#ifndef __HYDROFORTH_H__
|
||||
#define __HYDROFORTH_H__
|
||||
#ifndef __HF__HYDROFORTH_H__
|
||||
#define __HF__HYDROFORTH_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HF__VERSION "0.1.0"
|
||||
|
||||
/**
|
||||
* @brief Checks if specific bit at position it set to 1
|
||||
*
|
||||
*/
|
||||
#define HF__CHECK_BIT(var, pos) ((var) & (1 << (pos)))
|
||||
|
||||
/**
|
||||
* @brief Checks if char is a space- or tab-like
|
||||
*
|
||||
* @param c
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
extern bool hf__is_space_like(const char c);
|
||||
|
||||
/**
|
||||
* @brief Checks if a char is a decimal numeric (0-9)
|
||||
*
|
||||
* @param c
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
extern bool hf__is_numeric(const char c);
|
||||
|
||||
/**
|
||||
* @brief Quotes a string with either single or double quotes. Returned string
|
||||
* needs to be freed.
|
||||
*
|
||||
* @param str
|
||||
* @param double_quote
|
||||
* @return char*
|
||||
*/
|
||||
extern char *hf__quote(const char *const str, const bool double_quote);
|
||||
|
||||
/**
|
||||
* @brief Quotes a string inside a slice of memory with either single or double
|
||||
* quotes. Returned string needs to be freed.
|
||||
*
|
||||
* @param src
|
||||
* @param start
|
||||
* @param end
|
||||
* @param double_quote
|
||||
* @return char*
|
||||
*/
|
||||
extern char *hf__quote_mem_str(const char *const src, const size_t start,
|
||||
const size_t end, const bool double_quote);
|
||||
|
||||
#include "hash.h"
|
||||
#include "hashmap.h"
|
||||
#include "interpreter.h"
|
||||
#include "keywords.h"
|
||||
#include "lexer.h"
|
||||
#include "location.h"
|
||||
#include "parser.h"
|
||||
#include "result.h"
|
||||
#include "number.h"
|
||||
|
||||
extern unsigned hydroforth__hash_string(const char *const key, unsigned char len);
|
||||
|
||||
extern bool hydroforth__is_space(char c);
|
||||
|
||||
typedef enum HYDROFORTH__WORD_TYPE
|
||||
{
|
||||
PUSH,
|
||||
CHAR_WORD,
|
||||
WORD,
|
||||
} HYDROFORTH__WORD_TYPE;
|
||||
|
||||
typedef union HYDROFORTH__WORD_DATA
|
||||
{
|
||||
int number;
|
||||
char char_word;
|
||||
unsigned int hash;
|
||||
} HYDROFORTH__WORD_DATA;
|
||||
|
||||
typedef struct HYDROFORTH__WORD
|
||||
{
|
||||
HYDROFORTH__WORD_TYPE type;
|
||||
HYDROFORTH__WORD_DATA data;
|
||||
} HYDROFORTH__WORD;
|
||||
|
||||
typedef struct HYDROFORTH__WORD_DEFINITION
|
||||
{
|
||||
HYDROFORTH__WORD *words;
|
||||
unsigned char words_len;
|
||||
} HYDROFORTH__WORD_DEFINITION;
|
||||
|
||||
typedef struct HYDROFORTH__WORD_DEFINITION_BASE_KEY
|
||||
{
|
||||
unsigned char word_definition_index;
|
||||
} HYDROFORTH__WORD_DEFINITION_BASE_KEY;
|
||||
|
||||
typedef struct HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY
|
||||
{
|
||||
char c;
|
||||
HYDROFORTH__WORD_DEFINITION_BASE_KEY key;
|
||||
} HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY;
|
||||
|
||||
typedef struct HYDROFORTH__WORD_DEFINITION_WORD_KEY
|
||||
{
|
||||
unsigned int hash;
|
||||
HYDROFORTH__WORD_DEFINITION_BASE_KEY key;
|
||||
} HYDROFORTH__WORD_DEFINITION_WORD_KEY;
|
||||
|
||||
typedef struct HYDROFORTH__INTERPRETER
|
||||
{
|
||||
char *src;
|
||||
unsigned long pos;
|
||||
HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY single_char_word_keys[32];
|
||||
unsigned char single_char_word_keys_len;
|
||||
HYDROFORTH__WORD_DEFINITION_WORD_KEY word_keys[256];
|
||||
unsigned short word_keys_len;
|
||||
HYDROFORTH__WORD_DEFINITION word_definitions[256 + 32];
|
||||
unsigned short word_definitions_len;
|
||||
HYDROFORTH__WORD call_stack[256];
|
||||
unsigned char call_stack_len;
|
||||
int stack[256];
|
||||
unsigned char stack_len;
|
||||
} HYDROFORTH__INTERPRETER;
|
||||
|
||||
typedef struct HYDROFORTH__SCAN_NEXT_WORD_RESULT
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned char len;
|
||||
} HYDROFORTH__SCAN_NEXT_WORD_RESULT;
|
||||
|
||||
extern HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter);
|
||||
|
||||
extern void hydroforth__add_word_to_word_definition(HYDROFORTH__WORD_DEFINITION *word_def, HYDROFORTH__WORD word);
|
||||
|
||||
extern void hydroforth__parse(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter, HYDROFORTH__WORD_DEFINITION *word_def);
|
||||
|
||||
extern void hydroforth__run_call_stack(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
|
||||
extern void hydroforth__run(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
|
||||
typedef struct __HYDROFORTH
|
||||
{
|
||||
__HYDROFORTH__RESULT result;
|
||||
__HYDROFORTH__NUMBER number;
|
||||
unsigned (*hash_string)(const char *const key, unsigned char len);
|
||||
bool (*is_space)(char c);
|
||||
HYDROFORTH__SCAN_NEXT_WORD_RESULT(*scan_next_word)
|
||||
(HYDROFORTH__INTERPRETER *interpreter);
|
||||
void (*add_word_to_word_definition)(HYDROFORTH__WORD_DEFINITION *word_def, HYDROFORTH__WORD word);
|
||||
void (*parse)(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter, HYDROFORTH__WORD_DEFINITION *word_def);
|
||||
void (*run_call_stack)(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
void (*run)(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
} __HYDROFORTH;
|
||||
|
||||
static const __HYDROFORTH hydroforth = {
|
||||
.result = {
|
||||
.add_backtrace = hydroforth__result__add_backtrace,
|
||||
.get_error_message = hydroforth__result__get_error_message,
|
||||
.unwrap = hydroforth__result__unwrap,
|
||||
},
|
||||
.number = {
|
||||
.is_digit = hydroforth__number__is_digit,
|
||||
.convert_hex_digit = hydroforth__number__convert_hex_digit,
|
||||
.parse_number_hex = hydroforth__number__parse_number_hex,
|
||||
.parse_number = hydroforth__number__parse_number,
|
||||
.count_digits = hydroforth__number__count_digits,
|
||||
},
|
||||
.hash_string = hydroforth__hash_string,
|
||||
.is_space = hydroforth__is_space,
|
||||
.scan_next_word = hydroforth__scan_next_word,
|
||||
.add_word_to_word_definition = hydroforth__add_word_to_word_definition,
|
||||
.parse = hydroforth__parse,
|
||||
.run_call_stack = hydroforth__run_call_stack,
|
||||
.run = hydroforth__run,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
49
include/hydroforth/interpreter.h
Normal file
49
include/hydroforth/interpreter.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef __HF__INTERPRETER_H__
|
||||
#define __HF__INTERPRETER_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "parser.h"
|
||||
#include "result.h"
|
||||
|
||||
#define HF__INTERPRETER__WORDS_CAP 23
|
||||
|
||||
struct hf__interpreter__word {
|
||||
struct hf__node *body;
|
||||
size_t body_len;
|
||||
};
|
||||
|
||||
extern const hf__hashmap__free_value_t hf__interpreter__word_free;
|
||||
|
||||
struct hf__interpreter {
|
||||
struct hf__node *call_stack;
|
||||
size_t call_stack_len;
|
||||
size_t call_stack_size;
|
||||
|
||||
struct hf__hashmap words; // struct hf__interpreter__word *
|
||||
|
||||
long *stack;
|
||||
size_t stack_len;
|
||||
size_t stack_size;
|
||||
|
||||
bool is_running;
|
||||
int exit_code;
|
||||
};
|
||||
|
||||
extern void hf__interpreter__free(struct hf__interpreter *interpreter);
|
||||
|
||||
typedef struct hf__result (*hf__interpreter__word_func_t)(
|
||||
struct hf__interpreter *const, const struct hf__node *const);
|
||||
|
||||
extern const hf__interpreter__word_func_t
|
||||
HF__INTERPRETER__WORD_FUNCTION[__HF__NODE_TYPE__N];
|
||||
|
||||
extern void hf__interpreter__stack_push(long **arr, size_t *const len,
|
||||
size_t *const size, long item);
|
||||
|
||||
extern struct hf__result
|
||||
hf__interpreter__run(struct hf__interpreter *const interpreter);
|
||||
|
||||
#endif
|
68
include/hydroforth/keywords.h
Normal file
68
include/hydroforth/keywords.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef __HF__KEYWORDS_H__
|
||||
#define __HF__KEYWORDS_H__
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
enum HF__KEYWORD {
|
||||
HF__KEYWORD__DUP,
|
||||
HF__KEYWORD__DROP,
|
||||
HF__KEYWORD__SWAP,
|
||||
HF__KEYWORD__OVER,
|
||||
HF__KEYWORD__ROT,
|
||||
|
||||
HF__KEYWORD__ADD,
|
||||
HF__KEYWORD__SUB,
|
||||
|
||||
HF__KEYWORD__PERIOD,
|
||||
HF__KEYWORD__EMIT,
|
||||
HF__KEYWORD__SPACE,
|
||||
HF__KEYWORD__SPACES,
|
||||
HF__KEYWORD__CR,
|
||||
HF__KEYWORDS__CRS,
|
||||
HF__KEYWORD__DEBUG,
|
||||
|
||||
HF__KEYWORD__ABORT,
|
||||
HF__KEYWORD__EXIT,
|
||||
|
||||
__HF__KEYWORD__N,
|
||||
};
|
||||
|
||||
static const char *const HF__KEYWORD_STR[__HF__KEYWORD__N] = {
|
||||
[HF__KEYWORD__DUP] = "dup", [HF__KEYWORD__DROP] = "drop",
|
||||
[HF__KEYWORD__SWAP] = "swap", [HF__KEYWORD__OVER] = "over",
|
||||
[HF__KEYWORD__ROT] = "rot",
|
||||
|
||||
[HF__KEYWORD__ADD] = "+", [HF__KEYWORD__SUB] = "-",
|
||||
|
||||
[HF__KEYWORD__EMIT] = "emit", [HF__KEYWORD__PERIOD] = ".",
|
||||
[HF__KEYWORD__SPACE] = "space", [HF__KEYWORD__SPACES] = "spaces",
|
||||
[HF__KEYWORD__CR] = "cr", [HF__KEYWORDS__CRS] = "crs",
|
||||
[HF__KEYWORD__DEBUG] = "debug",
|
||||
|
||||
[HF__KEYWORD__ABORT] = "abort", [HF__KEYWORD__EXIT] = "exit",
|
||||
|
||||
};
|
||||
|
||||
static const enum hf__node_type HF__KEYWORD_NODE_TYPE[__HF__KEYWORD__N] = {
|
||||
[HF__KEYWORD__DUP] = HF__NODE_TYPE__DUP,
|
||||
[HF__KEYWORD__DROP] = HF__NODE_TYPE__DROP,
|
||||
[HF__KEYWORD__SWAP] = HF__NODE_TYPE__SWAP,
|
||||
[HF__KEYWORD__OVER] = HF__NODE_TYPE__OVER,
|
||||
[HF__KEYWORD__ROT] = HF__NODE_TYPE__ROT,
|
||||
|
||||
[HF__KEYWORD__ADD] = HF__NODE_TYPE__ADD,
|
||||
[HF__KEYWORD__SUB] = HF__NODE_TYPE__SUB,
|
||||
|
||||
[HF__KEYWORD__PERIOD] = HF__NODE_TYPE__DOT,
|
||||
[HF__KEYWORD__EMIT] = HF__NODE_TYPE__EMIT,
|
||||
[HF__KEYWORD__SPACE] = HF__NODE_TYPE__SPACE,
|
||||
[HF__KEYWORD__SPACES] = HF__NODE_TYPE__SPACES,
|
||||
[HF__KEYWORD__CR] = HF__NODE_TYPE__CR,
|
||||
[HF__KEYWORDS__CRS] = HF__NODE_TYPE__CRS,
|
||||
[HF__KEYWORD__DEBUG] = HF__NODE_TYPE__DEBUG,
|
||||
|
||||
[HF__KEYWORD__ABORT] = HF__NODE_TYPE__ABORT,
|
||||
[HF__KEYWORD__EXIT] = HF__NODE_TYPE__EXIT,
|
||||
};
|
||||
|
||||
#endif
|
29
include/hydroforth/lexer.h
Normal file
29
include/hydroforth/lexer.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef __HF__LEXER_H__
|
||||
#define __HF__LEXER_H__
|
||||
|
||||
#include "location.h"
|
||||
#include "result.h"
|
||||
|
||||
enum hf__token_type {
|
||||
HF__TOKEN_TYPE__NUMBER,
|
||||
HF__TOKEN_TYPE__CHAR,
|
||||
HF__TOKEN_TYPE__WORD,
|
||||
|
||||
HF__TOKEN_TYPE__COLON,
|
||||
HF__TOKEN_TYPE__SEMICOLON,
|
||||
|
||||
HF__TOKEN_TYPE__DASH_COMMENT,
|
||||
HF__TOKEN_TYPE__BACKSLASH_COMMENT,
|
||||
HF__TOKEN_TYPE__PAREN_COMMENT,
|
||||
};
|
||||
|
||||
struct hf__token {
|
||||
enum hf__token_type type;
|
||||
struct hf__location location;
|
||||
};
|
||||
|
||||
extern void hf__lex(const char *const src, const size_t src_len,
|
||||
struct hf__token **tokens, size_t *const len,
|
||||
size_t *const size);
|
||||
|
||||
#endif
|
9
include/hydroforth/location.h
Normal file
9
include/hydroforth/location.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __HF__LOCATION_H__
|
||||
#define __HF__LOCATION_H__
|
||||
|
||||
struct hf__location {
|
||||
size_t start;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef __HYDROFORTH__NUMBER_H__
|
||||
#define __HYDROFORTH__NUMBER_H__
|
||||
|
||||
extern bool hydroforth__number__is_digit(char c);
|
||||
|
||||
extern unsigned char hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c);
|
||||
|
||||
extern int hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
|
||||
extern int hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
|
||||
extern unsigned char hydroforth__number__count_digits(int n);
|
||||
|
||||
typedef struct __HYDROFORTH__NUMBER
|
||||
{
|
||||
bool (*is_digit)(char c);
|
||||
unsigned char (*convert_hex_digit)(HYDROFORTH__RESULT *const result, char c);
|
||||
int (*parse_number_hex)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
int (*parse_number)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
unsigned char (*count_digits)(int n);
|
||||
} __HYDROFORTH__NUMBER;
|
||||
|
||||
#endif
|
84
include/hydroforth/parser.h
Normal file
84
include/hydroforth/parser.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#ifndef __HF__PARSER_H__
|
||||
#define __HF__PARSER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "lexer.h"
|
||||
|
||||
enum hf__node_type {
|
||||
HF__NODE_TYPE__NUMBER,
|
||||
HF__NODE_TYPE__CHAR,
|
||||
HF__NODE_TYPE__WORD,
|
||||
HF__NODE_TYPE__WORD_DEF,
|
||||
|
||||
HF__NODE_TYPE__DASH_COMMENT,
|
||||
HF__NODE_TYPE__PAREN_COMMENT,
|
||||
|
||||
HF__NODE_TYPE__DUP,
|
||||
HF__NODE_TYPE__DROP,
|
||||
HF__NODE_TYPE__SWAP,
|
||||
HF__NODE_TYPE__OVER,
|
||||
HF__NODE_TYPE__ROT,
|
||||
|
||||
HF__NODE_TYPE__ADD,
|
||||
HF__NODE_TYPE__SUB,
|
||||
|
||||
HF__NODE_TYPE__DOT,
|
||||
HF__NODE_TYPE__EMIT,
|
||||
HF__NODE_TYPE__SPACE,
|
||||
HF__NODE_TYPE__SPACES,
|
||||
HF__NODE_TYPE__CR,
|
||||
HF__NODE_TYPE__CRS,
|
||||
HF__NODE_TYPE__DEBUG,
|
||||
|
||||
HF__NODE_TYPE__ABORT,
|
||||
HF__NODE_TYPE__EXIT,
|
||||
|
||||
__HF__NODE_TYPE__N,
|
||||
};
|
||||
|
||||
struct hf__node_value__word {
|
||||
unsigned long hash;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct hf__node_value__word_def {
|
||||
struct hf__node_value__word name;
|
||||
struct hf__node *body;
|
||||
size_t body_len;
|
||||
};
|
||||
|
||||
union hf__node_value {
|
||||
long number;
|
||||
char ch;
|
||||
struct hf__node_value__word word;
|
||||
struct hf__node_value__word_def *word_def;
|
||||
char *comment;
|
||||
};
|
||||
|
||||
struct hf__node {
|
||||
enum hf__node_type type;
|
||||
union hf__node_value value;
|
||||
};
|
||||
|
||||
struct hf__parser {
|
||||
struct hf__hashmap keyword_map;
|
||||
bool keyword_map_is_init;
|
||||
};
|
||||
|
||||
#define HF__PARSER__KEYWORD_MAP_CAP 23
|
||||
|
||||
extern void hf__parser__init_keyword_map(struct hf__hashmap *const map,
|
||||
size_t cap);
|
||||
|
||||
extern void hf__parser__node_array_push(struct hf__node **arr,
|
||||
size_t *const len, size_t *const size,
|
||||
struct hf__node item);
|
||||
|
||||
extern struct hf__result
|
||||
hf__parse(struct hf__parser *const parser, const char *const src,
|
||||
const struct hf__token *const tokens, const size_t tokens_len,
|
||||
struct hf__node **nodes, size_t *const len, size_t *const size);
|
||||
|
||||
#endif
|
|
@ -1,49 +1,60 @@
|
|||
#ifndef __HYDROFORTH__RESULT_H__
|
||||
#define __HYDROFORTH__RESULT_H__
|
||||
#ifndef __HF__RESULT_H__
|
||||
#define __HF__RESULT_H__
|
||||
|
||||
typedef enum HYDROFORTH__RESULT__ERROR
|
||||
{
|
||||
OK = 0,
|
||||
enum hf__error {
|
||||
HF__ERROR__PARSER__UNEXPECTED,
|
||||
HF__ERROR__PARSER__INVALID_NUMBER,
|
||||
HF__ERROR__PARSER__INVALID_CHAR,
|
||||
HF__ERROR__PARSER__WORD_DEF_INCOMPLETE,
|
||||
HF__ERROR__PARSER__WORD_DEF_INVALID_NAME,
|
||||
HF__ERROR__PARSER__WORD_DEF_IS_KEYWORD,
|
||||
|
||||
ERR_UNKNOWN,
|
||||
HF__ERROR__INTERPRETER__UNKNOWN_WORD,
|
||||
HF__ERROR__INTERPRETER__WORD_ALREADY_DEF,
|
||||
HF__ERROR__INTERPRETER__STACK_UNDERFLOW,
|
||||
|
||||
ERR_INVALID_HEX_CHAR,
|
||||
ERR_UNKNOWN_SINGLE_CHAR_WORD,
|
||||
ERR_UNKNOWN_WORD,
|
||||
ERR_UNTERMINATED_WORD_DEFINITION,
|
||||
ERR_WORD_NAME_CANT_BE_NUMBER,
|
||||
ERR_WORD_DEF_INSIDE_WORD_DEF,
|
||||
} HYDROFORTH__RESULT__ERROR;
|
||||
__HF__ERROR__N,
|
||||
};
|
||||
|
||||
typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR;
|
||||
struct hf__error_wrapper {
|
||||
enum hf__error error;
|
||||
bool msg_is_freeable;
|
||||
char *msg;
|
||||
};
|
||||
|
||||
typedef struct HYDROFORTH__RESULT__RESULT
|
||||
{
|
||||
HYDROFORTH__ERROR error;
|
||||
const char **backtrace;
|
||||
unsigned short backtrace_len;
|
||||
} HYDROFORTH__RESULT__RESULT;
|
||||
static const char *const HF__ERROR_STR[__HF__ERROR__N] = {
|
||||
[HF__ERROR__PARSER__UNEXPECTED] = "Unexpected token",
|
||||
[HF__ERROR__PARSER__INVALID_NUMBER] = "Invalid number",
|
||||
[HF__ERROR__PARSER__INVALID_CHAR] = "Invalid char",
|
||||
[HF__ERROR__PARSER__WORD_DEF_INCOMPLETE] = "Word definition imcomplete",
|
||||
[HF__ERROR__PARSER__WORD_DEF_INVALID_NAME] =
|
||||
"Invalid token type for word name",
|
||||
[HF__ERROR__PARSER__WORD_DEF_IS_KEYWORD] = "Word name is already a keyword",
|
||||
|
||||
typedef HYDROFORTH__RESULT__RESULT HYDROFORTH__RESULT;
|
||||
[HF__ERROR__INTERPRETER__UNKNOWN_WORD] = "Unknown word",
|
||||
[HF__ERROR__INTERPRETER__WORD_ALREADY_DEF] = "Word is already defined",
|
||||
[HF__ERROR__INTERPRETER__STACK_UNDERFLOW] = "Stack underflow",
|
||||
};
|
||||
|
||||
extern void hydroforth__result__add_backtrace(HYDROFORTH__RESULT *const result, const char *const s);
|
||||
extern void hf__print_error(struct hf__error_wrapper *error);
|
||||
|
||||
extern void hydroforth__result__set(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, const char *const s);
|
||||
struct hf__result {
|
||||
bool ok;
|
||||
struct hf__error_wrapper error;
|
||||
};
|
||||
|
||||
extern const char *hydroforth__result__get_error_message(HYDROFORTH__ERROR error);
|
||||
#define HF__OK ((struct hf__result){.ok = true})
|
||||
|
||||
#define hydroforth__set_func_result(result, error) hydroforth__result__set(result, error, __func__);
|
||||
#define HF__ERR(err) \
|
||||
((struct hf__result){ \
|
||||
.ok = false, \
|
||||
.error = {.error = err, .msg = NULL}, \
|
||||
})
|
||||
|
||||
#define hydroforth__add_func_backtrace(result) hydroforth__result__add_backtrace(result, __func__);
|
||||
|
||||
extern int hydroforth__result__unwrap(HYDROFORTH__RESULT *const result, int code);
|
||||
|
||||
typedef struct __HYDROFORTH__RESULT
|
||||
{
|
||||
void (*add_backtrace)(HYDROFORTH__RESULT *const result, const char *const s);
|
||||
void (*set)(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, const char *const s);
|
||||
const char *(*get_error_message)(HYDROFORTH__ERROR error);
|
||||
int (*unwrap)(HYDROFORTH__RESULT *const result, int code);
|
||||
} __HYDROFORTH__RESULT;
|
||||
#define HF__ERR_CUSTOM(err, message, freeable) \
|
||||
((struct hf__result){ \
|
||||
.ok = false, \
|
||||
.error = {.error = err, .msg_is_freeable = freeable, .msg = message}, \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue