diff --git a/src/lexer.l b/src/lexer.l index 856280a1..9e2ebb02 100644 --- a/src/lexer.l +++ b/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]; } %% diff --git a/src/parser.y b/src/parser.y index c8a1db70..2ea1fc00 100644 --- a/src/parser.y +++ b/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 ALBUM %token GENRE +%token EQUALS +%token LESS +%token LESSEQUAL +%token GREATER +%token GREATEREQUAL %token IS %token INCLUDES @@ -37,12 +42,16 @@ int pl_number=2; %token NOT %token ID +%token NUM + +%token YEAR %type expression %type predicate -%type idtag -%type boolarg -%type value +%type strtag +%type inttag +%type strbool +%type intbool %type 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; diff --git a/src/playlist.c b/src/playlist.c index f508058c..4656dfc0 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -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 (" "); 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(" "); 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("\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; diff --git a/src/playlist.h b/src/playlist.h index 3003e22a..7e1e01a7 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -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;