summaryrefslogtreecommitdiff
path: root/mp.h
blob: c576924678c25315af5c15c149657c4e033f55ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* 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 */