[examples] setup an examples base layer; sketch parser example

main
Allen Webster 2026-07-15 14:13:29 -07:00
parent 69b419b086
commit b755026ba6
12 changed files with 798 additions and 278 deletions

29
build_all_examples.sh Executable file
View File

@ -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

View File

@ -5,8 +5,10 @@
#define SY__MAIN 1
#include "symbol_set.h"
#include "examples.base.h"
#include "example1.h"
#include <stdio.h>
#include "examples.base.c"
COMMAND_SCRIPT(foo, "Generates foo and increments the foo counter"){
printf("foo, ");

View File

@ -1,30 +1,6 @@
#ifndef 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

121
examples/examples.base.c Normal file
View File

@ -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);
}

127
examples/examples.base.h Normal file
View File

@ -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

View File

@ -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
*/

View File

@ -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

View File

@ -6,73 +6,10 @@
#include "symbol_set.h"
#include "symbol_set.init.h"
#include "examples.base.h"
#include "hooks.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
////////////////////////////////
// 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);
}
#include "examples.base.c"
////////////////////////////////
// Pretend "Core API"

View File

@ -1,57 +1,6 @@
#ifndef 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

View File

@ -6,45 +6,10 @@
#include "symbol_set.h"
#include "symbol_set.init.h"
#include "examples.base.h"
#include "stack_machine.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
////////////////////////////////
// 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);
}
#include "examples.base.c"
////////////////////////////////
// Stack Machine

View File

@ -1,104 +1,6 @@
#ifndef 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

View File

@ -23,15 +23,22 @@ commands = {
.footer_panel = true, .save_dirty_files = true,
.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,
.win = "build\\example1", .linux = "build/example1", .mac = "build/example1"
},
.run_hooks = { .out = "*run*", .footer_panel = false, .save_dirty_files = false,
.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 = {
.F1 = "build_with_clang",
.F2 = "run_hooks",
.F1 = "build_all_examples",
.F2 = "run_expression_parser",
};