455 lines
13 KiB
C
455 lines
13 KiB
C
|
|
#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;
|
||
|
|
};
|
||
|
|
|
||
|
|
#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);
|
||
|
|
|
||
|
|
#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, \
|
||
|
|
char *: apfl_string_view_from_cstr, \
|
||
|
|
const char *: apfl_string_view_from_const_cstr \
|
||
|
|
)(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))
|
||
|
|
|
||
|
|
void apfl_string_deinit(struct apfl_string *);
|
||
|
|
bool apfl_string_copy(struct apfl_string *dst, struct apfl_string_view src);
|
||
|
|
struct apfl_string apfl_string_move(struct apfl_string *src);
|
||
|
|
|
||
|
|
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))))
|
||
|
|
|
||
|
|
// 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 {
|
||
|
|
struct apfl_string text;
|
||
|
|
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_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,
|
||
|
|
};
|
||
|
|
|
||
|
|
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,
|
||
|
|
};
|
||
|
|
|
||
|
|
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;
|
||
|
|
};
|
||
|
|
|
||
|
|
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;
|
||
|
|
struct apfl_string string;
|
||
|
|
apfl_number number;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_param_predicate {
|
||
|
|
struct apfl_expr_param *lhs;
|
||
|
|
struct apfl_expr *rhs;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_param_list {
|
||
|
|
struct apfl_expr_param *children;
|
||
|
|
size_t len;
|
||
|
|
};
|
||
|
|
|
||
|
|
enum apfl_expr_param_type {
|
||
|
|
APFL_EXPR_PARAM_VAR,
|
||
|
|
APFL_EXPR_PARAM_CONSTANT,
|
||
|
|
APFL_EXPR_PARAM_PREDICATE,
|
||
|
|
APFL_EXPR_PARAM_EXPAND,
|
||
|
|
APFL_EXPR_PARAM_LIST,
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_params {
|
||
|
|
struct apfl_expr_param *params;
|
||
|
|
size_t len;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_param {
|
||
|
|
enum apfl_expr_param_type type;
|
||
|
|
|
||
|
|
union {
|
||
|
|
struct apfl_string var;
|
||
|
|
struct apfl_expr_const constant;
|
||
|
|
struct apfl_expr_param_predicate predicate;
|
||
|
|
struct apfl_expr_param *expand;
|
||
|
|
struct apfl_expr_params list;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_subfunc {
|
||
|
|
struct apfl_expr_params params;
|
||
|
|
struct apfl_expr_body body;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_complex_func {
|
||
|
|
struct apfl_expr_subfunc *subfuncs;
|
||
|
|
size_t len;
|
||
|
|
};
|
||
|
|
|
||
|
|
enum apfl_expr_assignable_type {
|
||
|
|
APFL_EXPR_ASSIGNABLE_VAR,
|
||
|
|
APFL_EXPR_ASSIGNABLE_CONSTANT,
|
||
|
|
APFL_EXPR_ASSIGNABLE_PREDICATE,
|
||
|
|
APFL_EXPR_ASSIGNABLE_EXPAND,
|
||
|
|
APFL_EXPR_ASSIGNABLE_DOT,
|
||
|
|
APFL_EXPR_ASSIGNABLE_AT,
|
||
|
|
APFL_EXPR_ASSIGNABLE_LIST,
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_assignable_predicate {
|
||
|
|
struct apfl_expr_assignable *lhs;
|
||
|
|
struct apfl_expr *rhs;
|
||
|
|
};
|
||
|
|
struct apfl_expr_assignable_dot {
|
||
|
|
struct apfl_expr_assignable *lhs;
|
||
|
|
struct apfl_string rhs;
|
||
|
|
};
|
||
|
|
struct apfl_expr_assignable_at {
|
||
|
|
struct apfl_expr_assignable *lhs;
|
||
|
|
struct apfl_expr *rhs;
|
||
|
|
};
|
||
|
|
struct apfl_expr_assignable_list {
|
||
|
|
struct apfl_expr_assignable *children;
|
||
|
|
size_t len;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_assignable {
|
||
|
|
enum apfl_expr_assignable_type type;
|
||
|
|
|
||
|
|
union {
|
||
|
|
struct apfl_string var;
|
||
|
|
struct apfl_expr_const constant;
|
||
|
|
struct apfl_expr_assignable_predicate predicate;
|
||
|
|
struct apfl_expr_assignable *expand;
|
||
|
|
struct apfl_expr_assignable_dot dot;
|
||
|
|
struct apfl_expr_assignable_at at;
|
||
|
|
struct apfl_expr_assignable_list list;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_assignment {
|
||
|
|
bool local;
|
||
|
|
struct apfl_expr_assignable lhs;
|
||
|
|
struct apfl_expr *rhs;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct apfl_expr_dot {
|
||
|
|
struct apfl_expr *lhs;
|
||
|
|
struct apfl_string rhs;
|
||
|
|
};
|
||
|
|
|
||
|
|
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;
|
||
|
|
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;
|
||
|
|
struct apfl_string var;
|
||
|
|
};
|
||
|
|
|
||
|
|
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_deinit(struct apfl_expr_body *);
|
||
|
|
void apfl_expr_const_deinit(struct apfl_expr_const *);
|
||
|
|
void apfl_expr_param_predicate_deinit(struct apfl_expr_param_predicate *);
|
||
|
|
void apfl_expr_param_list_deinit(struct apfl_expr_param_list *);
|
||
|
|
void apfl_expr_params_deinit(struct apfl_expr_params *);
|
||
|
|
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_dot_deinit(struct apfl_expr_assignable_dot *);
|
||
|
|
void apfl_expr_assignable_at_deinit(struct apfl_expr_assignable_at *);
|
||
|
|
void apfl_expr_assignable_list_deinit(struct apfl_expr_assignable_list *);
|
||
|
|
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_param_list apfl_expr_param_list_move(struct apfl_expr_param_list *);
|
||
|
|
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_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 *);
|
||
|
|
|
||
|
|
// 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);
|
||
|
|
|
||
|
|
|
||
|
|
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;
|
||
|
|
|
||
|
|
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);
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#endif
|