Add YEAR token, and integer ops -- equal, greater, less, etc.

This commit is contained in:
Ron Pedde 2003-12-07 06:36:06 +00:00
parent 47dd724c35
commit e35cf88e50
4 changed files with 110 additions and 31 deletions

View File

@ -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]; }
%%

View File

@ -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;

View File

@ -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;

View File

@ -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;