290 lines
11 KiB
C
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_ */
|