mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-01 02:03:45 -04:00
Add YEAR token, and integer ops -- equal, greater, less, etc.
This commit is contained in:
parent
47dd724c35
commit
e35cf88e50
15
src/lexer.l
15
src/lexer.l
@ -30,12 +30,11 @@ artist { yylval.ival=ARTIST; return(ARTIST); }
|
|||||||
album { yylval.ival=ALBUM; return(ALBUM); }
|
album { yylval.ival=ALBUM; return(ALBUM); }
|
||||||
genre { yylval.ival=GENRE; return(GENRE); }
|
genre { yylval.ival=GENRE; return(GENRE); }
|
||||||
|
|
||||||
is |
|
year { yylval.ival=YEAR; return(YEAR); }
|
||||||
= { yylval.ival=IS; return(IS); }
|
|
||||||
|
|
||||||
includes |
|
is { yylval.ival=IS; return(IS); }
|
||||||
=~ |
|
includes { yylval.ival=INCLUDES; return(INCLUDES); }
|
||||||
~= { yylval.ival=INCLUDES; return(INCLUDES); }
|
= { yylval.ival=EQUALS; return(EQUALS); }
|
||||||
|
|
||||||
or |
|
or |
|
||||||
\|\| { yylval.ival=OR; return(OR); }
|
\|\| { yylval.ival=OR; return(OR); }
|
||||||
@ -46,12 +45,18 @@ and |
|
|||||||
not |
|
not |
|
||||||
! { yylval.ival=1; return(NOT); }
|
! { yylval.ival=1; return(NOT); }
|
||||||
|
|
||||||
|
\<= { yylval.ival=LESSEQUAL; return(LESSEQUAL); }
|
||||||
|
\< { yylval.ival=LESS; return(LESS); }
|
||||||
|
\>= { yylval.ival=GREATEREQUAL; return(GREATEREQUAL); }
|
||||||
|
\> { yylval.ival=GREATER; return(GREATER); }
|
||||||
|
|
||||||
{qstring} { yylval.cval=strdup(yytext+1);
|
{qstring} { yylval.cval=strdup(yytext+1);
|
||||||
if(yylval.cval[strlen(yylval.cval)-1] == '"');
|
if(yylval.cval[strlen(yylval.cval)-1] == '"');
|
||||||
yylval.cval[strlen(yylval.cval)-1] = '\0';
|
yylval.cval[strlen(yylval.cval)-1] = '\0';
|
||||||
return(ID); }
|
return(ID); }
|
||||||
|
|
||||||
|
[0-9]+ { yylval.ival=atoi(yytext); return(NUM); }
|
||||||
|
|
||||||
. { return yytext[0]; }
|
. { return yytext[0]; }
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
45
src/parser.y
45
src/parser.y
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
/* Forwards */
|
/* Forwards */
|
||||||
|
|
||||||
extern PL_NODE *pl_newpredicate(int tag, int op, char *value);
|
extern PL_NODE *pl_newpredicate(int tag, int op, char *value, int type);
|
||||||
extern PL_NODE *pl_newexpr(PL_NODE *arg1, int op, PL_NODE *arg2);
|
extern PL_NODE *pl_newexpr(PL_NODE *arg1, int op, PL_NODE *arg2);
|
||||||
extern int pl_addplaylist(char *name, PL_NODE *root);
|
extern int pl_addplaylist(char *name, PL_NODE *root);
|
||||||
|
|
||||||
@ -29,6 +29,11 @@ int pl_number=2;
|
|||||||
%token <ival> ALBUM
|
%token <ival> ALBUM
|
||||||
%token <ival> GENRE
|
%token <ival> GENRE
|
||||||
|
|
||||||
|
%token <ival> EQUALS
|
||||||
|
%token <ival> LESS
|
||||||
|
%token <ival> LESSEQUAL
|
||||||
|
%token <ival> GREATER
|
||||||
|
%token <ival> GREATEREQUAL
|
||||||
%token <ival> IS
|
%token <ival> IS
|
||||||
%token <ival> INCLUDES
|
%token <ival> INCLUDES
|
||||||
|
|
||||||
@ -37,12 +42,16 @@ int pl_number=2;
|
|||||||
%token <ival> NOT
|
%token <ival> NOT
|
||||||
|
|
||||||
%token <cval> ID
|
%token <cval> ID
|
||||||
|
%token <ival> NUM
|
||||||
|
|
||||||
|
%token <ival> YEAR
|
||||||
|
|
||||||
%type <plval> expression
|
%type <plval> expression
|
||||||
%type <plval> predicate
|
%type <plval> predicate
|
||||||
%type <ival> idtag
|
%type <ival> strtag
|
||||||
%type <ival> boolarg
|
%type <ival> inttag
|
||||||
%type <cval> value
|
%type <ival> strbool
|
||||||
|
%type <ival> intbool
|
||||||
%type <ival> playlist
|
%type <ival> playlist
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@ -60,25 +69,34 @@ expression: expression AND expression { $$=pl_newexpr($1,$2,$3); }
|
|||||||
| predicate
|
| predicate
|
||||||
;
|
;
|
||||||
|
|
||||||
predicate: idtag boolarg value { $$=pl_newpredicate($1, $2, $3); }
|
predicate: strtag strbool ID { $$=pl_newpredicate($1, $2, $3, T_STR); }
|
||||||
|
| inttag intbool NUM { $$=pl_newpredicate($1, $2, $3, T_INT); }
|
||||||
|
;
|
||||||
|
|
||||||
idtag: ARTIST
|
inttag: YEAR
|
||||||
|
;
|
||||||
|
|
||||||
|
intbool: EQUALS { $$ = $1; }
|
||||||
|
| LESS { $$ = $1; }
|
||||||
|
| LESSEQUAL { $$ = $1; }
|
||||||
|
| GREATER { $$ = $1; }
|
||||||
|
| GREATEREQUAL { $$ = $1; }
|
||||||
|
| NOT intbool { $$ = $2 | 0x80000000; }
|
||||||
|
;
|
||||||
|
|
||||||
|
strtag: ARTIST
|
||||||
| ALBUM
|
| ALBUM
|
||||||
| GENRE
|
| GENRE
|
||||||
;
|
;
|
||||||
|
|
||||||
boolarg: IS { $$=$1; }
|
strbool: IS { $$=$1; }
|
||||||
| INCLUDES { $$=$1; }
|
| INCLUDES { $$=$1; }
|
||||||
| NOT boolarg { $$=$2 | 0x80000000; }
|
| NOT strbool { $$=$2 | 0x80000000; }
|
||||||
;
|
;
|
||||||
|
|
||||||
value: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
PL_NODE *pl_newpredicate(int tag, int op, char *value) {
|
PL_NODE *pl_newpredicate(int tag, int op, char *value, int type) {
|
||||||
PL_NODE *pnew;
|
PL_NODE *pnew;
|
||||||
|
|
||||||
pnew=(PL_NODE*)malloc(sizeof(PL_NODE));
|
pnew=(PL_NODE*)malloc(sizeof(PL_NODE));
|
||||||
@ -86,6 +104,7 @@ PL_NODE *pl_newpredicate(int tag, int op, char *value) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pnew->op=op;
|
pnew->op=op;
|
||||||
|
pnew->type=type;
|
||||||
pnew->arg1.ival=tag;
|
pnew->arg1.ival=tag;
|
||||||
pnew->arg2.cval=value;
|
pnew->arg2.cval=value;
|
||||||
return pnew;
|
return pnew;
|
||||||
|
@ -73,6 +73,9 @@ void pl_dump_node(PL_NODE *pnode, int indent) {
|
|||||||
case GENRE:
|
case GENRE:
|
||||||
printf("GENRE ");
|
printf("GENRE ");
|
||||||
break;
|
break;
|
||||||
|
case YEAR:
|
||||||
|
printf("YEAR ");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf ("<unknown tag> ");
|
printf ("<unknown tag> ");
|
||||||
break;
|
break;
|
||||||
@ -89,12 +92,37 @@ void pl_dump_node(PL_NODE *pnode, int indent) {
|
|||||||
case INCLUDES:
|
case INCLUDES:
|
||||||
printf("%s",not? "DOES NOT INCLUDE " : "INCLUDES ");
|
printf("%s",not? "DOES NOT INCLUDE " : "INCLUDES ");
|
||||||
break;
|
break;
|
||||||
|
case EQUALS:
|
||||||
|
printf("EQUALS ");
|
||||||
|
break;
|
||||||
|
case LESS:
|
||||||
|
printf("< ");
|
||||||
|
break;
|
||||||
|
case LESSEQUAL:
|
||||||
|
printf("<= ");
|
||||||
|
break;
|
||||||
|
case GREATER:
|
||||||
|
printf("> ");
|
||||||
|
break;
|
||||||
|
case GREATEREQUAL:
|
||||||
|
printf(">= ");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("<unknown boolop> ");
|
printf("<unknown boolop> ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s\n",pnode->arg2.cval);
|
switch(pnode->type) {
|
||||||
|
case T_STR:
|
||||||
|
printf("%s\n",pnode->arg2.cval);
|
||||||
|
break;
|
||||||
|
case T_INT:
|
||||||
|
printf("%d\n",pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("<unknown type>\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +189,8 @@ void pl_eval(MP3FILE *pmp3) {
|
|||||||
int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
||||||
int r_arg,r_arg2;
|
int r_arg,r_arg2;
|
||||||
int argtypec;
|
int argtypec;
|
||||||
char *argc;
|
char *cval;
|
||||||
|
int ival;
|
||||||
int boolarg;
|
int boolarg;
|
||||||
int not=0;
|
int not=0;
|
||||||
int retval=0;
|
int retval=0;
|
||||||
@ -183,16 +212,16 @@ int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
|||||||
/* Not an AND/OR node, so let's eval */
|
/* Not an AND/OR node, so let's eval */
|
||||||
switch(pnode->arg1.ival) {
|
switch(pnode->arg1.ival) {
|
||||||
case ALBUM:
|
case ALBUM:
|
||||||
argtypec=1;
|
cval=pmp3->album;
|
||||||
argc=pmp3->album;
|
|
||||||
break;
|
break;
|
||||||
case ARTIST:
|
case ARTIST:
|
||||||
argtypec=1;
|
cval=pmp3->artist;
|
||||||
argc=pmp3->artist;
|
|
||||||
break;
|
break;
|
||||||
case GENRE:
|
case GENRE:
|
||||||
argtypec=1;
|
cval=pmp3->genre;
|
||||||
argc=pmp3->genre;
|
break;
|
||||||
|
case YEAR:
|
||||||
|
ival=pmp3->year;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,24 +229,45 @@ int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
|||||||
if(pnode->op & 0x80000000)
|
if(pnode->op & 0x80000000)
|
||||||
not=1;
|
not=1;
|
||||||
|
|
||||||
if(argtypec) {
|
if(pnode->type==T_STR) {
|
||||||
if(!argc)
|
if(!cval)
|
||||||
return not;
|
cval = "";
|
||||||
|
|
||||||
DPRINTF(ERR_DEBUG,"Matching %s to %s\n",argc,pnode->arg2.cval);
|
DPRINTF(ERR_DEBUG,"Matching %s to %s\n",argc,pnode->arg2.cval);
|
||||||
|
|
||||||
switch(boolarg) {
|
switch(boolarg) {
|
||||||
case IS:
|
case IS:
|
||||||
r_arg=strcasecmp(argc,pnode->arg2.cval);
|
r_arg=strcasecmp(cval,pnode->arg2.cval);
|
||||||
retval = not ? r_arg : !r_arg;
|
retval = not ? r_arg : !r_arg;
|
||||||
break;
|
break;
|
||||||
case INCLUDES:
|
case INCLUDES:
|
||||||
r_arg=strcasestr(argc,pnode->arg2.cval);
|
r_arg=strcasestr(cval,pnode->arg2.cval);
|
||||||
retval = not ? !r_arg : r_arg;
|
retval = not ? !r_arg : r_arg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pnode->type==T_INT) {
|
||||||
|
switch(boolarg) {
|
||||||
|
case EQUALS:
|
||||||
|
r_arg=(ival == pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
case GREATER:
|
||||||
|
r_arg=(ival > pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
case GREATEREQUAL:
|
||||||
|
r_arg=(ival >= pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
case LESS:
|
||||||
|
r_arg=(ival < pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
case LESSEQUAL:
|
||||||
|
r_arg=(ival <= pnode->arg2.ival);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return not? !r_arg : r_arg;
|
||||||
|
}
|
||||||
|
|
||||||
/* can't get here */
|
/* can't get here */
|
||||||
DPRINTF(ERR_DEBUG,"Returning %d\n",retval);
|
DPRINTF(ERR_DEBUG,"Returning %d\n",retval);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -8,14 +8,19 @@
|
|||||||
|
|
||||||
#include "mp3-scanner.h"
|
#include "mp3-scanner.h"
|
||||||
|
|
||||||
|
#define T_INT 0
|
||||||
|
#define T_STR 1
|
||||||
|
|
||||||
typedef struct tag_pl_node {
|
typedef struct tag_pl_node {
|
||||||
int op;
|
int op;
|
||||||
|
int type;
|
||||||
union {
|
union {
|
||||||
int ival;
|
int ival;
|
||||||
struct tag_pl_node *plval;
|
struct tag_pl_node *plval;
|
||||||
} arg1;
|
} arg1;
|
||||||
union {
|
union {
|
||||||
char *cval;
|
char *cval;
|
||||||
|
int ival;
|
||||||
struct tag_pl_node *plval;
|
struct tag_pl_node *plval;
|
||||||
} arg2;
|
} arg2;
|
||||||
} PL_NODE;
|
} PL_NODE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user