]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - mp.h
Version 2 moods.
[paraslash.git] / mp.h
diff --git a/mp.h b/mp.h
new file mode 100644 (file)
index 0000000..93bbab3
--- /dev/null
+++ b/mp.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 Andre Noll <maan@tuebingen.mpg.de>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/**
+ * \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);
+
+/* 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 */