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
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Since we do not supply yywrap(), we use noyywrap to instruct the scanner to
* behave as though yywrap() returned 1.
*/
%option noyywrap
/*
* We don't want symbols to clash with those of other flex users, particularly
* lopsub.
*/
%option prefix="mp_yy"
/*
* Generate a scanner that maintains the number of the current line read from
* its input in the yylineno variable.
*/
%option yylineno
/* Generate a bison-compatible scanner. */
%option bison-bridge bison-locations
/*
* Warn (in particular) if the default rule can be matched but no default rule
* has been given.
*/
%option warn
/*
* Generate a scanner which is portable and safe to use in one or more threads
* of control.
*/
%option reentrant
/*
* Generate a scanner which always looks one extra character ahead. This is a
* bit faster than an interactive scanner for which look ahead happens only
* when necessary.
*/
%option never-interactive
%{
#include <regex.h>
#include "para.h"
#include "string.h"
#include "mp.h"
#include "error.h"
#define YYSTYPE MP_YYSTYPE
#define YYLTYPE MP_YYLTYPE
#define YY_DECL int mp_yylex(MP_YYSTYPE *yylval_param, MP_YYLTYPE *yylloc_param, \
struct mp_context *ctx, struct mp_ast_node **ast, mp_yyscan_t yyscanner)
#include "mp.bison.h"
#define MP_YY_USER_ACTION do {mp_yylloc->first_line = mp_yylineno;} while (0);
%}
DECIMAL_CONSTANT (0|([[:digit:]]{-}[0])[[:digit:]]*)
STRING_LITERAL \"([^\"\\\n]|(\\[\"\\abfnrtv]))*\"
REGEX_PATTERN \/([^\/\\\n]|(\\[\/\\abfnrtv]))*\/([in])*
WILDCARD_PATTERN \|([^\|\\\n]|(\\[\|\\abfnrtv]))*\|([npPlie])*
%%
is_set {return IS_SET;}
num_attributes_set {return NUM_ATTRIBUTES_SET;}
path {return PATH;}
artist {return ARTIST;}
title {return TITLE;}
album {return ALBUM;}
comment {return COMMENT;}
year {return YEAR;}
num_played {return NUM_PLAYED;}
image_id {return IMAGE_ID;}
lyrics_id {return LYRICS_ID;}
bitrate {return BITRATE;}
frequency {return FREQUENCY;}
channels {return CHANNELS;}
duration {return DURATION;}
true {return TRUE;}
false {return FALSE;}
[[:space:]]+|#.*\n /* skip comments and whitespace */
"("|")"|","|"+"|"-"|"*"|"/"|"<"|">" {return yytext[0];}
"||" {return OR;}
"&&" {return AND;}
"!" {return NOT;}
"==" {return EQUAL;}
"!=" {return NOT_EQUAL;}
"<=" {return LESS_OR_EQUAL;}
">=" {return GREATER_OR_EQUAL;}
"=~" {return REGEX_MATCH;}
"=|" {return FILENAME_MATCH;}
{DECIMAL_CONSTANT} {
int ret;
yylval->node = mp_new_ast_leaf_node(NUM);
ret = para_atoi64(yytext, &yylval->node->sv.intval);
if (ret < 0) {
free(yylval->node);
mp_parse_error(yylloc->first_line, ctx, "%s: %s", yytext,
para_strerror(-ret));
return -E_MOOD_PARSE;
}
return NUM;
}
{STRING_LITERAL} {
yylval->node = mp_new_ast_leaf_node(STRING_LITERAL);
parse_quoted_string(yytext, "\"\"", &yylval->node->sv.strval);
//PARA_CRIT_LOG("strval: %s\n", yylval->node->sv.strval);
//PARA_CRIT_LOG("node: %p\n", yylval->node);
return STRING_LITERAL;
}
{REGEX_PATTERN} {
int ret;
yylval->node = mp_new_ast_leaf_node(REGEX_PATTERN);
ret = mp_parse_regex_pattern(yytext, &yylval->node->sv.re_pattern);
if (ret < 0) {
free(yylval->node);
mp_parse_error(yylloc->first_line, ctx, "%s: %s", yytext,
para_strerror(-ret));
return -E_MOOD_PARSE;
}
return REGEX_PATTERN;
}
{WILDCARD_PATTERN} {
yylval->node = mp_new_ast_leaf_node(WILDCARD_PATTERN);
mp_parse_wildcard_pattern(yytext, &yylval->node->sv.wc_pattern);
return WILDCARD_PATTERN;
}
. {
mp_parse_error(yylloc->first_line, ctx, "unrecognized text: %s",
yytext);
return -E_MOOD_PARSE;
}
|