[examples] setup an examples base layer; sketch parser example
parent
69b419b086
commit
b755026ba6
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
code=$PWD
|
||||||
|
opts="-g -Wno-switch"
|
||||||
|
inc="-I$code/symbol_set"
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
echo example1
|
||||||
|
clang -c $code/examples/example1.c $opts $inc
|
||||||
|
./symbol_set.ld_meta example1.o
|
||||||
|
clang -o example1 $code/examples/example1.c $opts $inc -T sy.ld
|
||||||
|
|
||||||
|
echo stack_machine
|
||||||
|
clang -c $code/examples/stack_machine.c $opts $inc
|
||||||
|
./symbol_set.ld_meta stack_machine.o
|
||||||
|
clang -o stack_machine $code/examples/stack_machine.c $opts $inc -T sy.ld
|
||||||
|
|
||||||
|
echo hooks
|
||||||
|
clang -c $code/examples/hooks.c $opts $inc
|
||||||
|
./symbol_set.ld_meta hooks.o
|
||||||
|
clang -o hooks $code/examples/hooks.c $opts $inc -T sy.ld
|
||||||
|
|
||||||
|
echo expression_parser
|
||||||
|
clang -c $code/examples/expression_parser.c $opts $inc
|
||||||
|
./symbol_set.ld_meta expression_parser.o
|
||||||
|
clang -o expression_parser $code/examples/expression_parser.c $opts $inc -T sy.ld
|
||||||
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
#define SY__MAIN 1
|
#define SY__MAIN 1
|
||||||
#include "symbol_set.h"
|
#include "symbol_set.h"
|
||||||
|
|
||||||
|
#include "examples.base.h"
|
||||||
#include "example1.h"
|
#include "example1.h"
|
||||||
#include <stdio.h>
|
|
||||||
|
#include "examples.base.c"
|
||||||
|
|
||||||
COMMAND_SCRIPT(foo, "Generates foo and increments the foo counter"){
|
COMMAND_SCRIPT(foo, "Generates foo and increments the foo counter"){
|
||||||
printf("foo, ");
|
printf("foo, ");
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,6 @@
|
||||||
#ifndef EXAMPLE1_H
|
#ifndef EXAMPLE1_H
|
||||||
#define EXAMPLE1_H
|
#define EXAMPLE1_H
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Little Base Layer
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int8_t S8;
|
|
||||||
typedef int16_t S16;
|
|
||||||
typedef int32_t S32;
|
|
||||||
typedef int64_t S64;
|
|
||||||
typedef uint8_t U8;
|
|
||||||
typedef uint16_t U16;
|
|
||||||
typedef uint32_t U32;
|
|
||||||
typedef uint64_t U64;
|
|
||||||
typedef S8 B8;
|
|
||||||
typedef S16 B16;
|
|
||||||
typedef S32 B32;
|
|
||||||
typedef S64 B64;
|
|
||||||
typedef float F32;
|
|
||||||
typedef double F64;
|
|
||||||
|
|
||||||
typedef struct String8{
|
|
||||||
U8 *str;
|
|
||||||
U64 size;
|
|
||||||
} String8;
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Example Specifics
|
// Example Specifics
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
////////////////////////////////
|
||||||
|
// Typical Base Stuff
|
||||||
|
|
||||||
|
static B32
|
||||||
|
str8_match(String8 a, String8 b){
|
||||||
|
B32 result = 0;
|
||||||
|
if (a.size == b.size){
|
||||||
|
result = 1;
|
||||||
|
for (U64 i = 0; i < a.size; i += 1){
|
||||||
|
if (a.str[i] != b.str[i]){
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Arena
|
||||||
|
arena_alloc(U64 cap){
|
||||||
|
Arena arena = {0};
|
||||||
|
arena.memory = malloc(cap);
|
||||||
|
arena.cap = cap;
|
||||||
|
return(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
arena_push(Arena *arena, U64 size){
|
||||||
|
void *result = 0;
|
||||||
|
if (arena->pos + size <= arena->cap){
|
||||||
|
result = (U8*)arena->memory + arena->pos;
|
||||||
|
arena->pos += size;
|
||||||
|
arena->pos = (arena->pos + 7)&~7; // "round up to multiple of 8"
|
||||||
|
memset(result, 0, size);
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
arena_pop_to(Arena *arena, U64 pos){
|
||||||
|
if (pos < arena->pos){
|
||||||
|
arena->pos = (pos + 7)&~7; // "round up to multiple of 8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
arena_pop_amount(Arena *arena, U64 amount){
|
||||||
|
U64 pos = arena->pos;
|
||||||
|
U64 new_pos = 0;
|
||||||
|
if (pos > amount){
|
||||||
|
new_pos = pos - amount;
|
||||||
|
}
|
||||||
|
arena_pop_to(arena, new_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static U64
|
||||||
|
arena_pos(Arena *arena){
|
||||||
|
return(arena->pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8
|
||||||
|
str8_pushfv(Arena *arena, char *fmt, va_list args){
|
||||||
|
// in case we need to try a second time
|
||||||
|
va_list args2;
|
||||||
|
va_copy(args2, args);
|
||||||
|
|
||||||
|
// try to build the string in 1024 bytes
|
||||||
|
U64 buffer_size = 1024;
|
||||||
|
U8 *buffer = push_array(arena, U8, buffer_size);
|
||||||
|
U64 actual_size = vsnprintf((char*)buffer, buffer_size, fmt, args);
|
||||||
|
|
||||||
|
String8 result = {0};
|
||||||
|
if (actual_size < buffer_size){
|
||||||
|
// if first try worked, put back what we didn't use and finish
|
||||||
|
arena_pop_amount(arena, buffer_size - actual_size - 1);
|
||||||
|
result = (String8){buffer, actual_size};
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// if first try failed, reset and try again with correct size
|
||||||
|
arena_pop_amount(arena, buffer_size);
|
||||||
|
U8 *fixed_buffer = push_array(arena, U8, actual_size + 1);
|
||||||
|
U64 final_size = vsnprintf((char*)fixed_buffer, actual_size + 1, fmt, args2);
|
||||||
|
result = (String8){fixed_buffer, final_size};
|
||||||
|
}
|
||||||
|
|
||||||
|
// end args2
|
||||||
|
va_end(args2);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Symbol-Set Specific Upgrades
|
||||||
|
|
||||||
|
static void*
|
||||||
|
copy_strided(void *dst, U32 dst_stride,
|
||||||
|
void *src, U32 src_stride,
|
||||||
|
U32 count){
|
||||||
|
void *base_src = src;
|
||||||
|
void *base_dst = dst;
|
||||||
|
if (dst_stride != src_stride){
|
||||||
|
U32 size = Min(dst_stride, src_stride);
|
||||||
|
for (U32 i = 0; i < count; i += 1){
|
||||||
|
memcpy(dst, src, size);
|
||||||
|
dst = (U8*)dst + dst_stride;
|
||||||
|
src = (U8*)src + src_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
memcpy(dst, src, dst_stride*count);
|
||||||
|
}
|
||||||
|
return(base_dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
arena_push_symbol_set__raw(Arena *arena,
|
||||||
|
U32 size, void *src, U32 src_stride, U32 count){
|
||||||
|
void *dst = push_array(arena, U8, size*(count + 1));
|
||||||
|
copy_strided((U8*)dst + size, size, src, src_stride, count);
|
||||||
|
return(dst);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
#ifndef EXAMPLES_BASE_H
|
||||||
|
#define EXAMPLES_BASE_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Typical Base Stuff
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int8_t S8;
|
||||||
|
typedef int16_t S16;
|
||||||
|
typedef int32_t S32;
|
||||||
|
typedef int64_t S64;
|
||||||
|
typedef uint8_t U8;
|
||||||
|
typedef uint16_t U16;
|
||||||
|
typedef uint32_t U32;
|
||||||
|
typedef uint64_t U64;
|
||||||
|
typedef S8 B8;
|
||||||
|
typedef S16 B16;
|
||||||
|
typedef S32 B32;
|
||||||
|
typedef S64 B64;
|
||||||
|
typedef float F32;
|
||||||
|
typedef double F64;
|
||||||
|
|
||||||
|
typedef struct String8{
|
||||||
|
U8 *str;
|
||||||
|
U64 size;
|
||||||
|
} String8;
|
||||||
|
|
||||||
|
#define str8_const(S) {(U8*)(S), (U64)(sizeof(S) - 1)}
|
||||||
|
#define str8(s,z) (String8){(s), (z)}
|
||||||
|
|
||||||
|
static B32 str8_match(String8 a, String8 b);
|
||||||
|
|
||||||
|
typedef struct Arena{
|
||||||
|
void *memory;
|
||||||
|
U64 pos;
|
||||||
|
U64 cap;
|
||||||
|
} Arena;
|
||||||
|
|
||||||
|
static Arena arena_alloc(U64 cap);
|
||||||
|
static void* arena_push(Arena *arena, U64 size);
|
||||||
|
static void arena_pop_to(Arena *arena, U64 pos);
|
||||||
|
static void arena_pop_amount(Arena *arena, U64 amount);
|
||||||
|
static U64 arena_pos(Arena *arena);
|
||||||
|
|
||||||
|
#define push_array(a,T,c) (T*)arena_push((a), sizeof(T)*(c))
|
||||||
|
|
||||||
|
#define Min(a,b) ((a)<(b))?(a):(b)
|
||||||
|
|
||||||
|
// Macros: Linked Lists
|
||||||
|
|
||||||
|
#define DLLPushBack_NPZ(f,l,n,next,prev,nil)\
|
||||||
|
(((f) == (nil))?\
|
||||||
|
((f)=(l)=(n),(n)->next=(n)->prev=(nil)):\
|
||||||
|
((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=(nil)))
|
||||||
|
|
||||||
|
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(f,l,n,next,prev,0)
|
||||||
|
#define DLLPushFront(f,l,n) DLLPushBack_NPZ(l,f,n,prev,next,0)
|
||||||
|
|
||||||
|
#define DLLInsert_NPZ(f,l,p,n,next,prev,nil) \
|
||||||
|
(((p) != (l))?\
|
||||||
|
((n)->next = (p)->next,\
|
||||||
|
(n)->prev = (p),\
|
||||||
|
(p)->next->prev = (n),\
|
||||||
|
(p)->next = (n))\
|
||||||
|
:((n)->next = (nil),\
|
||||||
|
(n)->prev = (l),\
|
||||||
|
(l)->next = (n),\
|
||||||
|
(l) = (n)))
|
||||||
|
|
||||||
|
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(f,l,p,n,next,prev,0)
|
||||||
|
|
||||||
|
#define DLLRemove_NPZ(f,l,n,next,prev,nil)\
|
||||||
|
((f)==(n)?\
|
||||||
|
((f)==(l)?\
|
||||||
|
((f)=(l)=(nil)):\
|
||||||
|
((f)=(f)->next,(f)->prev=(nil))):\
|
||||||
|
(l)==(n)?\
|
||||||
|
((l)=(l)->prev,(l)->next=(nil)):\
|
||||||
|
((n)->next->prev=(n)->prev,\
|
||||||
|
(n)->prev->next=(n)->next))
|
||||||
|
|
||||||
|
#define DLLRemove(f,l,n) DLLRemove_NPZ(f,l,n,next,prev,0)
|
||||||
|
|
||||||
|
#define SLLQueuePush_NZ(f,l,n,next,nil) (((f)==(nil)?\
|
||||||
|
(f)=(l)=(n):\
|
||||||
|
((l)->next=(n),(l)=(n))),\
|
||||||
|
(n)->next=(nil))
|
||||||
|
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(f,l,n,next,0)
|
||||||
|
|
||||||
|
#define SLLQueuePushFront_NZ(f,l,n,next,nil) ((f)==(nil)?\
|
||||||
|
((f)=(l)=(n),(n)->next=(nil)):\
|
||||||
|
((n)->next=(f),(f)=(n)))
|
||||||
|
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(f,l,n,next,0)
|
||||||
|
|
||||||
|
#define SLLQueuePop_NZ(f,l,next,nil) ((f)==(l)?\
|
||||||
|
(f)=(l)=(nil):\
|
||||||
|
((f)=(f)->next))
|
||||||
|
#define SLLQueuePop(f,l) SLLQueuePop_NZ(f,l,next,0)
|
||||||
|
|
||||||
|
#define SLLStackPush_N(f,n,next) ((n)->next=(f),(f)=(n))
|
||||||
|
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
|
||||||
|
|
||||||
|
#define SLLStackPop_NZ(f,next,nil) ((f)==(nil)?(nil):\
|
||||||
|
((f)=(f)->next))
|
||||||
|
#define SLLStackPop(f) SLLStackPop_NZ(f,next,0)
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Symbol-Set Specific Upgrades
|
||||||
|
|
||||||
|
static void*copy_strided(void *dst, U32 dst_stride,
|
||||||
|
void *src, U32 src_stride,
|
||||||
|
U32 count);
|
||||||
|
|
||||||
|
static void*arena_push_symbol_set__raw(Arena *arena,
|
||||||
|
U32 size, void *src, U32 src_stride, U32 count);
|
||||||
|
|
||||||
|
#define arena_push_symbol_set(ar,S) (SyType(S)*) \
|
||||||
|
arena_push_symbol_set__raw((ar), sizeof(SyType(S)), SyFirst(S), SyStride(S), SyCount(S))
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EXAMPLES_BASE_H
|
||||||
|
|
@ -0,0 +1,345 @@
|
||||||
|
/*
|
||||||
|
** C Scripting - Expression Parser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SY__MAIN 1
|
||||||
|
#include "symbol_set.h"
|
||||||
|
#include "symbol_set.init.h"
|
||||||
|
|
||||||
|
#include "examples.base.h"
|
||||||
|
#include "expression_parser.h"
|
||||||
|
|
||||||
|
#include "examples.base.c"
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Operator Functions
|
||||||
|
|
||||||
|
static U32
|
||||||
|
exp_operator_id_from_string(String8 string){
|
||||||
|
// TODO(allen): bake accelerator ahead of time for this path
|
||||||
|
U32 operator_id = 0;
|
||||||
|
for (SyEachID(EXP_OPERATOR, id)){
|
||||||
|
EXP_Operator *op = SyAddressFromID(EXP_OPERATOR, id);
|
||||||
|
if (str8_match(op->token_str, string)){
|
||||||
|
operator_id = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(operator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Lexer Functions
|
||||||
|
|
||||||
|
static EXP_TokenArray
|
||||||
|
exp_lex(Arena *arena, String8 text){
|
||||||
|
// Static Map of char -> TokenKind
|
||||||
|
static U8 token_kind_table[127] = {0};
|
||||||
|
static B8 token_kinds_initialized = 0;
|
||||||
|
if (!token_kinds_initialized){
|
||||||
|
token_kind_table[' '] = token_kind_table['\n'] =
|
||||||
|
token_kind_table['\t'] = token_kind_table['\r'] =
|
||||||
|
token_kind_table['\f'] = token_kind_table['\v'] = EXP_TokenKind_Whitespace;
|
||||||
|
|
||||||
|
token_kind_table['`'] = token_kind_table['~'] =
|
||||||
|
token_kind_table['!'] = token_kind_table['@'] =
|
||||||
|
token_kind_table['#'] = token_kind_table['$'] =
|
||||||
|
token_kind_table['%'] = token_kind_table['^'] =
|
||||||
|
token_kind_table['&'] = token_kind_table['*'] =
|
||||||
|
token_kind_table['='] = token_kind_table['-'] =
|
||||||
|
token_kind_table['+'] = token_kind_table['\\'] =
|
||||||
|
token_kind_table['|'] = token_kind_table[':'] =
|
||||||
|
token_kind_table[','] = token_kind_table['<'] =
|
||||||
|
token_kind_table['.'] = token_kind_table['>'] =
|
||||||
|
token_kind_table['/'] = token_kind_table['?'] = EXP_TokenKind_Operator;
|
||||||
|
|
||||||
|
for (U32 i = 'a'; i <= 'z'; i += 1){
|
||||||
|
token_kind_table[i] = EXP_TokenKind_IDNum;
|
||||||
|
}
|
||||||
|
for (U32 i = 'A'; i <= 'Z'; i += 1){
|
||||||
|
token_kind_table[i] = EXP_TokenKind_IDNum;
|
||||||
|
}
|
||||||
|
for (U32 i = '0'; i <= '9'; i += 1){
|
||||||
|
token_kind_table[i] = EXP_TokenKind_IDNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
token_kind_table['('] = EXP_TokenKind_OpenParen|(1 << 7);
|
||||||
|
token_kind_table[')'] = EXP_TokenKind_CloseParen|(1 << 7);
|
||||||
|
token_kind_table['['] = EXP_TokenKind_OpenBracket|(1 << 7);
|
||||||
|
token_kind_table[']'] = EXP_TokenKind_CloseBracket|(1 << 7);
|
||||||
|
token_kind_table['{'] = EXP_TokenKind_OpenBrace|(1 << 7);
|
||||||
|
token_kind_table['}'] = EXP_TokenKind_CloseBrace|(1 << 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// over-allocate tokens
|
||||||
|
U32 token_cap = text.size + 1;
|
||||||
|
EXP_Token *tokens = push_array(arena, EXP_Token, token_cap);
|
||||||
|
|
||||||
|
// fill tokens array
|
||||||
|
EXP_Token *tp = tokens;
|
||||||
|
U8 *ptr = text.str;
|
||||||
|
U8 *opl = text.str + text.size;
|
||||||
|
for (;ptr < opl;){
|
||||||
|
U32 kind = EXP_TokenKind_IDNum;
|
||||||
|
if (*ptr < 127){
|
||||||
|
kind = token_kind_table[*ptr];
|
||||||
|
}
|
||||||
|
|
||||||
|
tp->pos = (U32)(ptr - text.str);
|
||||||
|
tp->kind = kind&~(1 << 7);
|
||||||
|
|
||||||
|
if (kind&(1 << 7)){
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for (ptr += 1;
|
||||||
|
ptr < opl && token_kind_table[*ptr] == kind;
|
||||||
|
ptr += 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tp += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp->pos = (U32)text.size;
|
||||||
|
tp->kind = EXP_TokenKind_EndOfFile;
|
||||||
|
tp += 1;
|
||||||
|
|
||||||
|
// put back extra memory
|
||||||
|
U32 token_count = (U32)(tp - tokens);
|
||||||
|
arena_pop_amount(arena, sizeof(*tokens)*(token_cap - token_count));
|
||||||
|
|
||||||
|
// arrange as result
|
||||||
|
EXP_TokenArray result = {0};
|
||||||
|
result.tokens = tokens;
|
||||||
|
result.count = token_count - 1;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Parser Functions
|
||||||
|
|
||||||
|
EXP_PRECEDENCE(1, Multiplicative);
|
||||||
|
EXP_PRECEDENCE(2, Additive);
|
||||||
|
EXP_PRECEDENCE(3, Assignment, .right_to_left = 1);
|
||||||
|
|
||||||
|
EXP_OPERATOR(Multiply, "*", Multiplicative);
|
||||||
|
EXP_OPERATOR(Divide, "/", Multiplicative);
|
||||||
|
EXP_OPERATOR(Modulo, "%", Multiplicative);
|
||||||
|
EXP_OPERATOR(Add, "+", Additive);
|
||||||
|
EXP_OPERATOR(Subtract, "-", Additive);
|
||||||
|
EXP_OPERATOR(Assign, "=", Assignment);
|
||||||
|
EXP_OPERATOR(MulAssign, "*=", Assignment);
|
||||||
|
EXP_OPERATOR(DivAssign, "/=", Assignment);
|
||||||
|
EXP_OPERATOR(AddAssign, "+=", Assignment);
|
||||||
|
EXP_OPERATOR(SubAssign, "-=", Assignment);
|
||||||
|
|
||||||
|
static EXP_ParseNode*
|
||||||
|
exp_parse(Arena *arena, String8 text, EXP_TokenArray tokens){
|
||||||
|
EXP_ParseCtx ctx = {0};
|
||||||
|
ctx.text = text;
|
||||||
|
ctx.tokens = tokens;
|
||||||
|
ctx.token = tokens.tokens;
|
||||||
|
|
||||||
|
EXP_ParseNode *result = exp__parse_op(arena, &ctx);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EXP_ParseNode*
|
||||||
|
exp__parse_op_rec(Arena *arena, EXP_ParseCtx *ctx,
|
||||||
|
EXP_ParseNode *left, U32 max_precedence_level){
|
||||||
|
// read first operator
|
||||||
|
exp__parse_skip_whitespace(ctx);
|
||||||
|
EXP_OperatorRead peak_op = exp__parse_read_operator(ctx);
|
||||||
|
|
||||||
|
for (;;){
|
||||||
|
EXP_OperatorRead left_op = peak_op;
|
||||||
|
|
||||||
|
// end loop when precedence level increases (or no operator next)
|
||||||
|
if (left_op.operator_id == 0 ||
|
||||||
|
left_op.precedence_level > max_precedence_level){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume left op
|
||||||
|
ctx->token += 1;
|
||||||
|
|
||||||
|
// read right leaf
|
||||||
|
exp__parse_skip_whitespace(ctx);
|
||||||
|
EXP_ParseNode *right = exp__parse_leaf(arena, ctx);
|
||||||
|
|
||||||
|
// apply stickier right hand operators
|
||||||
|
for (;;){
|
||||||
|
|
||||||
|
// read right operator
|
||||||
|
exp__parse_skip_whitespace(ctx);
|
||||||
|
peak_op = exp__parse_read_operator(ctx);
|
||||||
|
|
||||||
|
// check precedence
|
||||||
|
if (peak_op.operator_id == 0 ||
|
||||||
|
peak_op.precedence_level > left_op.precedence_level ||
|
||||||
|
(peak_op.precedence_level == left_op.precedence_level && !peak_op.right_to_left)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively fold onto right
|
||||||
|
right = exp__parse_op_rec(arena, ctx, right, peak_op.precedence_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
// combine left & right with operator
|
||||||
|
{
|
||||||
|
EXP_ParseNode *node = push_array(arena, EXP_ParseNode, 1);
|
||||||
|
node->kind = EXP_ParseNodeKind_Operator;
|
||||||
|
node->op.operator_id = left_op.operator_id;
|
||||||
|
node->op.child[0] = left;
|
||||||
|
node->op.child[1] = right;
|
||||||
|
left = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:;
|
||||||
|
return(left);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EXP_ParseNode*
|
||||||
|
exp__parse_op(Arena *arena, EXP_ParseCtx *ctx){
|
||||||
|
EXP_ParseNode *left = exp__parse_leaf(arena, ctx);
|
||||||
|
EXP_ParseNode *result = exp__parse_op_rec(arena, ctx, left, 3);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EXP_ParseNode*
|
||||||
|
exp__parse_leaf(Arena *arena, EXP_ParseCtx *ctx){
|
||||||
|
EXP_ParseNode *result = 0;
|
||||||
|
|
||||||
|
exp__parse_skip_whitespace(ctx);
|
||||||
|
|
||||||
|
// check next token
|
||||||
|
switch (ctx->token->kind){
|
||||||
|
case EXP_TokenKind_OpenParen: {
|
||||||
|
ctx->token += 1;
|
||||||
|
result = exp__parse_op(arena, ctx);
|
||||||
|
if (ctx->error) goto done;
|
||||||
|
if (ctx->token->kind == EXP_TokenKind_CloseParen){
|
||||||
|
ctx->token += 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
exp__parse_errorf(arena, ctx, "Expected ')'");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EXP_TokenKind_IDNum: {
|
||||||
|
result = push_array(arena, EXP_ParseNode, 1);
|
||||||
|
result->kind = EXP_ParseNodeKind_Leaf;
|
||||||
|
result->leaf.token_idx = (U32)(ctx->token - ctx->tokens.tokens);
|
||||||
|
ctx->token += 1;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
exp__parse_errorf(Arena *arena, EXP_ParseCtx *ctx, char *fmt, ...){
|
||||||
|
if (ctx->error == 0){
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 string = str8_pushfv(arena, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
ctx->error = 1;
|
||||||
|
ctx->error_token_idx = (U32)(ctx->token - ctx->tokens.tokens);
|
||||||
|
ctx->error_message = string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
exp__parse_skip_whitespace(EXP_ParseCtx *ctx){
|
||||||
|
if (ctx->token->kind == EXP_TokenKind_Whitespace){
|
||||||
|
ctx->token += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static EXP_OperatorRead
|
||||||
|
exp__parse_read_operator(EXP_ParseCtx *ctx){
|
||||||
|
EXP_OperatorRead result = {0};
|
||||||
|
if (ctx->token->kind == EXP_TokenKind_Operator){
|
||||||
|
String8 operator_text = str8(ctx->text.str + ctx->token->pos,
|
||||||
|
(ctx->token + 1)->pos - ctx->token->pos);
|
||||||
|
result.operator_id = exp_operator_id_from_string(operator_text);
|
||||||
|
|
||||||
|
if (result.operator_id != 0){
|
||||||
|
// TODO(allen): [operator] -> precedence_level accelerator
|
||||||
|
EXP_Operator *op = SyAddressFromID(EXP_OPERATOR, result.operator_id);
|
||||||
|
EXP_Precedence *precedence = SyAddressFromID(EXP_PRECEDENCE, op->precedence_id);
|
||||||
|
result.precedence_level = precedence->order;
|
||||||
|
result.right_to_left = precedence->right_to_left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
exp_parse_node_print(String8 text, EXP_TokenArray tokens,
|
||||||
|
EXP_ParseNode *node, S32 indent){
|
||||||
|
printf("%.*s", indent, " ");
|
||||||
|
switch (node->kind){
|
||||||
|
case EXP_ParseNodeKind_Operator: {
|
||||||
|
EXP_Operator *op = SyAddressFromID(EXP_OPERATOR, node->op.operator_id);
|
||||||
|
printf("%.*s\n", (U32)op->token_str.size, op->token_str.str);
|
||||||
|
exp_parse_node_print(text, tokens, node->op.child[0], indent + 1);
|
||||||
|
exp_parse_node_print(text, tokens, node->op.child[1], indent + 1);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EXP_ParseNodeKind_Leaf: {
|
||||||
|
EXP_Token *token = &tokens.tokens[node->leaf.token_idx];
|
||||||
|
String8 string = str8(text.str + token->pos, (token + 1)->pos - token->pos);
|
||||||
|
printf("%.*s\n", (U32)string.size, string.str);
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Entrpy Point
|
||||||
|
|
||||||
|
int main(void){
|
||||||
|
sy__run_init();
|
||||||
|
|
||||||
|
Arena arena = arena_alloc((10 << 20));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
String8 text = str8_const("((FooBar + 100 ** 3 ^;;\r\n\t\t 17){{[[?/:::~`]]}})");
|
||||||
|
EXP_TokenArray tokens = exp_lex(&arena, text);
|
||||||
|
|
||||||
|
for (U32 i = 0; i < tokens.count; i += 1){
|
||||||
|
EXP_Token *token = &tokens.tokens[i];
|
||||||
|
char *token_kind_str = 0;
|
||||||
|
switch (token->kind){
|
||||||
|
#define X(N) case EXP_TokenKind_##N: token_kind_str = #N; break;
|
||||||
|
EXP_TokenKindXList(X)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
U32 token_size = (token + 1)->pos - token->pos;
|
||||||
|
printf("TOKEN %s: '%.*s'\n", token_kind_str, token_size, text.str + token->pos);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String8 text = str8_const("1 + 2 = a - b + c /= a + b * c = (a + b) / (x += c) = d");
|
||||||
|
EXP_TokenArray tokens = exp_lex(&arena, text);
|
||||||
|
EXP_ParseNode *root = exp_parse(&arena, text, tokens);
|
||||||
|
|
||||||
|
exp_parse_node_print(text, tokens, root, 0);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO
|
||||||
|
** C-Scripted Interpretations
|
||||||
|
**
|
||||||
|
** C-Scripted Prefix Postfix Operators
|
||||||
|
**
|
||||||
|
** C-Scripted Bracket Operators
|
||||||
|
**
|
||||||
|
** C-Scripted Structure Builder
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
#ifndef EXPRESSION_PARSER_H
|
||||||
|
#define EXPRESSION_PARSER_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Operators
|
||||||
|
|
||||||
|
//// PRECEDENCE ////
|
||||||
|
|
||||||
|
typedef struct EXP_Precedence{
|
||||||
|
String8 name;
|
||||||
|
U32 order;
|
||||||
|
B32 right_to_left;
|
||||||
|
} EXP_Precedence;
|
||||||
|
|
||||||
|
#define SYMBOL_SET_DEFINE EXP_PRECEDENCE
|
||||||
|
#define EXP_PRECEDENCE_Type EXP_Precedence
|
||||||
|
#define EXP_PRECEDENCE_elf_section ".sy.precedence"
|
||||||
|
#define EXP_PRECEDENCE_coff_a_section ".sy$precedence_a"
|
||||||
|
#define EXP_PRECEDENCE_coff_m_section ".sy$precedence_m"
|
||||||
|
#define EXP_PRECEDENCE_coff_z_section ".sy$precedence_z"
|
||||||
|
#define EXP_PRECEDENCE_marker precedence
|
||||||
|
#include "symbol_set.define.h"
|
||||||
|
|
||||||
|
#define EXP_PRECEDENCE(ord,N,...) \
|
||||||
|
SyDefine(EXP_PRECEDENCE, N) = { .order = (ord), .name = str8_const(#N), __VA_ARGS__ }
|
||||||
|
|
||||||
|
//// OPERATOR ////
|
||||||
|
|
||||||
|
typedef struct EXP_Operator{
|
||||||
|
String8 name;
|
||||||
|
String8 token_str;
|
||||||
|
SY__UAddr precedence_id;
|
||||||
|
} EXP_Operator;
|
||||||
|
|
||||||
|
#define SYMBOL_SET_DEFINE EXP_OPERATOR
|
||||||
|
#define EXP_OPERATOR_Type EXP_Operator
|
||||||
|
#define EXP_OPERATOR_elf_section ".sy.operator"
|
||||||
|
#define EXP_OPERATOR_coff_a_section ".sy$operator_a"
|
||||||
|
#define EXP_OPERATOR_coff_m_section ".sy$operator_m"
|
||||||
|
#define EXP_OPERATOR_coff_z_section ".sy$operator_z"
|
||||||
|
#define EXP_OPERATOR_marker operator
|
||||||
|
#include "symbol_set.define.h"
|
||||||
|
|
||||||
|
#define EXP_OPERATOR(N,str,P) \
|
||||||
|
SyDefine(EXP_OPERATOR, N) = { .name = str8_const(#N), \
|
||||||
|
.token_str = str8_const(str), \
|
||||||
|
.precedence_id = SyRaw(EXP_PRECEDENCE, P) }
|
||||||
|
|
||||||
|
#if SY__MAIN
|
||||||
|
SY_INIT(EXP_OPERATOR){
|
||||||
|
for (SyEach(EXP_OPERATOR, op)){
|
||||||
|
op->precedence_id = SyIDFromRaw(EXP_PRECEDENCE, op->precedence_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Operator Functions
|
||||||
|
|
||||||
|
static U32 exp_operator_id_from_string(String8 string);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Lexer Types
|
||||||
|
|
||||||
|
#define EXP_TokenKindXList(X) \
|
||||||
|
X(Error)\
|
||||||
|
X(EndOfFile)\
|
||||||
|
X(Whitespace)\
|
||||||
|
X(IDNum)\
|
||||||
|
X(Operator)\
|
||||||
|
X(OpenParen)\
|
||||||
|
X(CloseParen)\
|
||||||
|
X(OpenBracket)\
|
||||||
|
X(CloseBracket)\
|
||||||
|
X(OpenBrace)\
|
||||||
|
X(CloseBrace)
|
||||||
|
|
||||||
|
typedef enum EXP_TokenKind{
|
||||||
|
#define X(N) EXP_TokenKind_##N,
|
||||||
|
EXP_TokenKindXList(X)
|
||||||
|
#undef X
|
||||||
|
EXP_TokenKind_COUNT
|
||||||
|
} EXP_TokenKind;
|
||||||
|
|
||||||
|
typedef struct EXP_Token{
|
||||||
|
EXP_TokenKind kind;
|
||||||
|
U32 pos;
|
||||||
|
} EXP_Token;
|
||||||
|
|
||||||
|
typedef struct EXP_TokenArray{
|
||||||
|
EXP_Token *tokens;
|
||||||
|
U64 count;
|
||||||
|
} EXP_TokenArray;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Lexer Functions
|
||||||
|
|
||||||
|
static EXP_TokenArray exp_lex(Arena *arena, String8 text);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Parser Types
|
||||||
|
|
||||||
|
#define EXP_ParseNodeKindXList(X)\
|
||||||
|
X(NULL)\
|
||||||
|
X(Operator)\
|
||||||
|
X(Leaf)
|
||||||
|
|
||||||
|
typedef enum EXP_ParseNodeKind{
|
||||||
|
#define X(N) EXP_ParseNodeKind_##N,
|
||||||
|
EXP_ParseNodeKindXList(X)
|
||||||
|
#undef X
|
||||||
|
EXP_ParseNodeKind_COUNT
|
||||||
|
} EXP_ParseNodeKind;
|
||||||
|
|
||||||
|
typedef struct EXP_ParseNode{
|
||||||
|
EXP_ParseNodeKind kind;
|
||||||
|
union{
|
||||||
|
struct{
|
||||||
|
U32 operator_id;
|
||||||
|
struct EXP_ParseNode *child[2];
|
||||||
|
} op;
|
||||||
|
struct{
|
||||||
|
U32 token_idx;
|
||||||
|
} leaf;
|
||||||
|
};
|
||||||
|
} EXP_ParseNode;
|
||||||
|
|
||||||
|
typedef struct EXP_ParseCtx{
|
||||||
|
String8 text;
|
||||||
|
EXP_TokenArray tokens;
|
||||||
|
EXP_Token *token;
|
||||||
|
B32 error;
|
||||||
|
U32 error_token_idx;
|
||||||
|
String8 error_message;
|
||||||
|
} EXP_ParseCtx;
|
||||||
|
|
||||||
|
typedef struct EXP_OperatorRead{
|
||||||
|
U32 operator_id;
|
||||||
|
U32 precedence_level;
|
||||||
|
B32 right_to_left;
|
||||||
|
} EXP_OperatorRead;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Parser Functions
|
||||||
|
|
||||||
|
static EXP_ParseNode* exp_parse(Arena *arena, String8 text, EXP_TokenArray tokens);
|
||||||
|
|
||||||
|
static EXP_ParseNode* exp__parse_op_rec(Arena *arena, EXP_ParseCtx *ctx,
|
||||||
|
EXP_ParseNode *left, U32 precedence_level);
|
||||||
|
static EXP_ParseNode* exp__parse_op(Arena *arena, EXP_ParseCtx *ctx);
|
||||||
|
static EXP_ParseNode* exp__parse_leaf(Arena *arena, EXP_ParseCtx *ctx);
|
||||||
|
|
||||||
|
static void exp__parse_errorf(Arena *arena, EXP_ParseCtx *ctx, char *fmt, ...);
|
||||||
|
static void exp__parse_skip_whitespace(EXP_ParseCtx *ctx);
|
||||||
|
static EXP_OperatorRead exp__parse_read_operator(EXP_ParseCtx *ctx);
|
||||||
|
|
||||||
|
static void exp_parse_node_print(String8 text, EXP_TokenArray tokens,
|
||||||
|
EXP_ParseNode *node, S32 indent);
|
||||||
|
|
||||||
|
#endif //EXPRESSION_PARSER_H
|
||||||
|
|
@ -6,73 +6,10 @@
|
||||||
#include "symbol_set.h"
|
#include "symbol_set.h"
|
||||||
#include "symbol_set.init.h"
|
#include "symbol_set.init.h"
|
||||||
|
|
||||||
|
#include "examples.base.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
////////////////////////////////
|
#include "examples.base.c"
|
||||||
// Little Base Layer
|
|
||||||
|
|
||||||
static Arena
|
|
||||||
arena_alloc(U64 cap){
|
|
||||||
Arena arena = {0};
|
|
||||||
arena.memory = malloc(cap);
|
|
||||||
arena.cap = cap;
|
|
||||||
return(arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
arena_push(Arena *arena, U64 size){
|
|
||||||
void *result = 0;
|
|
||||||
if (arena->pos + size <= arena->cap){
|
|
||||||
result = (U8*)arena->memory + arena->pos;
|
|
||||||
arena->pos += size;
|
|
||||||
arena->pos = (arena->pos + 7)&~7; // "round up to multiple of 8"
|
|
||||||
memset(result, 0, size);
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
arena_pop_to(Arena *arena, U64 pos){
|
|
||||||
if (pos < arena->pos){
|
|
||||||
arena->pos = (pos + 7)&~7; // "round up to multiple of 8"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static U64
|
|
||||||
arena_pos(Arena *arena){
|
|
||||||
return(arena->pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
copy_strided(void *dst, U32 dst_stride,
|
|
||||||
void *src, U32 src_stride,
|
|
||||||
U32 count){
|
|
||||||
void *base_src = src;
|
|
||||||
void *base_dst = dst;
|
|
||||||
if (dst_stride != src_stride){
|
|
||||||
U32 size = Min(dst_stride, src_stride);
|
|
||||||
for (U32 i = 0; i < count; i += 1){
|
|
||||||
memcpy(dst, src, size);
|
|
||||||
dst = (U8*)dst + dst_stride;
|
|
||||||
src = (U8*)src + src_stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
memcpy(dst, src, dst_stride*count);
|
|
||||||
}
|
|
||||||
return(base_dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
arena_push_symbol_set__raw(Arena *arena,
|
|
||||||
U32 size, void *src, U32 src_stride, U32 count){
|
|
||||||
void *dst = push_array(arena, U8, size*(count + 1));
|
|
||||||
copy_strided((U8*)dst + size, size, src, src_stride, count);
|
|
||||||
return(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Pretend "Core API"
|
// Pretend "Core API"
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,6 @@
|
||||||
#ifndef HOOKS_H
|
#ifndef HOOKS_H
|
||||||
#define HOOKS_H
|
#define HOOKS_H
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Little Base Layer
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int8_t S8;
|
|
||||||
typedef int16_t S16;
|
|
||||||
typedef int32_t S32;
|
|
||||||
typedef int64_t S64;
|
|
||||||
typedef uint8_t U8;
|
|
||||||
typedef uint16_t U16;
|
|
||||||
typedef uint32_t U32;
|
|
||||||
typedef uint64_t U64;
|
|
||||||
typedef S8 B8;
|
|
||||||
typedef S16 B16;
|
|
||||||
typedef S32 B32;
|
|
||||||
typedef S64 B64;
|
|
||||||
typedef float F32;
|
|
||||||
typedef double F64;
|
|
||||||
|
|
||||||
typedef struct String8{
|
|
||||||
U8 *str;
|
|
||||||
U64 size;
|
|
||||||
} String8;
|
|
||||||
|
|
||||||
#define str8_const(S) {(U8*)(S), (U64)(sizeof(S) - 1)}
|
|
||||||
|
|
||||||
typedef struct Arena{
|
|
||||||
void *memory;
|
|
||||||
U64 pos;
|
|
||||||
U64 cap;
|
|
||||||
} Arena;
|
|
||||||
|
|
||||||
static Arena arena_alloc(U64 cap);
|
|
||||||
static void* arena_push(Arena *arena, U64 size);
|
|
||||||
static void arena_pop_to(Arena *arena, U64 pos);
|
|
||||||
static U64 arena_pos(Arena *arena);
|
|
||||||
|
|
||||||
#define push_array(a,T,c) (T*)arena_push((a), sizeof(T)*(c))
|
|
||||||
|
|
||||||
static void*copy_strided(void *dst, U32 dst_stride,
|
|
||||||
void *src, U32 src_stride,
|
|
||||||
U32 count);
|
|
||||||
|
|
||||||
static void*arena_push_symbol_set__raw(Arena *arena,
|
|
||||||
U32 size, void *src, U32 src_stride, U32 count);
|
|
||||||
|
|
||||||
#define arena_push_symbol_set(ar,S) (SyType(S)*) \
|
|
||||||
arena_push_symbol_set__raw((ar), sizeof(SyType(S)), SyFirst(S), SyStride(S), SyCount(S))
|
|
||||||
|
|
||||||
#define Min(a,b) ((a)<(b))?(a):(b)
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Hooks
|
// Hooks
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,45 +6,10 @@
|
||||||
#include "symbol_set.h"
|
#include "symbol_set.h"
|
||||||
#include "symbol_set.init.h"
|
#include "symbol_set.init.h"
|
||||||
|
|
||||||
|
#include "examples.base.h"
|
||||||
#include "stack_machine.h"
|
#include "stack_machine.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
////////////////////////////////
|
#include "examples.base.c"
|
||||||
// Little Base Layer
|
|
||||||
|
|
||||||
static Arena
|
|
||||||
arena_alloc(U64 cap){
|
|
||||||
Arena arena = {0};
|
|
||||||
arena.memory = malloc(cap);
|
|
||||||
arena.cap = cap;
|
|
||||||
return(arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
arena_push(Arena *arena, U64 size){
|
|
||||||
void *result = 0;
|
|
||||||
if (arena->pos + size <= arena->cap){
|
|
||||||
result = (U8*)arena->memory + arena->pos;
|
|
||||||
arena->pos += size;
|
|
||||||
arena->pos = (arena->pos + 7)&~7; // "round up to multiple of 8"
|
|
||||||
memset(result, 0, size);
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
arena_pop_to(Arena *arena, U64 pos){
|
|
||||||
if (pos < arena->pos){
|
|
||||||
arena->pos = (pos + 7)&~7; // "round up to multiple of 8"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static U64
|
|
||||||
arena_pos(Arena *arena){
|
|
||||||
return(arena->pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Stack Machine
|
// Stack Machine
|
||||||
|
|
|
||||||
|
|
@ -1,104 +1,6 @@
|
||||||
#ifndef STACK_MACHINE_H
|
#ifndef STACK_MACHINE_H
|
||||||
#define STACK_MACHINE_H
|
#define STACK_MACHINE_H
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Little Base Layer
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int8_t S8;
|
|
||||||
typedef int16_t S16;
|
|
||||||
typedef int32_t S32;
|
|
||||||
typedef int64_t S64;
|
|
||||||
typedef uint8_t U8;
|
|
||||||
typedef uint16_t U16;
|
|
||||||
typedef uint32_t U32;
|
|
||||||
typedef uint64_t U64;
|
|
||||||
typedef S8 B8;
|
|
||||||
typedef S16 B16;
|
|
||||||
typedef S32 B32;
|
|
||||||
typedef S64 B64;
|
|
||||||
typedef float F32;
|
|
||||||
typedef double F64;
|
|
||||||
|
|
||||||
typedef struct String8{
|
|
||||||
U8 *str;
|
|
||||||
U64 size;
|
|
||||||
} String8;
|
|
||||||
|
|
||||||
#define str8_const(S) {(U8*)(S), (U64)(sizeof(S) - 1)}
|
|
||||||
|
|
||||||
typedef struct Arena{
|
|
||||||
void *memory;
|
|
||||||
U64 pos;
|
|
||||||
U64 cap;
|
|
||||||
} Arena;
|
|
||||||
|
|
||||||
static Arena arena_alloc(U64 cap);
|
|
||||||
static void* arena_push(Arena *arena, U64 size);
|
|
||||||
static void arena_pop_to(Arena *arena, U64 pos);
|
|
||||||
static U64 arena_pos(Arena *arena);
|
|
||||||
|
|
||||||
#define push_array(a,T,c) (T*)arena_push((a), sizeof(T)*(c))
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Macros: Linked Lists
|
|
||||||
|
|
||||||
#define DLLPushBack_NPZ(f,l,n,next,prev,nil)\
|
|
||||||
(((f) == (nil))?\
|
|
||||||
((f)=(l)=(n),(n)->next=(n)->prev=(nil)):\
|
|
||||||
((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=(nil)))
|
|
||||||
|
|
||||||
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(f,l,n,next,prev,0)
|
|
||||||
#define DLLPushFront(f,l,n) DLLPushBack_NPZ(l,f,n,prev,next,0)
|
|
||||||
|
|
||||||
#define DLLInsert_NPZ(f,l,p,n,next,prev,nil) \
|
|
||||||
(((p) != (l))?\
|
|
||||||
((n)->next = (p)->next,\
|
|
||||||
(n)->prev = (p),\
|
|
||||||
(p)->next->prev = (n),\
|
|
||||||
(p)->next = (n))\
|
|
||||||
:((n)->next = (nil),\
|
|
||||||
(n)->prev = (l),\
|
|
||||||
(l)->next = (n),\
|
|
||||||
(l) = (n)))
|
|
||||||
|
|
||||||
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(f,l,p,n,next,prev,0)
|
|
||||||
|
|
||||||
#define DLLRemove_NPZ(f,l,n,next,prev,nil)\
|
|
||||||
((f)==(n)?\
|
|
||||||
((f)==(l)?\
|
|
||||||
((f)=(l)=(nil)):\
|
|
||||||
((f)=(f)->next,(f)->prev=(nil))):\
|
|
||||||
(l)==(n)?\
|
|
||||||
((l)=(l)->prev,(l)->next=(nil)):\
|
|
||||||
((n)->next->prev=(n)->prev,\
|
|
||||||
(n)->prev->next=(n)->next))
|
|
||||||
|
|
||||||
#define DLLRemove(f,l,n) DLLRemove_NPZ(f,l,n,next,prev,0)
|
|
||||||
|
|
||||||
#define SLLQueuePush_NZ(f,l,n,next,nil) (((f)==(nil)?\
|
|
||||||
(f)=(l)=(n):\
|
|
||||||
((l)->next=(n),(l)=(n))),\
|
|
||||||
(n)->next=(nil))
|
|
||||||
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(f,l,n,next,0)
|
|
||||||
|
|
||||||
#define SLLQueuePushFront_NZ(f,l,n,next,nil) ((f)==(nil)?\
|
|
||||||
((f)=(l)=(n),(n)->next=(nil)):\
|
|
||||||
((n)->next=(f),(f)=(n)))
|
|
||||||
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(f,l,n,next,0)
|
|
||||||
|
|
||||||
#define SLLQueuePop_NZ(f,l,next,nil) ((f)==(l)?\
|
|
||||||
(f)=(l)=(nil):\
|
|
||||||
((f)=(f)->next))
|
|
||||||
#define SLLQueuePop(f,l) SLLQueuePop_NZ(f,l,next,0)
|
|
||||||
|
|
||||||
#define SLLStackPush_N(f,n,next) ((n)->next=(f),(f)=(n))
|
|
||||||
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
|
|
||||||
|
|
||||||
#define SLLStackPop_NZ(f,next,nil) ((f)==(nil)?(nil):\
|
|
||||||
((f)=(f)->next))
|
|
||||||
#define SLLStackPop(f) SLLStackPop_NZ(f,next,0)
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Stack Machine
|
// Stack Machine
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,22 @@ commands = {
|
||||||
.footer_panel = true, .save_dirty_files = true,
|
.footer_panel = true, .save_dirty_files = true,
|
||||||
.linux = "./build_ld_meta.sh", .mac = "./build_ld_meta.sh"
|
.linux = "./build_ld_meta.sh", .mac = "./build_ld_meta.sh"
|
||||||
},
|
},
|
||||||
|
.build_all_examples = { .out = "*compilation*",
|
||||||
|
.footer_panel = true, .save_dirty_files = true,
|
||||||
|
.linux = "./build_all_examples.sh", .mac = "./build_all_examples.sh"
|
||||||
|
},
|
||||||
.run_example1 = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
.run_example1 = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
||||||
.win = "build\\example1", .linux = "build/example1", .mac = "build/example1"
|
.win = "build\\example1", .linux = "build/example1", .mac = "build/example1"
|
||||||
},
|
},
|
||||||
.run_hooks = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
.run_hooks = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
||||||
.win = "build\\hooks", .linux = "build/hooks", .mac = "build/hooks"
|
.win = "build\\hooks", .linux = "build/hooks", .mac = "build/hooks"
|
||||||
},
|
},
|
||||||
|
.run_expression_parser = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
||||||
|
.win = "build\\expression_parser", .linux = "build/expression_parser", .mac = "build/expression_parser"
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
fkey_command = {
|
fkey_command = {
|
||||||
.F1 = "build_with_clang",
|
.F1 = "build_all_examples",
|
||||||
.F2 = "run_hooks",
|
.F2 = "run_expression_parser",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue