apfl/src/apfl.h

554 lines
16 KiB
C
Raw Normal View History

2021-12-10 20:22:16 +00:00
#ifndef APFL_H
#define APFL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
typedef double apfl_number;
struct apfl_position {
int line;
int col;
};
bool apfl_position_eq(struct apfl_position, struct apfl_position);
// Strings
struct apfl_string_view {
const char *bytes;
size_t len;
};
struct apfl_string {
char *bytes;
size_t len;
};
struct apfl_refcounted_string_data;
typedef struct apfl_refcounted_string_data *apfl_refcounted_string;
2021-12-10 20:22:16 +00:00
#define APFL_STR_FMT "%.*s"
#define APFL_STR_FMT_ARGS(s) (int)(s).len,(s).bytes
struct apfl_string_view apfl_string_view_from_view(struct apfl_string_view);
struct apfl_string_view apfl_string_view_from_cstr(char *);
struct apfl_string_view apfl_string_view_from_const_cstr(const char *);
struct apfl_string_view apfl_string_view_from_string(struct apfl_string);
struct apfl_string_view apfl_string_view_from_refcounted_string(apfl_refcounted_string);
#define apfl_string_view_from(s) _Generic((s), \
struct apfl_string: apfl_string_view_from_string, \
struct apfl_string_view: apfl_string_view_from_view, \
apfl_refcounted_string: apfl_string_view_from_refcounted_string, \
char *: apfl_string_view_from_cstr, \
const char *: apfl_string_view_from_const_cstr \
2021-12-10 20:22:16 +00:00
)(s)
int apfl_string_view_cmp(struct apfl_string_view, struct apfl_string_view);
#define apfl_string_cmp(a, b) apfl_string_view_cmp(apfl_string_view_from(a), apfl_string_view_from(b))
#define apfl_string_eq(a, b) (apfl_string_cmp((a), (b)) == 0)
2021-12-10 20:22:16 +00:00
struct apfl_string apfl_string_blank(void);
2021-12-10 20:22:16 +00:00
void apfl_string_deinit(struct apfl_string *);
struct apfl_string apfl_string_move(struct apfl_string *src);
/**
* Copies a string from src to dst. dst must point to a blank string.
* Returns true on success, false otherwise (if the necessary memory could not
* be allocated).
*/
bool apfl_string_copy(struct apfl_string *dst, struct apfl_string_view src);
2021-12-10 20:22:16 +00:00
struct apfl_string_builder {
char *bytes;
size_t len;
size_t cap;
};
void apfl_string_builder_init(struct apfl_string_builder *);
void apfl_string_builder_deinit(struct apfl_string_builder *);
bool apfl_string_builder_append(struct apfl_string_builder *, struct apfl_string_view);
bool apfl_string_builder_append_byte(struct apfl_string_builder *, char byte);
struct apfl_string apfl_string_builder_move_string(struct apfl_string_builder *);
#define apfl_string_builder_append_cstr(builder, cstr) (apfl_string_builder_append((builder), apfl_string_view_from_cstr((cstr))))
apfl_refcounted_string apfl_string_copy_into_new_refcounted(struct apfl_string_view);
apfl_refcounted_string apfl_string_move_into_new_refcounted(struct apfl_string *);
/* Increases the reference of the refcounted string.
* Returns the same apfl_refcounted_string value.
*/
apfl_refcounted_string apfl_refcounted_string_incref(apfl_refcounted_string);
/* Unrefs the refcounted string. It is no longer allowed to use the pointer
* after calling this function with it!
*/
void apfl_refcounted_string_unref(apfl_refcounted_string );
/* Like apfl_refcounted_string_unref, but accepts a pointer to a refcounted_string.
* The pointed to value will be set to NULL.
*/
void apfl_refcounted_string_unref_ptr(apfl_refcounted_string *);
2021-12-10 20:22:16 +00:00
// Tokens
enum apfl_token_type {
APFL_TOK_LPAREN,
APFL_TOK_RPAREN,
APFL_TOK_LBRACKET,
APFL_TOK_RBRACKET,
APFL_TOK_LBRACE,
APFL_TOK_RBRACE,
APFL_TOK_MAPSTO,
APFL_TOK_EXPAND,
APFL_TOK_DOT,
APFL_TOK_AT,
APFL_TOK_SEMICOLON,
APFL_TOK_LINEBREAK,
APFL_TOK_CONTINUE_LINE,
APFL_TOK_COMMENT,
APFL_TOK_COMMA,
APFL_TOK_QUESTION_MARK,
APFL_TOK_STRINGIFY,
APFL_TOK_ASSIGN,
APFL_TOK_LOCAL_ASSIGN,
APFL_TOK_NUMBER,
APFL_TOK_NAME,
APFL_TOK_STRING,
};
struct apfl_token {
enum apfl_token_type type;
struct apfl_position position;
union {
apfl_refcounted_string text;
2021-12-10 20:22:16 +00:00
apfl_number number;
};
};
void apfl_token_deinit(struct apfl_token *);
const char *apfl_token_type_name(enum apfl_token_type);
void apfl_token_print(struct apfl_token, FILE *);
// Errors
enum apfl_error_type {
APFL_ERR_MALLOC_FAILED,
APFL_ERR_INPUT_ERROR,
APFL_ERR_UNEXPECTED_EOF,
APFL_ERR_EXPECTED_EQ_AFTER_COLON,
APFL_ERR_UNEXPECTED_BYTE,
2021-12-10 20:22:16 +00:00
APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER,
APFL_ERR_EXPECTED_DIGIT,
APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE,
APFL_ERR_INVALID_ESCAPE_SEQUENCE,
APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE,
APFL_ERR_UNEXPECTED_TOKEN,
APFL_ERR_MISMATCHING_CLOSING_BRACKET,
APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN,
APFL_ERR_STATEMENTS_BEFORE_PARAMETERS,
APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS,
APFL_ERR_UNEXPECTED_EXPRESSION,
APFL_ERR_INVALID_ASSIGNMENT_LHS,
APFL_ERR_EMPTY_ASSIGNMENT,
APFL_ERR_ONLY_ONE_EXPAND_ALLOWED,
APFL_ERR_UNEXPECTED_CONSTANT_IN_MEMBER_ACCESS,
APFL_ERR_UNEXPECTED_EXPR_IN_MEMBER_ACCESS,
APFL_ERR_UNEXPECTED_BLANK_IN_MEMBER_ACCESS,
2021-12-10 20:22:16 +00:00
};
2021-12-18 23:27:34 +00:00
const char *apfl_error_type_name(enum apfl_error_type);
2021-12-10 20:22:16 +00:00
struct apfl_error {
enum apfl_error_type type;
// Optional data
struct apfl_position position;
struct apfl_position position2;
enum apfl_token_type token_type;
enum apfl_token_type token_type2;
char byte;
};
void apfl_error_print(struct apfl_error, FILE *);
struct apfl_error apfl_error_simple(enum apfl_error_type);
bool apfl_error_is_fatal_type(enum apfl_error_type);
#define APFL_ERROR_IS_FATAL(err) (apfl_error_is_fatal_type((err).type))
enum apfl_expr_type {
APFL_EXPR_LIST,
APFL_EXPR_DICT,
APFL_EXPR_CALL,
APFL_EXPR_SIMPLE_FUNC,
APFL_EXPR_COMPLEX_FUNC,
APFL_EXPR_ASSIGNMENT,
APFL_EXPR_DOT,
APFL_EXPR_AT,
APFL_EXPR_CONSTANT,
APFL_EXPR_VAR,
APFL_EXPR_BLANK,
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_list_item {
struct apfl_expr *expr;
bool expand;
};
struct apfl_expr_list {
struct apfl_expr_list_item *items;
size_t len;
};
struct apfl_expr_dict_pair {
struct apfl_expr *k;
struct apfl_expr *v;
};
struct apfl_expr_dict {
struct apfl_expr_dict_pair *items;
size_t len;
};
struct apfl_expr_call {
struct apfl_expr *callee;
struct apfl_expr_list arguments;
};
struct apfl_expr_body {
struct apfl_expr *items;
size_t len;
unsigned refcount; // TODO: Probably better to not expose refcount
2021-12-10 20:22:16 +00:00
};
enum apfl_expr_const_type {
APFL_EXPR_CONST_NIL,
APFL_EXPR_CONST_BOOLEAN,
APFL_EXPR_CONST_STRING,
APFL_EXPR_CONST_NUMBER,
};
struct apfl_expr_const {
enum apfl_expr_const_type type;
union {
// variant nil is without data
bool boolean;
apfl_refcounted_string string;
2021-12-10 20:22:16 +00:00
apfl_number number;
};
};
struct apfl_expr_param_predicate {
struct apfl_expr_param *lhs;
struct apfl_expr *rhs;
};
enum apfl_expr_param_type {
APFL_EXPR_PARAM_VAR,
APFL_EXPR_PARAM_CONSTANT,
APFL_EXPR_PARAM_PREDICATE,
APFL_EXPR_PARAM_LIST,
APFL_EXPR_PARAM_BLANK,
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_params {
struct apfl_expr_params_item *params;
2021-12-10 20:22:16 +00:00
size_t len;
};
struct apfl_expr_param {
enum apfl_expr_param_type type;
union {
apfl_refcounted_string var;
2021-12-10 20:22:16 +00:00
struct apfl_expr_const constant;
struct apfl_expr_param_predicate predicate;
struct apfl_expr_params list;
};
};
struct apfl_expr_params_item {
bool expand;
struct apfl_expr_param param;
};
2021-12-10 20:22:16 +00:00
struct apfl_expr_subfunc {
struct apfl_expr_params params;
struct apfl_expr_body *body;
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_complex_func {
struct apfl_expr_subfunc *subfuncs;
size_t len;
};
enum apfl_expr_assignable_type {
APFL_EXPR_ASSIGNABLE_VAR_OR_MEMBER,
2021-12-10 20:22:16 +00:00
APFL_EXPR_ASSIGNABLE_CONSTANT,
APFL_EXPR_ASSIGNABLE_PREDICATE,
APFL_EXPR_ASSIGNABLE_LIST,
APFL_EXPR_ASSIGNABLE_BLANK,
2021-12-10 20:22:16 +00:00
};
enum apfl_expr_assignable_var_or_member_type {
APFL_EXPR_ASSIGNABLE_VAR_OR_MEMBER_VAR,
APFL_EXPR_ASSIGNABLE_VAR_OR_MEMBER_DOT,
APFL_EXPR_ASSIGNABLE_VAR_OR_MEMBER_AT,
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_assignable_var_or_member_dot {
struct apfl_expr_assignable_var_or_member *lhs;
apfl_refcounted_string rhs;
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_assignable_var_or_member_at {
struct apfl_expr_assignable_var_or_member *lhs;
struct apfl_expr *rhs;
};
struct apfl_expr_assignable_var_or_member {
enum apfl_expr_assignable_var_or_member_type type;
union {
apfl_refcounted_string var;
struct apfl_expr_assignable_var_or_member_dot dot;
struct apfl_expr_assignable_var_or_member_at at;
};
};
struct apfl_expr_assignable_predicate {
2021-12-10 20:22:16 +00:00
struct apfl_expr_assignable *lhs;
struct apfl_expr *rhs;
};
struct apfl_expr_assignable_list {
struct apfl_expr_assignable_list_item *items;
2021-12-10 20:22:16 +00:00
size_t len;
};
struct apfl_expr_assignable {
enum apfl_expr_assignable_type type;
union {
struct apfl_expr_assignable_var_or_member var_or_member;
2021-12-10 20:22:16 +00:00
struct apfl_expr_const constant;
struct apfl_expr_assignable_predicate predicate;
struct apfl_expr_assignable_list list;
};
};
struct apfl_expr_assignable_list_item {
struct apfl_expr_assignable assignable;
bool expand;
};
2021-12-10 20:22:16 +00:00
struct apfl_expr_assignment {
bool local;
struct apfl_expr_assignable lhs;
struct apfl_expr *rhs;
};
struct apfl_expr_dot {
struct apfl_expr *lhs;
apfl_refcounted_string rhs;
2021-12-10 20:22:16 +00:00
};
struct apfl_expr_at {
struct apfl_expr *lhs;
struct apfl_expr *rhs;
};
struct apfl_expr {
enum apfl_expr_type type;
union {
struct apfl_expr_list list;
struct apfl_expr_dict dict;
struct apfl_expr_call call;
struct apfl_expr_body *simple_func;
2021-12-10 20:22:16 +00:00
struct apfl_expr_complex_func complex_func;
struct apfl_expr_assignment assignment;
struct apfl_expr_dot dot;
struct apfl_expr_at at;
struct apfl_expr_const constant;
apfl_refcounted_string var;
// blank has no further data
2021-12-10 20:22:16 +00:00
};
struct apfl_position position;
};
void apfl_expr_print(struct apfl_expr, FILE *);
bool apfl_expr_eq(struct apfl_expr, struct apfl_expr);
// Begin deinit functions
void apfl_expr_deinit(struct apfl_expr *);
void apfl_expr_list_deinit(struct apfl_expr_list *);
void apfl_expr_list_item_deinit(struct apfl_expr_list_item *);
void apfl_expr_dict_pair_deinit(struct apfl_expr_dict_pair *);
void apfl_expr_dict_deinit(struct apfl_expr_dict *);
void apfl_expr_call_deinit(struct apfl_expr_call *);
void apfl_expr_body_unref(struct apfl_expr_body *);
2021-12-10 20:22:16 +00:00
void apfl_expr_const_deinit(struct apfl_expr_const *);
void apfl_expr_param_predicate_deinit(struct apfl_expr_param_predicate *);
void apfl_expr_params_deinit(struct apfl_expr_params *);
void apfl_expr_params_item_deinit(struct apfl_expr_params_item *);
2021-12-10 20:22:16 +00:00
void apfl_expr_param_deinit(struct apfl_expr_param *);
void apfl_expr_subfunc_deinit(struct apfl_expr_subfunc *);
void apfl_expr_complex_func_deinit(struct apfl_expr_complex_func *);
void apfl_expr_assignable_predicate_deinit(struct apfl_expr_assignable_predicate *);
void apfl_expr_assignable_list_item_deinit(struct apfl_expr_assignable_list_item *);
2021-12-10 20:22:16 +00:00
void apfl_expr_assignable_list_deinit(struct apfl_expr_assignable_list *);
void apfl_expr_assignable_var_or_member_dot_deinit(struct apfl_expr_assignable_var_or_member_dot *);
void apfl_expr_assignable_var_or_member_at_deinit(struct apfl_expr_assignable_var_or_member_at *);
void apfl_expr_assignable_var_or_member_deinit(struct apfl_expr_assignable_var_or_member *);
2021-12-10 20:22:16 +00:00
void apfl_expr_assignable_deinit(struct apfl_expr_assignable *);
void apfl_expr_assignment_deinit(struct apfl_expr_assignment *);
void apfl_expr_dot_deinit(struct apfl_expr_dot *);
void apfl_expr_at_deinit(struct apfl_expr_at *);
// End deinit functions
// Begin move functions
struct apfl_expr apfl_expr_move(struct apfl_expr *);
struct apfl_expr_list apfl_expr_list_move(struct apfl_expr_list *);
struct apfl_expr_list_item apfl_expr_list_item_move(struct apfl_expr_list_item *);
struct apfl_expr_dict_pair apfl_expr_dict_pair_move(struct apfl_expr_dict_pair *);
struct apfl_expr_dict apfl_expr_dict_move(struct apfl_expr_dict *);
struct apfl_expr_call apfl_expr_call_move(struct apfl_expr_call *);
struct apfl_expr_body * apfl_expr_body_move(struct apfl_expr_body **);
struct apfl_expr_const apfl_expr_const_move(struct apfl_expr_const *);
struct apfl_expr_param_predicate apfl_expr_param_predicate_move(struct apfl_expr_param_predicate *);
struct apfl_expr_params apfl_expr_params_move(struct apfl_expr_params *);
struct apfl_expr_param apfl_expr_param_move(struct apfl_expr_param *);
struct apfl_expr_subfunc apfl_expr_subfunc_move(struct apfl_expr_subfunc *);
struct apfl_expr_complex_func apfl_expr_complex_func_move(struct apfl_expr_complex_func *);
struct apfl_expr_assignable_var_or_member apfl_expr_assignable_var_or_member_move(struct apfl_expr_assignable_var_or_member *);
struct apfl_expr_assignable_predicate apfl_expr_assignable_predicate_move(struct apfl_expr_assignable_predicate *);
struct apfl_expr_assignable_dot apfl_expr_assignable_dot_move(struct apfl_expr_assignable_dot *);
struct apfl_expr_assignable_at apfl_expr_assignable_at_move(struct apfl_expr_assignable_at *);
struct apfl_expr_assignable_list apfl_expr_assignable_list_move(struct apfl_expr_assignable_list *);
struct apfl_expr_assignable apfl_expr_assignable_move(struct apfl_expr_assignable *);
struct apfl_expr_assignment apfl_expr_assignment_move(struct apfl_expr_assignment *);
struct apfl_expr_dot apfl_expr_dot_move(struct apfl_expr_dot *);
struct apfl_expr_at apfl_expr_at_move(struct apfl_expr_at *);
2021-12-10 20:22:16 +00:00
// End move functions
enum apfl_parse_result {
APFL_PARSE_OK,
APFL_PARSE_EOF,
APFL_PARSE_ERROR,
};
struct apfl_tokenizer;
typedef struct apfl_tokenizer *apfl_tokenizer_ptr;
typedef bool (*apfl_source_reader_cb)(void *context, char *buf, size_t *len, bool need);
apfl_tokenizer_ptr apfl_tokenizer_new(apfl_source_reader_cb, void *context);
void apfl_tokenizer_destroy(apfl_tokenizer_ptr);
enum apfl_parse_result apfl_tokenizer_next(apfl_tokenizer_ptr, bool need);
/* Get the current token.
* Return value is undefined when the last call to apfl_tokenizer_next did not
* return APFL_PARSE_OK.
*/
struct apfl_token apfl_tokenizer_get_token(apfl_tokenizer_ptr);
/* Get the current error.
* Return value is undefined when the last call to apfl_tokenizer_next did not
* return APFL_PARSE_ERROR.
*/
struct apfl_error apfl_tokenizer_get_error(apfl_tokenizer_ptr);
/* An apfl_source_reader_cb implementation to have a string view as a source.
* Use together with apfl_string_source_reader_new.
*/
bool apfl_string_source_reader(void *, char *, size_t *len, bool);
void *apfl_string_source_reader_new(struct apfl_string_view);
void apfl_string_source_reader_destroy(void *);
2021-12-10 20:22:16 +00:00
struct apfl_parser_token_source {
enum apfl_parse_result (*next)(void *, bool need);
struct apfl_token (*get_token)(void *);
struct apfl_error (*get_error)(void *);
void *opaque;
};
struct apfl_parser_token_source apfl_tokenizer_as_token_source(apfl_tokenizer_ptr);
2021-12-10 20:22:16 +00:00
struct apfl_parser;
typedef struct apfl_parser *apfl_parser_ptr;
apfl_parser_ptr apfl_parser_new(struct apfl_parser_token_source);
/* Destroys the parser.
* Note that if the token source needs it's own destruction, you'll have to do
* that yourself after destroying the parser.
*/
void apfl_parser_destroy(apfl_parser_ptr);
enum apfl_parse_result apfl_parser_next(apfl_parser_ptr);
/* Get the current error.
* Return value is undefined when the last call to apfl_parser_next did not
* return APFL_PARSE_ERROR.
*/
struct apfl_error apfl_parser_get_error(apfl_parser_ptr);
/* Get the current expression.
* Return value is undefined when the last call to apfl_parser_next did not
* return APFL_PARSE_OK.
*/
struct apfl_expr apfl_parser_get_expr(apfl_parser_ptr);
struct apfl_ctx_data;
typedef struct apfl_ctx_data *apfl_ctx;
enum apfl_result {
APFL_RESULT_OK, // Evaluation succeeded, value is on the stack
// TODO: No further details are yet provided on (fatal) error. Not quite
// sure what to return / how errors/exceptions should work. Maybe a
// value + a backtrace?
APFL_RESULT_ERR,
APFL_RESULT_ERR_FATAL,
};
apfl_ctx apfl_ctx_new(void);
void apfl_ctx_destroy(apfl_ctx);
enum apfl_result apfl_eval(apfl_ctx, struct apfl_expr);
void apfl_debug_print_val(apfl_ctx, int, FILE *);
2021-12-10 20:22:16 +00:00
#ifdef __cplusplus
}
#endif
#endif