vessel/web/include/temple.h
Arija A. d9b70ac06e
feat(web): Implement basic Temple
Signed-off-by: Arija A. <ari@ari.lt>
2025-07-01 22:20:30 +03:00

290 lines
11 KiB
C

#ifndef VESSEL_WEB_TEMPLE_H_
#define VESSEL_WEB_TEMPLE_H_
#include "conf.h"
#include <vessel/log.h>
#include <vessel/hmap.h>
typedef enum {
vw_TempleASTNodeType_template = 0, /* Template: entire template */
vw_TempleASTNodeType_text, /* Raw text outside of tags */
vw_TempleASTNodeType_comment, /* Comment: {# ... #} */
vw_TempleASTNodeType_output_expr, /* Output: {{ expression }} */
vw_TempleASTNodeType_set_stmt, /* Set statement: {% set member_or_var.here = expr %} */
vw_TempleASTNodeType_unset_stmt, /* Unset statement (only nonmembers): {% unset var %} */
vw_TempleASTNodeType_unmacro_stmt, /* Unmacro statement (only macros): {% unmacro name %} */
vw_TempleASTNodeType_conditional, /* If: {% if ... %} ... {% elif ... %} ... {% end %} or
ternary: cond ? a : b */
vw_TempleASTNodeType_macro_stmt, /* Block: {% macro ... %} ... {% end %} */
vw_TempleASTNodeType_namespace_stmt, /* Namespace: {% namespace ... %} ... {% end %} */
vw_TempleASTNodeType_import_stmt, /* Import: {% import "filename.tpl" %} */
vw_TempleASTNodeType_for_loop, /* For loop: {% for x : y %} */
vw_TempleASTNodeType_while_loop, /* While loop: {% while expr %} */
vw_TempleASTNodeType_binary_expr, /* Binary expression: a + b */
vw_TempleASTNodeType_unary_expr, /* Unary expression: !x, -x */
vw_TempleASTNodeType_function_call, /* Function call: lower(x) */
vw_TempleASTNodeType_variable, /* Variable: x */
vw_TempleASTNodeType_literal_string, /* Literal string: "..." or r"..." */
vw_TempleASTNodeType_fmt_string, /* Literal format string: f"... {expr} ..." */
vw_TempleASTNodeType_literal_number, /* Literal number: 123 (base 10) (or 0d123), 0x123 (base
16), 0o123 (base 8), 0b110 (base 2) */
vw_TempleASTNodeType_literal_array, /* Literal array: [..., ...] */
vw_TempleASTNodeType_literal_boolean, /* Literal boolean: true or false */
vw_TempleASTNodeType_literal_null, /* Literal null: null */
vw_TempleASTNodeType_literal_float, /* Literal float: 3.14159 or 12e-3 (0.012) */
vw_TempleASTNodeType_literal_inf, /* Literal infinity: inf */
vw_TempleASTNodeType_parent_stmt, /* Parent stmt: parent */
vw_TempleASTNodeType_lookup, /* Lookup: [...] */
vw_TempleASTNodeType_member_lookup, /* Member lookup: a.b */
vw_TempleASTNodeType_finish_stmt, /* Finish render: {% finish %} */
vw_TempleASTNodeType_break_stmt, /* Break statement: {% break %} */
vw_TempleASTNodeType_continue_stmt, /* Continue statement: {% continue %} */
vw_TempleASTNodeType_block_stmt, /* Block statement: {% block name %} {% end %} */
vw_TempleASTNodeType_range, /* Range: a:b/step */
vw_TempleASTNodeType_literal_hashmap, /* Literal hashmao: {a: b} */
} vw_TempleASTNodeType;
typedef enum {
vw_TempleASTBinaryOperator_add = 0, /* + */
vw_TempleASTBinaryOperator_sub, /* - */
vw_TempleASTBinaryOperator_mul, /* * */
vw_TempleASTBinaryOperator_div, /* / */
vw_TempleASTBinaryOperator_mod, /* % */
vw_TempleASTBinaryOperator_keyword, /* = (for keyword arguments and default values) */
vw_TempleASTBinaryOperator_eq, /* == */
vw_TempleASTBinaryOperator_neq, /* != */
vw_TempleASTBinaryOperator_lt, /* < */
vw_TempleASTBinaryOperator_gt, /* > */
vw_TempleASTBinaryOperator_leq, /* <= */
vw_TempleASTBinaryOperator_geq, /* >= */
vw_TempleASTBinaryOperator_and, /* && */
vw_TempleASTBinaryOperator_or, /* || */
vw_TempleASTBinaryOperator_band, /* & */
vw_TempleASTBinaryOperator_bor, /* | */
vw_TempleASTBinaryOperator_bxor, /* ^ */
vw_TempleASTBinaryOperator_shl, /* << */
vw_TempleASTBinaryOperator_shr, /* >> */
vw_TempleASTBinaryOperator_in, /* @ */
} vw_TempleASTBinaryOperator;
typedef enum {
vw_TempleASTAssignmentOperator_simple = 0, /* = */
vw_TempleASTAssignmentOperator_add, /* += */
vw_TempleASTAssignmentOperator_sub, /* -= */
vw_TempleASTAssignmentOperator_mul, /* *= */
vw_TempleASTAssignmentOperator_div, /* /= */
vw_TempleASTAssignmentOperator_mod, /* %= */
vw_TempleASTAssignmentOperator_band, /* &= */
vw_TempleASTAssignmentOperator_bor, /* |= */
vw_TempleASTAssignmentOperator_bxor, /* ^= */
vw_TempleASTAssignmentOperator_shl, /* <<= */
vw_TempleASTAssignmentOperator_shr, /* >>= */
} vw_TempleASTAssignmentOperator;
typedef enum {
vw_TempleASTUnaryOperator_neg = 0, /* - */
vw_TempleASTUnaryOperator_pos, /* + */
vw_TempleASTUnaryOperator_not, /* ! */
vw_TempleASTUnaryOperator_bnot, /* ~ */
vw_TempleASTUnaryOperator_spread, /* * */
vw_TempleASTUnaryOperator_kspread, /* ** */
} vw_TempleASTUnaryOperator;
typedef struct vw_TempleASTNode {
vw_TempleASTNodeType type;
union {
struct {
char *text;
size_t len;
} text;
struct {
char *text;
size_t len;
} comment;
struct {
struct vw_TempleASTNode *expr;
} output;
struct {
struct vw_TempleASTNode *name;
vw_TempleASTAssignmentOperator eq;
struct vw_TempleASTNode *expr;
bool trim; /* trim value */
} set_stmt;
struct {
char *name;
size_t name_len;
} unset_stmt;
struct {
char *name;
size_t name_len;
} unmacro_stmt;
struct {
struct vw_TempleASTNode *condition;
struct vw_TempleASTNode *body;
struct vw_TempleASTNode *else_clause;
bool trim_body, trim_clause;
} conditional;
struct {
char *name;
size_t name_len;
struct vw_TempleASTNode **args;
size_t args_count;
struct vw_TempleASTNode *body;
bool trim; /* trim macro body */
} macro_stmt;
struct {
char *name;
size_t name_len;
struct vw_TempleASTNode *body;
bool trim; /* trim macro body */
} namespace_stmt;
struct {
struct vw_TempleASTNode *filename;
char *namespace;
size_t namespace_size;
bool trim; /* trim template body */
} import_stmt;
struct {
char *varname;
struct vw_TempleASTNode *iterable;
struct vw_TempleASTNode *body;
bool trim; /* trim loop body */
} for_loop;
struct {
struct vw_TempleASTNode *condition;
struct vw_TempleASTNode *body;
bool trim; /* trim loop body */
} while_loop;
struct {
vw_TempleASTBinaryOperator op;
struct vw_TempleASTNode *left;
struct vw_TempleASTNode *right;
} binary;
struct {
vw_TempleASTUnaryOperator op;
struct vw_TempleASTNode *operand;
} unary;
struct {
struct vw_TempleASTNode *name;
struct vw_TempleASTNode **args;
size_t args_count;
} function_call;
struct {
char *name;
size_t name_len;
} variable;
struct {
int64_t value;
} number;
struct {
bool raw;
char *value;
size_t value_len;
} string;
struct {
struct vw_TempleASTNode *string;
} fmt_string;
struct {
struct vw_TempleASTNode *operand;
struct vw_TempleASTNode *index;
} lookup;
struct {
struct vw_TempleASTNode *operand;
char *member;
size_t member_len;
} member_lookup;
struct {
struct vw_TempleASTNode **items;
size_t items_count;
} array;
struct {
bool value;
} boolean;
struct {
double value;
} floatnum;
struct {
char *name;
size_t name_len;
struct vw_TempleASTNode *body;
bool trim; /* trim block body */
} block;
struct {
struct vw_TempleASTNode *from;
struct vw_TempleASTNode *to;
struct vw_TempleASTNode *step;
} range;
struct {
struct vw_TempleASTNode **keys;
struct vw_TempleASTNode **values;
size_t count;
} hashmap;
} data;
struct vw_TempleASTNode *next;
} vw_TempleASTNode;
typedef enum {
vw_TempleVarType_string = 0,
vw_TempleVarType_number,
vw_TempleVarType_float,
vw_TempleVarType_boolean,
vw_TempleVarType_array,
vw_TempleVarType_hashmap,
vw_TempleVarType_object,
vw_TempleVarType_function,
vw_TempleVarType_argument,
} vw_TempleVarType;
typedef struct vw_TempleVar {
vw_TempleVarType type;
union {
struct {
char *value;
size_t len;
} string;
struct {
int64_t value;
} number;
struct {
double value;
} floatnum;
struct {
bool value;
} boolean;
struct {
struct vw_TempleVar *elements;
size_t count;
} array;
struct {
vs_HMap *kv;
} hashmap;
struct {
vs_HMap *members;
} object;
struct {
vw_TempleASTNode (*call)(vw_TempleASTNode *args, size_t args_count);
} function;
} data;
} vw_TempleVar;
typedef struct {
bool auto_escape;
vs_Logger *logger;
vs_HMap vars;
vw_TempleASTNode root;
} vw_Temple;
bool vw_Temple_init(vw_Temple *ctx, bool auto_escape, vs_Logger *logger);
bool vw_Temple_compile(vw_Temple *ctx, const char *input, const char *end);
char *vw_Temple_render(vw_Temple *ctx);
bool vw_Temple_dump(vw_Temple *ctx, const char *filename);
bool vw_Temple_load(vw_Temple *ctx, const char *filename);
bool vw_Temple_print(vw_Temple *ctx);
bool vw_Temple_destroy(vw_Temple *ctx);
void vw_TempleASTNode_free(vw_TempleASTNode *node);
#endif /* VESSEL_WEB_TEMPLE_H_ */