mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-24 22:25:56 -05: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); }
|
||||
genre { yylval.ival=GENRE; return(GENRE); }
|
||||
|
||||
is |
|
||||
= { yylval.ival=IS; return(IS); }
|
||||
year { yylval.ival=YEAR; return(YEAR); }
|
||||
|
||||
includes |
|
||||
=~ |
|
||||
~= { yylval.ival=INCLUDES; return(INCLUDES); }
|
||||
is { yylval.ival=IS; return(IS); }
|
||||
includes { yylval.ival=INCLUDES; return(INCLUDES); }
|
||||
= { yylval.ival=EQUALS; return(EQUALS); }
|
||||
|
||||
or |
|
||||
\|\| { yylval.ival=OR; return(OR); }
|
||||
@ -46,12 +45,18 @@ and |
|
||||
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);
|
||||
if(yylval.cval[strlen(yylval.cval)-1] == '"');
|
||||
yylval.cval[strlen(yylval.cval)-1] = '\0';
|
||||
return(ID); }
|
||||
|
||||
[0-9]+ { yylval.ival=atoi(yytext); return(NUM); }
|
||||
|
||||
. { return yytext[0]; }
|
||||
|
||||
%%
|
||||
|
45
src/parser.y
45
src/parser.y
@ -7,7 +7,7 @@
|
||||
|
||||
/* 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 int pl_addplaylist(char *name, PL_NODE *root);
|
||||
|
||||
@ -29,6 +29,11 @@ int pl_number=2;
|
||||
%token <ival> ALBUM
|
||||
%token <ival> GENRE
|
||||
|
||||
%token <ival> EQUALS
|
||||
%token <ival> LESS
|
||||
%token <ival> LESSEQUAL
|
||||
%token <ival> GREATER
|
||||
%token <ival> GREATEREQUAL
|
||||
%token <ival> IS
|
||||
%token <ival> INCLUDES
|
||||
|
||||
@ -37,12 +42,16 @@ int pl_number=2;
|
||||
%token <ival> NOT
|
||||
|
||||
%token <cval> ID
|
||||
%token <ival> NUM
|
||||
|
||||
%token <ival> YEAR
|
||||
|
||||
%type <plval> expression
|
||||
%type <plval> predicate
|
||||
%type <ival> idtag
|
||||
%type <ival> boolarg
|
||||
%type <cval> value
|
||||
%type <ival> strtag
|
||||
%type <ival> inttag
|
||||
%type <ival> strbool
|
||||
%type <ival> intbool
|
||||
%type <ival> playlist
|
||||
|
||||
%%
|
||||
@ -60,25 +69,34 @@ expression: expression AND expression { $$=pl_newexpr($1,$2,$3); }
|
||||
| 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
|
||||
| GENRE
|
||||
;
|
||||
|
||||
boolarg: IS { $$=$1; }
|
||||
strbool: IS { $$=$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;
|
||||
|
||||
pnew=(PL_NODE*)malloc(sizeof(PL_NODE));
|
||||
@ -86,6 +104,7 @@ PL_NODE *pl_newpredicate(int tag, int op, char *value) {
|
||||
return NULL;
|
||||
|
||||
pnew->op=op;
|
||||
pnew->type=type;
|
||||
pnew->arg1.ival=tag;
|
||||
pnew->arg2.cval=value;
|
||||
return pnew;
|
||||
|
@ -73,6 +73,9 @@ void pl_dump_node(PL_NODE *pnode, int indent) {
|
||||
case GENRE:
|
||||
printf("GENRE ");
|
||||
break;
|
||||
case YEAR:
|
||||
printf("YEAR ");
|
||||
break;
|
||||
default:
|
||||
printf ("<unknown tag> ");
|
||||
break;
|
||||
@ -89,12 +92,37 @@ void pl_dump_node(PL_NODE *pnode, int indent) {
|
||||
case INCLUDES:
|
||||
printf("%s",not? "DOES NOT INCLUDE " : "INCLUDES ");
|
||||
break;
|
||||
case EQUALS:
|
||||
printf("EQUALS ");
|
||||
break;
|
||||
case LESS:
|
||||
printf("< ");
|
||||
break;
|
||||
case LESSEQUAL:
|
||||
printf("<= ");
|
||||
break;
|
||||
case GREATER:
|
||||
printf("> ");
|
||||
break;
|
||||
case GREATEREQUAL:
|
||||
printf(">= ");
|
||||
break;
|
||||
default:
|
||||
printf("<unknown boolop> ");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -161,7 +189,8 @@ void pl_eval(MP3FILE *pmp3) {
|
||||
int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
||||
int r_arg,r_arg2;
|
||||
int argtypec;
|
||||
char *argc;
|
||||
char *cval;
|
||||
int ival;
|
||||
int boolarg;
|
||||
int not=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 */
|
||||
switch(pnode->arg1.ival) {
|
||||
case ALBUM:
|
||||
argtypec=1;
|
||||
argc=pmp3->album;
|
||||
cval=pmp3->album;
|
||||
break;
|
||||
case ARTIST:
|
||||
argtypec=1;
|
||||
argc=pmp3->artist;
|
||||
cval=pmp3->artist;
|
||||
break;
|
||||
case GENRE:
|
||||
argtypec=1;
|
||||
argc=pmp3->genre;
|
||||
cval=pmp3->genre;
|
||||
break;
|
||||
case YEAR:
|
||||
ival=pmp3->year;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -200,24 +229,45 @@ int pl_eval_node(MP3FILE *pmp3, PL_NODE *pnode) {
|
||||
if(pnode->op & 0x80000000)
|
||||
not=1;
|
||||
|
||||
if(argtypec) {
|
||||
if(!argc)
|
||||
return not;
|
||||
if(pnode->type==T_STR) {
|
||||
if(!cval)
|
||||
cval = "";
|
||||
|
||||
DPRINTF(ERR_DEBUG,"Matching %s to %s\n",argc,pnode->arg2.cval);
|
||||
|
||||
switch(boolarg) {
|
||||
case IS:
|
||||
r_arg=strcasecmp(argc,pnode->arg2.cval);
|
||||
r_arg=strcasecmp(cval,pnode->arg2.cval);
|
||||
retval = not ? r_arg : !r_arg;
|
||||
break;
|
||||
case INCLUDES:
|
||||
r_arg=strcasestr(argc,pnode->arg2.cval);
|
||||
r_arg=strcasestr(cval,pnode->arg2.cval);
|
||||
retval = not ? !r_arg : r_arg;
|
||||
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 */
|
||||
DPRINTF(ERR_DEBUG,"Returning %d\n",retval);
|
||||
return retval;
|
||||
|
@ -8,14 +8,19 @@
|
||||
|
||||
#include "mp3-scanner.h"
|
||||
|
||||
#define T_INT 0
|
||||
#define T_STR 1
|
||||
|
||||
typedef struct tag_pl_node {
|
||||
int op;
|
||||
int type;
|
||||
union {
|
||||
int ival;
|
||||
struct tag_pl_node *plval;
|
||||
} arg1;
|
||||
union {
|
||||
char *cval;
|
||||
int ival;
|
||||
struct tag_pl_node *plval;
|
||||
} arg2;
|
||||
} PL_NODE;
|
||||
|
Loading…
Reference in New Issue
Block a user