/* SPDX-License-Identifier: GPL-2.0 */ /** * \file mp.h Internal mood parser API (backend). * * This header is included from the lexer, the parser, and from \ref mp.c, but * not from \ref mood.c, the only user of the mood parser front end. It * contains structures and function prototypes which are considered * implementation details. * * There is one function for each keyword in the context-free grammar of the * parser. These functions return the semantic value of the keyword. * * The functions declared here are defined either in mp.c or in mp.y. */ /** Opaque, only known to mp.c. Passed to the generated mp_yyparse(). */ struct mp_context; /** * Since we use a reentrant lexer, all functions generated by flex(1) * receive an additional argument of this type. */ typedef void *mp_yyscan_t; /** Parsed regex pattern. */ struct mp_re_pattern { regex_t preg; /**< Pre-compiled regex. **/ unsigned flags; /**< Subset of the cflags described in regex(3). */ }; /** Parsed wildcard pattern. */ struct mp_wc_pattern { char *pat; /**< Unescaped C string (without quotes and flags). */ unsigned flags; /**< For modifying matching behaviour. */ }; /** * The possible values of a node in the abstract syntax tree (AST). * * Constant semantic values (string literals, numeric constants, wildcard and * regex patterns which are part of the mood definition) are determined during * \ref mp_init() while values which depend on the audio file (path, bitrate, * etc.) are determined during mp_eval_row(). * * This union, and the \ref mp_ast_node structure below are used extensively in * mp.y. However, both need to be public because the lexer must be able to * create AST nodes for the constant semantic values. */ union mp_semantic_value { bool boolval; /**< Comparators, =~ and =|. */ char *strval; /**< String literals, tags, path. */ int64_t intval; /**< Constants, bitrate, frequency, etc. */ struct mp_wc_pattern wc_pattern; /**< Right-hand side operand of =|. */ struct mp_re_pattern re_pattern; /**< Right-hand side operand of =~. */ }; /** * Describes one node of the abstract syntax tree. * * A node is either interior or a leaf node. Interior nodes have at least one * child while leaf nodes have a semantic value and no children. * * Examples: (a) STRING_LITERAL has a semantic value (the unescaped string * literal) and no children, (b) NEG (unary minus) has no semantic value but * one child (the numeric expression that is to be negated), (c) LESS_OR_EQUAL * has no semantic value and two children (the two numeric expressions being * compared). */ struct mp_ast_node { /** Corresponds to a token type, for example LESS_OR_EQUAL. */ int id; union { /** Pointers to the child nodes (interior nodes only). */ struct mp_ast_node **children; /** Leaf nodes only. */ union mp_semantic_value sv; }; /** * The number of children is implicitly given by the id, but we include * it here to avoid having to maintain a lookup table. The AST is * usually small, so we can afford to waste a byte per node. */ uint8_t num_children; }; /* Called from both the lexer and the parser. */ __printf_3_4 void mp_parse_error(int line, struct mp_context *ctx, const char *fmt, ...); /* Helper functions for the lexer. */ unsigned parse_quoted_string(const char *src, const char quote_chars[2], char **result); int mp_parse_regex_pattern(const char *src, struct mp_re_pattern *result); void mp_parse_wildcard_pattern(const char *src, struct mp_wc_pattern *result); /* * The functions below are implemented in mp.y. They are documented here * because mp.y is not doxyfied. */ /** * Allocate a new leaf node for the abstract syntax tree. * * \param id Initial value for the ->id field of the new node * * \return Pointer to a node whose ->num_children field is initialized to zero. * The caller is expected to initialize the ->sv field. */ struct mp_ast_node *mp_new_ast_leaf_node(int id); /** * Evaluate an abstract syntax tree, starting at the root node. * * \param root As returned from \ref mp_init() via the context pointer. * \param ctx Contains the aft row to evaluate. * * \return True if the AST evaluates to true, a non-empty string, or a * non-zero number. False otherwise. * * \sa mp_eval_row(). */ bool mp_eval_ast(struct mp_ast_node *root, struct mp_context *ctx); /** * Deallocate an abstract syntax tree. * * This frees the memory occupied by the nodes of the AST, the child pointers * of the internal nodes and the (constant) semantic values of the leaf nodes * (string literals, unescaped wildcard patterns and pre-compiled regular * expressions). * * \param root It's OK to pass NULL here. */ void mp_free_ast(struct mp_ast_node *root); /* Helper functions for the parser. */ bool mp_is_set(const char *attr, struct mp_context *ctx); char *mp_path(struct mp_context *ctx); int64_t mp_year(struct mp_context *ctx); int64_t mp_num_attributes_set(struct mp_context *ctx); int64_t mp_duration(struct mp_context *ctx); /* Generated with MP_AFSI() */ /** \cond MP_AFSI */ int64_t mp_num_played(struct mp_context *ctx); int64_t mp_image_id(struct mp_context *ctx); int64_t mp_lyrics_id(struct mp_context *ctx); /** \endcond */ /* Generated with MP_AFHI() */ /** \cond MP_AFHI */ int64_t mp_bitrate(struct mp_context *ctx); int64_t mp_frequency(struct mp_context *ctx); int64_t mp_channels(struct mp_context *ctx); /** \endcond */ /* Generated with MP_TAG() */ /** \cond MP_TAG */ char *mp_artist(struct mp_context *ctx); char *mp_title(struct mp_context *ctx); char *mp_album(struct mp_context *ctx); char *mp_comment(struct mp_context *ctx); /** \endcond */