From 24f981233bc3e0b000acf4615d4bc6f2332eefb0 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Tue, 14 Feb 2023 02:02:50 -0800 Subject: init --- .gitignore | 5 +++ Makefile | 11 +++++++ README | 1 + example.pcdt | 3 ++ hashtable.c | 34 ++++++++++++++++++++ hashtable.h | 18 +++++++++++ parse.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse.h | 29 +++++++++++++++++ precedent | Bin 0 -> 28848 bytes precedent.c | 11 +++++++ precedent.h | 8 +++++ scope.c | 20 ++++++++++++ scope.h | 13 ++++++++ 13 files changed, 256 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README create mode 100644 example.pcdt create mode 100644 hashtable.c create mode 100644 hashtable.h create mode 100644 parse.c create mode 100644 parse.h create mode 100755 precedent create mode 100644 precedent.c create mode 100644 precedent.h create mode 100644 scope.c create mode 100644 scope.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d77bb67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +a.out +a.exe +*.swp +snake3 +*.core diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a9b5503 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +CFLAGS=-I. -pthread -Wall -Wextra -Wpedantic -std=c99 -march=native -O3 -lm +CFLAGS+= -Wshadow -Wstrict-prototypes -Wundef -Wpointer-arith -Wcast-align -Wstrict-overflow=5 -Wswitch-default +CFLAGS+= -Wunreachable-code -Wswitch-enum -Wformat=2 -g +PREFIX ?= /usr +BINDIR ?= ${PREFIX}/bin + +generate: + $(CC) -o precedent precedent.c hashtable.c scope.c parse.c $(CFLAGS) + +clean: + rm precedent diff --git a/README b/README new file mode 100644 index 0000000..9111412 --- /dev/null +++ b/README @@ -0,0 +1 @@ +Attempt to make a programming language of some sort diff --git a/example.pcdt b/example.pcdt new file mode 100644 index 0000000..6c4dd92 --- /dev/null +++ b/example.pcdt @@ -0,0 +1,3 @@ +store(5; myVar;); +print(read(myVar;);); +(hello; hello2;) diff --git a/hashtable.c b/hashtable.c new file mode 100644 index 0000000..ce4c65a --- /dev/null +++ b/hashtable.c @@ -0,0 +1,34 @@ +#include +#include "hashtable.h" + +const unsigned int fnvPrime = 16777619; +const unsigned int fnvOffset = 2166136261U; + +//FNV-1a hash +unsigned int get_hash(char* str) { + unsigned int hash = fnvOffset; + while (*str != '\0') { + hash = (hash ^ *str) * fnvPrime; + str++; + } + return hash; +} +hashtable_t* init_hashtable(unsigned int capacity) { + hashtable_t* ht = malloc(sizeof(hashtable_t)); + ht->pairs = calloc(capacity, sizeof(pair_t*)); + ht->capacity = capacity; + return ht; +} +/* TODO: handle collision +TODO: return 0 if something goes wrong */ +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair) { + unsigned int hash = get_hash(pair.key); + pair_t* memPair = malloc(sizeof(pair_t)); + *memPair = pair; + hashtable->pairs[hash % hashtable->capacity] = memPair; + return hash; +} +pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key) { + unsigned int hash = get_hash(key); + return hashtable->pairs[hash % hashtable->capacity]; +} diff --git a/hashtable.h b/hashtable.h new file mode 100644 index 0000000..be45964 --- /dev/null +++ b/hashtable.h @@ -0,0 +1,18 @@ +#ifndef HASHTABLE +#define HASHTABLE + +typedef struct HashPair { + char* key; + void* value; +} pair_t; +typedef struct HashTable { + pair_t** pairs; + int capacity; + int itemCount; +} hashtable_t; +unsigned int get_hash(char* str); +hashtable_t* init_hashtable(unsigned int capacity); +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair); +pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key); + +#endif diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..e48adda --- /dev/null +++ b/parse.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include "parse.h" +#include "hashtable.h" + +void symbol_add_arg(sym_t* symbol, sym_t* arg) { + symbol->argCount += 1; + if (symbol->argCount == 1) { + symbol->args = malloc(sizeof(sym_t*)); + } + else { + symbol->args = realloc(symbol->args, symbol->argCount * (sizeof(sym_t*))); + } + (symbol->args)[symbol->argCount - 1] = arg; +} +void symset_add_symbol(symset_t* symbolSet, sym_t* symbol) { + symbolSet->count += 1; + if (symbolSet->count == 1) { + symbolSet->symbols = malloc(sizeof(sym_t*)); + } + else { + symbolSet->symbols = realloc(symbolSet->symbols, symbolSet->count * (sizeof(sym_t*))); + } + (symbolSet->symbols)[symbolSet->count - 1] = symbol; +} +symset_t* parse_symbols(char** str) { + symset_t* symbolSet = malloc(sizeof(symset_t)); + symbolSet->count = 0; + while (1) { + /* clear whitespace */ + while (!isalnum(**str) && **str != '(' && **str != ')' && **str != '\0') { + (*str)++; + } + if (**str == ')') { + (*str)++; + if (**str == ';') { + (*str)++; + return symbolSet; + } + } + else if (**str == '\0') { + return symbolSet; + } + char* symbolName = calloc(30, sizeof(char)); + int i = 0; + while (1) { + symbolName[i] = **str; + if (**str == ',' || **str == ';') { + (*str)++; + symbolName[i] = '\0'; + sym_t* symbol = malloc(sizeof(sym_t)); + symbol->province = LITERAL; + symbol->name = symbolName; + symbol->argCount = 0; + symset_add_symbol(symbolSet, symbol); + break; + } + else if (**str == '(') { + (*str)++; + symbolName[i] = '\0'; + sym_t* symbol = malloc(sizeof(sym_t)); + symbol->province = KEY_REF; + if(i > 1) { + symbol->name = symbolName; + } + else { + symbol->name = "fork"; + } + symset_t* symbols = parse_symbols(str); + for (int s = 0; s < symbols->count; s++) { + symbol_add_arg(symbol, symbols->symbols[s]); + } + symset_add_symbol(symbolSet, symbol); + break; + } + i++; + (*str)++; + } + } +} +sym_t* parse_symbol_final(char* str) { + char** strp = malloc(sizeof(char**)); + *strp = str; + symset_t* finalSymset = parse_symbols(strp); + sym_t* root = malloc(sizeof(sym_t)); + root->name = "root"; + root->province = KEY_REF; + for (int s = 0; s < finalSymset->count; s++) { + symbol_add_arg(root, finalSymset->symbols[s]); + } + return root; +} +void write_symbol_visual(sym_t* symbol, int offset) { + for (int o = 0; o < offset; o++) { + printf(" "); + } + printf("%s (%s)\n", (char*)(symbol->name), symbol->province == 1 ? "KEY" : "LITERAL"); + for (int i = 0; i < symbol->argCount; i++) { + write_symbol_visual(symbol->args[i], offset + 4); + } +} diff --git a/parse.h b/parse.h new file mode 100644 index 0000000..44d1c0e --- /dev/null +++ b/parse.h @@ -0,0 +1,29 @@ +#ifndef PARSE +#define PARSE + +/* keyword hashes */ +#define VAR_H 2317739966u +#define DEFINE_H 1788839250 + +typedef enum SymbolProvince { + NO_PROVINCE, + KEY_REF, + LITERAL +} prov_t; +typedef struct Symbol { + prov_t province; + void* name; + struct Symbol** args; + int argCount; +} sym_t; +typedef struct SymbolSet { + sym_t** symbols; + int count; +} symset_t; +void symbol_add_arg(sym_t* symbol, sym_t* arg); +void symset_add_symbol(symset_t* symbolSet, sym_t* symbol); +symset_t* parse_symbols(char** str); +sym_t* parse_symbol_final(char* str); +void write_symbol_visual(sym_t* symbol, int offset); + +#endif diff --git a/precedent b/precedent new file mode 100755 index 0000000..cc1fba2 Binary files /dev/null and b/precedent differ diff --git a/precedent.c b/precedent.c new file mode 100644 index 0000000..df7ac33 --- /dev/null +++ b/precedent.c @@ -0,0 +1,11 @@ +#include +#include +#include "precedent.h" +#include "hashtable.h" +#include "parse.h" + +int main() { + sym_t* finalSymbol = parse_symbol_final("store(5; test;); print(read(test;);); (hello; hello2;);"); + write_symbol_visual(finalSymbol, 0); + return 0; +} diff --git a/precedent.h b/precedent.h new file mode 100644 index 0000000..4449f83 --- /dev/null +++ b/precedent.h @@ -0,0 +1,8 @@ +#include "parse.h" +#ifndef PRECEDENT +#define PRECEDENT + +void execute_imperative(sym_t symbol); +void* eval_symbol(sym_t symbol); + +#endif diff --git a/scope.c b/scope.c new file mode 100644 index 0000000..4cc5249 --- /dev/null +++ b/scope.c @@ -0,0 +1,20 @@ +#include +#include "scope.h" +#include "hashtable.h" + +scope_t* init_scope(scope_t parent) { + scope_t* scope = malloc(sizeof(scope_t)); + scope->hashtable = init_hashtable(1000); + *(scope->parent) = parent; + return scope; +} +pair_t* get_pair_global(char* key, scope_t* scope) { + while (scope->parent != NULL) { + pair_t* pair = hashtable_get_pair(scope->hashtable, key); + if (pair != NULL) { + return pair; + } + scope = scope->parent; + } + return NULL; +} diff --git a/scope.h b/scope.h new file mode 100644 index 0000000..7847e06 --- /dev/null +++ b/scope.h @@ -0,0 +1,13 @@ +#include "hashtable.h" +#ifndef SCOPE +#define SCOPE + +typedef struct Scope { + hashtable_t* hashtable; + struct Scope* parent; +} scope_t; +scope_t* init_scope(scope_t parent); +pair_t* get_pair_global(char* key, scope_t* scope); +pair_t* get_pair_local(char* key, scope_t* scope); + +#endif -- cgit v1.3.1