CYaRon! lang C Impls

Run Settings
LanguageC
Language Version
Run Command
#include "ctype.h" #include "stddef.h" #include "stdio.h" #include "stdlib.h" #include "string.h" typedef struct DynArr { void *items; size_t item_size; size_t item_cnts; size_t capacity; } DynArr; void da_init(DynArr *dyn_arr, size_t item_size, size_t capacity); DynArr *da_create(size_t item_size, size_t capacity); void *da_try_push_back(DynArr *dyn_arr); void *da_push_back(DynArr *dyn_arr, void *item); static inline void *da_get(DynArr *dyn_arr, size_t idx) { void *item = dyn_arr->items + idx * dyn_arr->item_size; return item; } static inline void da_set(DynArr *dyn_arr, size_t idx, void *item) { void *dest = dyn_arr->items + idx * dyn_arr->item_size; memcpy(dest, item, dyn_arr->item_size); return; } void da_free(DynArr *dyn_arr); typedef struct StrPoolNode { char *str; size_t len; char alloc_by_pool; } StrPoolNode; typedef struct StrPool { char *mempool; size_t mempool_offset; size_t mempool_size; DynArr pool_nodes; } StrPool; void str_pool_init(StrPool *pool, size_t mempool_size, size_t capacity); StrPool *str_pool_create(size_t mempool_size, size_t capacity); void str_pool_free(StrPool *str_pool); char *str_pool_intern(StrPool *str_pool, const char *string, size_t len); typedef struct VarIntData { int val; } VarIntData; typedef struct VarArrData { int *arr; } VarArrData; typedef union VarData { VarIntData i; VarArrData a; } VarData; typedef struct Interpreter { DynArr *stmts; DynArr *var_decls; } Interpreter; Interpreter *interpreter_create(DynArr *stmts, DynArr *var_decls); void interpreter_free(Interpreter *interpreter); void interpreter_execute(Interpreter *interpreter); enum TokType { TOK_EOF, TOK_IDENT, TOK_INT, TOK_PLUS, TOK_MINUS, TOK_COMMA, TOK_COLON, TOK_LBRACE, TOK_RBRACE, TOK_LBRACKET, TOK_RBRACKET, TOK_DOTDOT, TOK_KEYWORD_VARS, TOK_KEYWORD_SET, TOK_KEYWORD_YOSORO, TOK_KEYWORD_IHU, TOK_KEYWORD_HOR, TOK_KEYWORD_WHILE, TOK_KEYWORD_INT, TOK_KEYWORD_ARRAY, TOK_CMP_LT, TOK_CMP_GT, TOK_CMP_LE, TOK_CMP_GE, TOK_CMP_EQ, TOK_CMP_NEQ, }; typedef struct Token { enum TokType type; const char *str; } Token; typedef struct Lexer { char *src; size_t src_len; size_t ch_pos; DynArr toks; StrPool tok_val_pool; } Lexer; Lexer *lexer_create(char *src); void lexer_free(Lexer *lexer); void token_init(Token *tok, enum TokType tok_type, const char *str); Token *token_create(enum TokType tok_type, const char *str); void lexer_tokenize(Lexer *lexer); enum OperandTyp { OPERAND_INT_VAR, OPERAND_ARR_ELEM, }; enum ExprTermTyp { EXPR_TERM_CONST, EXPR_TERM_OPERAND, }; typedef struct Expr { DynArr terms; } Expr; typedef struct VarDecl VarDecl; typedef struct Operand { enum OperandTyp typ; size_t decl_idx; union { Expr idx_expr; }; } Operand; typedef struct ExprTerm { int coefficient; enum ExprTermTyp typ; union { int constant; Operand operand; }; } ExprTerm; enum StmtType { STMT_IHU_BLK = 0x00, STMT_WHILE_BLK, STMT_HOR_BLK, STMT_YOSORO_CMD = 0xf0, STMT_SET_CMD, }; enum VarType { VAR_INT, VAR_ARR, }; typedef struct VarDecl { enum VarType typ; VarData data; const char *name; struct { size_t start; size_t end; }; } VarDecl; typedef struct Cond { enum TokType typ; Expr left; Expr right; } Cond; typedef struct IhuStmt { Cond cond; DynArr stmts; } IhuStmt; typedef struct WhileStmt { Cond cond; DynArr stmts; } WhileStmt; typedef struct HorStmt { Operand var; Expr start; Expr end; DynArr stmts; } HorStmt; typedef struct YosoroStmt { Expr expr; } YosoroStmt; typedef struct SetStmt { Operand operand; Expr expr; } SetStmt; typedef struct Stmt { enum StmtType typ; union { IhuStmt ihu; WhileStmt while_stmt; HorStmt hor; YosoroStmt yosoro; SetStmt set; } inner; } Stmt; typedef struct Parser { DynArr *toks; size_t pos; DynArr stmts; DynArr var_decls; } Parser; Parser *parser_create(DynArr *toks); void parser_free(Parser *parser); size_t operand_finder(Parser *parser, const char *var_name, enum OperandTyp type); DynArr *parser_parse(Parser *parser); void var_decls_init_data(DynArr *var_decls) { for (int i = 0; i < var_decls->item_cnts; i++) { VarDecl *var_decl = da_get(var_decls, i); switch (var_decl->typ) { case VAR_INT: { VarIntData *int_data = &var_decl->data.i; int_data->val = 0; } break; case VAR_ARR: { VarArrData *arr_data = &var_decl->data.a; arr_data->arr = malloc((var_decl->end - var_decl->start + 1) * sizeof(int)); } break; } } } void var_decls_free_data(DynArr *var_decls) { for (int i = 0; i < var_decls->item_cnts; i++) { VarDecl *var_decl = da_get(var_decls, i); switch (var_decl->typ) { case VAR_INT: break; case VAR_ARR: { VarArrData *arr_data = &var_decl->data.a; free(arr_data->arr); } break; } } } Interpreter *interpreter_create(DynArr *stmts, DynArr *var_decls) { Interpreter *interpreter = malloc(sizeof(Interpreter)); interpreter->stmts = stmts; var_decls_init_data(var_decls); interpreter->var_decls = var_decls; return interpreter; } void interpreter_free(Interpreter *interpreter) { var_decls_free_data(interpreter->var_decls); free(interpreter); } int eval_expr(Interpreter *interpreter, Expr *expr); void write_operand(Interpreter *interpreter, Operand *operand, int data) { size_t decl_idx = operand->decl_idx; VarDecl *decl = da_get(interpreter->var_decls, decl_idx); switch (operand->typ) { case OPERAND_INT_VAR: decl->data.i.val = data; return; case OPERAND_ARR_ELEM: decl->data.a.arr[eval_expr(interpreter, &operand->idx_expr) - decl->start] = data; return; } } int read_operand(Interpreter *interpreter, Operand *operand) { size_t decl_idx = operand->decl_idx; VarDecl *decl = da_get(interpreter->var_decls, decl_idx); int data = 0; switch (operand->typ) { case OPERAND_INT_VAR: data = decl->data.i.val; break; case OPERAND_ARR_ELEM: data = decl->data.a .arr[eval_expr(interpreter, &operand->idx_expr) - decl->start]; break; } return data; } inline int eval_expr(Interpreter *interpreter, Expr *expr) { DynArr *terms = &expr->terms; int res = 0; for (int i = 0; i < terms->item_cnts; i++) { ExprTerm *term = da_get(terms, i); switch (term->typ) { case EXPR_TERM_CONST: res += term->coefficient * term->constant; break; case EXPR_TERM_OPERAND: res += term->coefficient * read_operand(interpreter, &term->operand); break; } } return res; } void execute_stmts(Interpreter *interpreter, DynArr *stmts); char execute_cond(Interpreter *interpreter, Cond *cond) { int left = eval_expr(interpreter, &cond->left); int right = eval_expr(interpreter, &cond->right); switch (cond->typ) { case TOK_CMP_LT: return left < right; case TOK_CMP_GT: return left > right; case TOK_CMP_LE: return left <= right; case TOK_CMP_GE: return left >= right; case TOK_CMP_EQ: return left == right; case TOK_CMP_NEQ: return left != right; default: return 0; } } void execute_stmt(Interpreter *interpreter, Stmt *stmt) { switch (stmt->typ) { case STMT_IHU_BLK: { IhuStmt *ihu = &stmt->inner.ihu; if (execute_cond(interpreter, &ihu->cond)) { execute_stmts(interpreter, &ihu->stmts); } } break; case STMT_WHILE_BLK: { WhileStmt *while_stmt = &stmt->inner.while_stmt; while (execute_cond(interpreter, &while_stmt->cond)) { execute_stmts(interpreter, &while_stmt->stmts); } } break; case STMT_HOR_BLK: { HorStmt *hor = &stmt->inner.hor; int start = eval_expr(interpreter, &hor->start); int end = eval_expr(interpreter, &hor->end); for (int i = start; i <= end; i++) { write_operand(interpreter, &hor->var, i); execute_stmts(interpreter, &hor->stmts); } write_operand(interpreter, &hor->var, end); } break; case STMT_YOSORO_CMD: { YosoroStmt *yosoro = &stmt->inner.yosoro; int res = eval_expr(interpreter, &yosoro->expr); printf("%d ", res); } break; case STMT_SET_CMD: { SetStmt *set = &stmt->inner.set; int res = eval_expr(interpreter, &set->expr); write_operand(interpreter, &set->operand, res); } break; } } void execute_stmts(Interpreter *interpreter, DynArr *stmts) { Stmt *stmt; for (int i = 0; i < stmts->item_cnts; i++) { stmt = da_get(stmts, i); execute_stmt(interpreter, stmt); } } void interpreter_execute(Interpreter *interpreter) { DynArr *stmts = interpreter->stmts; execute_stmts(interpreter, stmts); } Lexer *lexer_create(char *src) { Lexer *lexer = malloc(sizeof(Lexer)); str_pool_init(&lexer->tok_val_pool, 512, 16); lexer->src_len = strlen(src); lexer->src = src; lexer->ch_pos = 0; da_init(&lexer->toks, sizeof(Token), 128); return lexer; } void lexer_free(Lexer *lexer) { da_free(&lexer->toks); str_pool_free(&lexer->tok_val_pool); free(lexer); } void token_init(Token *tok, enum TokType tok_type, const char *str) { tok->type = tok_type; tok->str = str; return; } Token *token_create(enum TokType tok_type, const char *str) { Token *tok = malloc(sizeof(Token)); token_init(tok, tok_type, str); return tok; } inline static void add_token(Lexer *lexer, enum TokType tok_type, const char *val) { Token *tok = da_try_push_back(&lexer->toks); token_init(tok, tok_type, val); return; } inline static char is_identifier_char(char c) { return isalpha(c) || c == '_'; } const struct KeyWords { const enum TokType typ; const char *val; const size_t len; } keywords[] = { {TOK_KEYWORD_VARS, "vars", sizeof("vars") - 1}, {TOK_KEYWORD_SET, "set", sizeof("set") - 1}, {TOK_KEYWORD_YOSORO, "yosoro", sizeof("yosoro") - 1}, {TOK_KEYWORD_IHU, "ihu", sizeof("ihu") - 1}, {TOK_KEYWORD_HOR, "hor", sizeof("hor") - 1}, {TOK_KEYWORD_WHILE, "while", sizeof("while") - 1}, {TOK_KEYWORD_INT, "int", sizeof("int") - 1}, {TOK_KEYWORD_ARRAY, "array", sizeof("array") - 1}, {TOK_CMP_LT, "lt", sizeof("lt") - 1}, {TOK_CMP_GT, "gt", sizeof("gt") - 1}, {TOK_CMP_LE, "le", sizeof("le") - 1}, {TOK_CMP_GE, "ge", sizeof("ge") - 1}, {TOK_CMP_EQ, "eq", sizeof("eq") - 1}, {TOK_CMP_NEQ, "neq", sizeof("neq") - 1}, }; const size_t keyword_cnts = sizeof(keywords) / sizeof(*keywords); int check_keyword(const char *tok_val, size_t len) { for (int i = 0; i < keyword_cnts; ++i) { if (keywords[i].len == len && strncmp(tok_val, keywords[i].val, len) == 0) { return i; } } return -1; } void lexer_tokenize(Lexer *lexer) { while (lexer->ch_pos < lexer->src_len) { char ch = lexer->src[lexer->ch_pos]; if (isspace(ch)) { lexer->ch_pos++; continue; } if (isdigit(ch)) { size_t start = lexer->ch_pos; while (lexer->ch_pos < lexer->src_len && isdigit(lexer->src[lexer->ch_pos])) { lexer->ch_pos++; } size_t len = lexer->ch_pos - start; char *val = lexer->src + start; val = str_pool_intern(&lexer->tok_val_pool, val, len); add_token(lexer, TOK_INT, val); continue; } if (is_identifier_char(ch)) { size_t start = lexer->ch_pos; while (lexer->ch_pos < lexer->src_len && isalnum(lexer->src[lexer->ch_pos])) { lexer->ch_pos++; } size_t len = lexer->ch_pos - start; const char *val = lexer->src + start; int keyword_idx = check_keyword(val, len); enum TokType type; if (keyword_idx != -1) { type = keywords[keyword_idx].typ; val = keywords[keyword_idx].val; } else { type = TOK_IDENT; val = str_pool_intern(&lexer->tok_val_pool, val, len); } add_token(lexer, type, val); continue; } switch (ch) { case '+': add_token(lexer, TOK_PLUS, "'+'"); break; case '-': add_token(lexer, TOK_MINUS, "'-'"); break; case ',': add_token(lexer, TOK_COMMA, "','"); break; case ':': add_token(lexer, TOK_COLON, "':'"); break; case '{': add_token(lexer, TOK_LBRACE, "'{'"); break; case '}': add_token(lexer, TOK_RBRACE, "'}'"); break; case '[': add_token(lexer, TOK_LBRACKET, "'['"); break; case ']': add_token(lexer, TOK_RBRACKET, "']'"); break; default: if (ch == '.' && lexer->ch_pos + 1 < lexer->src_len && lexer->src[lexer->ch_pos + 1] == '.') { add_token(lexer, TOK_DOTDOT, ".."); lexer->ch_pos += 2; continue; } else { lexer->ch_pos++; continue; } break; } lexer->ch_pos++; } add_token(lexer, TOK_EOF, NULL); return; } void read_src(char **src) { // FILE *input = stdin; // fseek(input, 0, SEEK_END); // size_t input_size = ftell(input); // fseek(input, 0, SEEK_SET); // *src = malloc(input_size + 1); // fread(*src, 512, input_size / 512, input); // size_t remaining = input_size % 512; // fread(*src + input_size - remaining, 1, remaining, input); // (*src)[input_size] = '\0'; const char test_src[] = "{ vars\n" "fuck:int\n" "ccf:int\n" "}\n" ":set ccf, 38\n" ":set fuck, 250\n" ":yosoro 114514 - ccf + fuck\n" ; *src = malloc(sizeof(test_src)); memcpy(*src,test_src,sizeof(test_src)); } int main() { const char *src; read_src(&src); Lexer *lexer = lexer_create(src); lexer_tokenize(lexer); Parser *parser = parser_create(&lexer->toks); parser_parse(parser); Interpreter *interpreter = interpreter_create(&parser->stmts, &parser->var_decls); interpreter_execute(interpreter); interpreter_free(interpreter); parser_free(parser); lexer_free(lexer); free(src); return 0; } Parser *parser_create(DynArr *toks) { Parser *parser = malloc(sizeof(Parser)); parser->toks = toks; parser->pos = 0; da_init(&parser->stmts, sizeof(Stmt), 16); da_init(&parser->var_decls, sizeof(VarDecl), 16); return parser; } void free_operand(Operand *op); void free_expr(Expr *expr) { for (int i = 0; i < expr->terms.item_cnts; i++) { ExprTerm *term = da_get(&expr->terms, i); switch (term->typ) { case EXPR_TERM_CONST: continue; case EXPR_TERM_OPERAND: free_operand(&term->operand); break; } } da_free(&expr->terms); } void free_operand(Operand *op) { if (op->typ == OPERAND_ARR_ELEM) { free_expr(&op->idx_expr); } } void free_stmts(DynArr *stmts) { for (int i = 0; i < stmts->item_cnts; i++) { Stmt *stmt = da_get(stmts, i); switch (stmt->typ) { case STMT_YOSORO_CMD: free_expr(&stmt->inner.yosoro.expr); break; case STMT_SET_CMD: free_operand(&stmt->inner.set.operand); free_expr(&stmt->inner.set.expr); break; case STMT_IHU_BLK: free_expr(&stmt->inner.ihu.cond.left); free_expr(&stmt->inner.ihu.cond.right); free_stmts(&stmt->inner.ihu.stmts); break; case STMT_WHILE_BLK: free_expr(&stmt->inner.while_stmt.cond.left); free_expr(&stmt->inner.while_stmt.cond.right); free_stmts(&stmt->inner.while_stmt.stmts); break; case STMT_HOR_BLK: free_operand(&stmt->inner.hor.var); free_expr(&stmt->inner.hor.start); free_expr(&stmt->inner.hor.end); free_stmts(&stmt->inner.hor.stmts); } } da_free(stmts); } void parser_free(Parser *parser) { free_stmts(&parser->stmts); da_free(&parser->var_decls); free(parser); } static Token *current_token(Parser *parser) { if (parser->pos >= parser->toks->item_cnts) { return NULL; } return da_get(parser->toks, parser->pos); } static Token *peek_token(Parser *parser, size_t offset) { if (parser->pos + offset >= parser->toks->item_cnts) { return NULL; } return da_get(parser->toks, parser->pos + offset); } static void consume_token(Parser *parser) { parser->pos++; } static int match_token(Parser *parser, enum TokType typ) { Token *token = current_token(parser); return token && token->type == typ; } static Token *next_token(Parser *parser) { Token *token = current_token(parser); consume_token(parser); return token; } void parse_vars(Parser *parser) { consume_token(parser); consume_token(parser); DynArr *var_decls = &parser->var_decls; size_t cnt = 0; while (!match_token(parser, TOK_RBRACE)) { Token *ident = next_token(parser); consume_token(parser); VarDecl *decl = da_try_push_back(var_decls); decl->name = ident->str; if (match_token(parser, TOK_KEYWORD_INT)) { consume_token(parser); decl->typ = VAR_INT; } else if (match_token(parser, TOK_KEYWORD_ARRAY)) { consume_token(parser); consume_token(parser); consume_token(parser); consume_token(parser); decl->typ = VAR_ARR; decl->start = atoll(next_token(parser)->str); consume_token(parser); decl->end = atoll(next_token(parser)->str); consume_token(parser); } cnt++; } consume_token(parser); } void parse_blk(Parser *parser, DynArr *stmts); void parse_expr(Parser *parser, Expr *expr); size_t operand_finder(Parser *parser, const char *var_name, enum OperandTyp type) { enum VarType target_type = 0xff; switch (type) { case OPERAND_INT_VAR: target_type = VAR_INT; break; case OPERAND_ARR_ELEM: target_type = VAR_ARR; break; } for (int i = 0; i < parser->var_decls.item_cnts; i++) { VarDecl *decl = da_get(&parser->var_decls, i); if ((target_type == 0xff || decl->typ == target_type) && decl->name == var_name) { return i; } } return (size_t)-1; } void parse_operand(Parser *parser, Operand *operand) { Token *operand_tok = current_token(parser); consume_token(parser); operand->typ = OPERAND_INT_VAR; if (match_token(parser, TOK_LBRACKET)) { operand->typ = OPERAND_ARR_ELEM; consume_token(parser); parse_expr(parser, &operand->idx_expr); consume_token(parser); } operand->decl_idx = operand_finder(parser, operand_tok->str, operand->typ); } int is_operand_eq(Operand *a, Operand *b); int is_expr_eq(Expr *a, Expr *b) { int cnts = a->terms.item_cnts; if (cnts != b->terms.item_cnts) { return 0; } for (int i = 0; i < cnts; i++) { ExprTerm *a_term = da_get(&a->terms, i); ExprTerm *b_term = da_get(&b->terms, i); if (a_term->typ != b_term->typ) { return 0; } switch (a_term->typ) { case EXPR_TERM_CONST: return a_term->constant == b_term->constant; case EXPR_TERM_OPERAND: return is_operand_eq(&a_term->operand, &b_term->operand); } } return 1; } int is_operand_eq(Operand *a, Operand *b) { if (a->typ != b->typ || a->decl_idx != b->decl_idx) { return 0; } if (a->typ == OPERAND_INT_VAR) { return 1; } else { return is_expr_eq(&a->idx_expr, &b->idx_expr); } } void terms_add_operand(DynArr *terms, Operand op, int sign) { for (int i = 0; i < terms->item_cnts; i++) { ExprTerm *term = da_get(terms, i); if (term->typ == EXPR_TERM_OPERAND && is_operand_eq(&term->operand, &op)) { term->coefficient += sign; if (op.typ == OPERAND_ARR_ELEM) { da_free(&op.idx_expr.terms); } return; } } ExprTerm *term = da_try_push_back(terms); term->coefficient = sign; term->typ = EXPR_TERM_OPERAND; term->operand = op; return; } void parse_expr(Parser *parser, Expr *expr) { da_init(&expr->terms, sizeof(ExprTerm), 8); DynArr *terms = &expr->terms; int const_val = 0; short sign = 1; while (current_token(parser) && !(match_token(parser, TOK_EOF) || match_token(parser, TOK_COLON) || match_token(parser, TOK_COMMA) || match_token(parser, TOK_RBRACE) || match_token(parser, TOK_LBRACE) || match_token(parser, TOK_RBRACKET))) { sign = 1; if (match_token(parser, TOK_PLUS)) { consume_token(parser); } else if (match_token(parser, TOK_MINUS)) { sign = -1; consume_token(parser); } Token *term_tok = current_token(parser); if (term_tok->type == TOK_INT) { const_val += atoi(term_tok->str) * sign; consume_token(parser); continue; } Operand op; parse_operand(parser, &op); terms_add_operand(terms, op, sign); } if (const_val != 0 || terms->item_cnts == 0) { ExprTerm *const_term = da_try_push_back(terms); const_term->coefficient = 1; const_term->typ = EXPR_TERM_CONST; const_term->constant = const_val; } } void parse_cond(Parser *parser, Cond *cond) { cond->typ = next_token(parser)->type; consume_token(parser); parse_expr(parser, &cond->left); consume_token(parser); parse_expr(parser, &cond->right); } void parse_ihu(Parser *parser, Stmt *stmt) { consume_token(parser); consume_token(parser); stmt->typ = STMT_IHU_BLK; IhuStmt *ihu = &stmt->inner.ihu; parse_cond(parser, &ihu->cond); da_init(&ihu->stmts, sizeof(Stmt), 16); parse_blk(parser, &ihu->stmts); consume_token(parser); } void parse_while(Parser *parser, Stmt *stmt) { consume_token(parser); consume_token(parser); stmt->typ = STMT_WHILE_BLK; WhileStmt *while_stmt = &stmt->inner.while_stmt; parse_cond(parser, &while_stmt->cond); da_init(&while_stmt->stmts, sizeof(Stmt), 16); parse_blk(parser, &while_stmt->stmts); consume_token(parser); } void parse_hor(Parser *parser, Stmt *stmt) { consume_token(parser); consume_token(parser); stmt->typ = STMT_HOR_BLK; HorStmt *hor = &stmt->inner.hor; parse_operand(parser, &hor->var); consume_token(parser); parse_expr(parser, &hor->start); consume_token(parser); parse_expr(parser, &hor->end); da_init(&hor->stmts, sizeof(Stmt), 16); parse_blk(parser, &hor->stmts); consume_token(parser); } void parse_yosoro(Parser *parser, Stmt *stmt) { consume_token(parser); consume_token(parser); stmt->typ = STMT_YOSORO_CMD; YosoroStmt *yosoro = &stmt->inner.yosoro; parse_expr(parser, &yosoro->expr); } void parse_set(Parser *parser, Stmt *stmt) { consume_token(parser); consume_token(parser); stmt->typ = STMT_SET_CMD; SetStmt *set = &stmt->inner.set; parse_operand(parser, &set->operand); consume_token(parser); parse_expr(parser, &set->expr); } static void parse_stmts(Parser *parser, DynArr *stmts) { Token *tok = current_token(parser); if (!tok) { return; } Stmt *cur_stmt; switch (tok->type) { case TOK_LBRACE: tok = peek_token(parser, 1); if (!tok) { consume_token(parser); return; } switch (tok->type) { case TOK_KEYWORD_VARS: parse_vars(parser); break; case TOK_KEYWORD_IHU: cur_stmt = da_try_push_back(stmts); parse_ihu(parser, cur_stmt); break; case TOK_KEYWORD_WHILE: cur_stmt = da_try_push_back(stmts); parse_while(parser, cur_stmt); break; case TOK_KEYWORD_HOR: cur_stmt = da_try_push_back(stmts); parse_hor(parser, cur_stmt); break; default: break; } return; case TOK_COLON: tok = peek_token(parser, 1); if (!tok) { consume_token(parser); return; } cur_stmt = da_try_push_back(stmts); switch (tok->type) { case TOK_KEYWORD_YOSORO: parse_yosoro(parser, cur_stmt); break; case TOK_KEYWORD_SET: parse_set(parser, cur_stmt); break; default: break; } break; default: consume_token(parser); return; } } void parse_blk(Parser *parser, DynArr *stmts) { while (!match_token(parser, TOK_RBRACE) && parser->pos < parser->toks->item_cnts && !match_token(parser, TOK_EOF)) { parse_stmts(parser, stmts); } } DynArr *parser_parse(Parser *parser) { while (parser->pos < parser->toks->item_cnts && !match_token(parser, TOK_EOF)) { parse_stmts(parser, &parser->stmts); } return &parser->stmts; } void da_init(DynArr *dyn_arr, size_t item_size, size_t capacity) { dyn_arr->item_cnts = 0; dyn_arr->capacity = capacity; dyn_arr->item_size = item_size; dyn_arr->items = malloc(capacity * dyn_arr->item_size); } DynArr *da_create(size_t item_size, size_t capacity) { DynArr *dyn_arr = malloc(sizeof(DynArr)); da_init(dyn_arr, item_size, capacity); return dyn_arr; } void *da_try_push_back(DynArr *dyn_arr) { if (dyn_arr->item_cnts >= dyn_arr->capacity) { dyn_arr->capacity *= 2; dyn_arr->items = realloc(dyn_arr->items, dyn_arr->capacity * dyn_arr->item_size); } void *dest = dyn_arr->items + dyn_arr->item_cnts * dyn_arr->item_size; ++dyn_arr->item_cnts; return dest; } void *da_push_back(DynArr *dyn_arr, void *item) { void *dest = da_try_push_back(dyn_arr); memcpy(dest, item, dyn_arr->item_size); return dest; } void da_free(DynArr *dyn_arr) { free(dyn_arr->items); } void str_pool_init(StrPool *pool, size_t mempool_size, size_t capacity) { pool->mempool_size = mempool_size; pool->mempool = malloc(mempool_size); da_init(&pool->pool_nodes, sizeof(StrPoolNode), capacity); return; } StrPool *str_pool_create(size_t mempool_size, size_t capacity) { StrPool *pool = malloc(sizeof(StrPool)); str_pool_init(pool, mempool_size, capacity); return pool; } void str_pool_free(StrPool *str_pool) { StrPoolNode *node; for (size_t i = 0; i < str_pool->pool_nodes.item_cnts; i++) { node = da_get(&str_pool->pool_nodes, i); if (!node->alloc_by_pool) { free(node->str); } } da_free(&str_pool->pool_nodes); free(str_pool->mempool); return; } char *str_pool_intern(StrPool *str_pool, const char *string, size_t len) { StrPoolNode *dest_node = NULL; size_t str_node_cnts = str_pool->pool_nodes.item_cnts; for (size_t i = 0; i < str_node_cnts; i++) { dest_node = da_get(&str_pool->pool_nodes, i); if (dest_node->len == len && (strncmp(dest_node->str, string, len) == 0)) { return dest_node->str; } } dest_node = da_try_push_back(&str_pool->pool_nodes); dest_node->len = len; if (len + 1 < str_pool->mempool_size - str_pool->mempool_offset) { dest_node->alloc_by_pool = 1; dest_node->str = &str_pool->mempool[str_pool->mempool_offset]; str_pool->mempool_offset += len + 1; } else { dest_node->alloc_by_pool = 0; dest_node->str = malloc(len + 1); } memcpy(dest_node->str, string, len); dest_node->str[len] = '\0'; return dest_node->str; }
Editor Settings
Theme
Key bindings
Full width
Lines