summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Makefile11
-rw-r--r--README1
-rw-r--r--example.pcdt3
-rw-r--r--hashtable.c34
-rw-r--r--hashtable.h18
-rw-r--r--parse.c103
-rw-r--r--parse.h29
-rwxr-xr-xprecedentbin0 -> 28848 bytes
-rw-r--r--precedent.c11
-rw-r--r--precedent.h8
-rw-r--r--scope.c20
-rw-r--r--scope.h13
13 files changed, 256 insertions, 0 deletions
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 <stdlib.h>
+#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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#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
--- /dev/null
+++ b/precedent
Binary files 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 <stdlib.h>
+#include <stdio.h>
+#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 <stdlib.h>
+#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