148 lines
3.3 KiB
C
Raw Normal View History

2026-01-17 20:56:54 +01:00
#ifndef RINJA_H
#define RINJA_H
#define PY_SSIZE_T_CLEAN
#include <Python.h>
/* retoor <retoor@molodetz.nl> */
typedef enum {
TOKEN_TEXT,
TOKEN_VAR_START, TOKEN_VAR_END,
TOKEN_BLOCK_START, TOKEN_BLOCK_END,
TOKEN_COMMENT_START, TOKEN_COMMENT_END,
TOKEN_IDENTIFIER, TOKEN_STRING, TOKEN_NUMBER, TOKEN_OPERATOR,
TOKEN_EOF
} TokenType;
typedef struct {
TokenType type;
const char *start;
size_t length;
int line;
int column;
} Token;
typedef struct {
const char *source;
const char *current;
int line;
int column;
} Tokenizer;
typedef enum {
EXPR_LITERAL,
EXPR_VARIABLE,
EXPR_GETATTR,
EXPR_GETITEM,
EXPR_CALL,
EXPR_FILTER,
EXPR_TEST,
EXPR_BINOP,
EXPR_UNOP,
EXPR_CONDITIONAL,
EXPR_LIST,
EXPR_DICT,
EXPR_TUPLE
} ExpressionType;
typedef struct Expression {
ExpressionType type;
union {
PyObject* literal;
char* identifier;
struct {
struct Expression* left;
char* op;
struct Expression* right;
} binop;
struct {
struct Expression* target;
char* attr;
} getattr;
struct {
struct Expression* target;
struct Expression* arg;
} getitem;
struct {
struct Expression* func;
struct Expression** args;
int arg_count;
} call;
struct {
struct Expression* target;
char* name;
struct Expression** args;
int arg_count;
} filter;
struct {
struct Expression** items;
int count;
} list;
} data;
} Expression;
typedef enum {
NODE_ROOT,
NODE_TEXT,
NODE_VARIABLE,
NODE_IF,
NODE_FOR,
NODE_WHILE,
NODE_BLOCK,
NODE_EXTENDS,
NODE_INCLUDE,
NODE_IMPORT,
NODE_MACRO,
NODE_SET,
NODE_WITH,
NODE_FILTER_BLOCK,
NODE_CALL,
NODE_AUTOESCAPE,
NODE_RAW,
NODE_DO,
NODE_BREAK,
NODE_CONTINUE,
NODE_MARKDOWN,
NODE_LINKIFY,
NODE_EMOJI
} NodeType;
typedef struct ASTNode {
NodeType type;
struct ASTNode *next;
struct ASTNode *child;
struct ASTNode *alternate; /* else / elif */
const char* start;
size_t length;
char* name;
Expression* expr;
int trim_left;
int trim_right;
} ASTNode;
typedef struct {
char* buffer;
size_t length;
size_t capacity;
} StringBuilder;
/* Function prototypes */
void tokenizer_init(Tokenizer* t, const char* source);
int tokenizer_is_at_end(Tokenizer* t);
Token next_token(Tokenizer* t, int in_expression);
Token peek_token(Tokenizer* t, int in_expression);
ASTNode* parse(const char* source);
void free_ast(ASTNode* node);
void free_expression(Expression* expr);
PyObject* render_ast(ASTNode* root, PyObject* context, PyObject* filters, PyObject* tests, PyObject* env);
PyObject* apply_builtin_filter(const char* name, PyObject* val, Expression** args, int arg_count, PyObject* context, PyObject* filters, PyObject* tests, PyObject* env);
PyObject* apply_builtin_test(const char* name, PyObject* val, PyObject* tests);
void sb_init(StringBuilder* sb);
void sb_append(StringBuilder* sb, const char* text, size_t len);
void sb_free(StringBuilder* sb);
#endif /* RINJA_H */