%{ #include #include "playlist.h" #define YYERROR_VERBOSE 1 /* Forwards */ 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); /* Globals */ int pl_number=2; %} %left OR AND %union { unsigned int ival; char *cval; PL_NODE *plval; } %token ARTIST %token ALBUM %token GENRE %token EQUALS %token LESS %token LESSEQUAL %token GREATER %token GREATEREQUAL %token IS %token INCLUDES %token OR %token AND %token NOT %token ID %token NUM %token YEAR %type expression %type predicate %type strtag %type inttag %type strbool %type intbool %type playlist %% playlistlist: playlist {} | playlistlist playlist {} ; playlist: ID '{' expression '}' { $$ = pl_addplaylist($1, $3); } ; expression: expression AND expression { $$=pl_newexpr($1,$2,$3); } | expression OR expression { $$=pl_newexpr($1,$2,$3); } | '(' expression ')' { $$=$2; } | predicate ; predicate: strtag strbool ID { $$=pl_newpredicate($1, $2, $3, T_STR); } | inttag intbool NUM { $$=pl_newpredicate($1, $2, $3, T_INT); } ; inttag: YEAR ; intbool: EQUALS { $$ = $1; } | LESS { $$ = $1; } | LESSEQUAL { $$ = $1; } | GREATER { $$ = $1; } | GREATEREQUAL { $$ = $1; } | NOT intbool { $$ = $2 | 0x80000000; } ; strtag: ARTIST | ALBUM | GENRE ; strbool: IS { $$=$1; } | INCLUDES { $$=$1; } | NOT strbool { $$=$2 | 0x80000000; } ; %% PL_NODE *pl_newpredicate(int tag, int op, char *value, int type) { PL_NODE *pnew; pnew=(PL_NODE*)malloc(sizeof(PL_NODE)); if(!pnew) return NULL; pnew->op=op; pnew->type=type; pnew->arg1.ival=tag; pnew->arg2.cval=value; return pnew; } PL_NODE *pl_newexpr(PL_NODE *arg1, int op, PL_NODE *arg2) { PL_NODE *pnew; pnew=(PL_NODE*)malloc(sizeof(PL_NODE)); if(!pnew) return NULL; pnew->op=op; pnew->arg1.plval=arg1; pnew->arg2.plval=arg2; return pnew; } int pl_addplaylist(char *name, PL_NODE *root) { SMART_PLAYLIST *pnew; pnew=(SMART_PLAYLIST *)malloc(sizeof(SMART_PLAYLIST)); if(!pnew) return -1; pnew->next=pl_smart.next; pnew->name=name; pnew->root=root; pnew->id=pl_number++; pl_smart.next=pnew; return 0; }