diff options
| author | Michiel Van Der Kolk <not.valid@email.address> | 2005-04-28 12:33:38 +0000 |
|---|---|---|
| committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-04-28 12:33:38 +0000 |
| commit | 9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8 (patch) | |
| tree | 0276c6299a3b26705b028f399ceadf3ac7867b2f /apps/plugins/searchengine/parser.c | |
| parent | a7f7781dca4db172a507e7e6f73bee03fc7deb2f (diff) | |
| download | rockbox-9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8.zip rockbox-9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8.tar.gz rockbox-9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8.tar.bz2 rockbox-9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8.tar.xz | |
Search engine core for database v2, has an hardcoded "songs for year >= 1980 and year < 1990" at the moment.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6367 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/searchengine/parser.c')
| -rw-r--r-- | apps/plugins/searchengine/parser.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/apps/plugins/searchengine/parser.c b/apps/plugins/searchengine/parser.c new file mode 100644 index 0000000..fe10452 --- /dev/null +++ b/apps/plugins/searchengine/parser.c @@ -0,0 +1,240 @@ +#include "searchengine.h" +#include "token.h" +#include "dbinterface.h" +#include "parser.h" + +struct token *tokenbuffer,*currentToken; +int currentindex; +int syntaxerror; +char errormsg[250]; + +unsigned char *parse(struct token *tokenbuf) { + unsigned char *ret=0; + currentindex=0; + syntaxerror=0; + tokenbuffer=tokenbuf; + database_init(); + currentToken=&tokenbuffer[currentindex]; + PUTS("parse"); + ret=parseMExpr(); + if(syntaxerror) { + PUTS("Syntaxerror"); + rb->splash(HZ*3,true,errormsg); + } + parser_accept(TOKEN_EOF); + return ret; +} + +void parser_acceptIt(void) { + if(syntaxerror) return; + currentToken=&tokenbuffer[++currentindex]; +} + +int parser_accept(unsigned char kind) { + if(currentToken->kind!=kind) { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where '%d' expected\n",currentToken->kind,kind); + return 0; + } + else { + parser_acceptIt(); + return 1; + } +} + +unsigned char *parseCompareNum() { + struct token *number1,*number2; + unsigned char *ret; + int i,n1=-1,n2=-1; + int op; + if(syntaxerror) return 0; + PUTS("parseCompareNum"); + if(currentToken->kind==TOKEN_NUM || + currentToken->kind==TOKEN_NUMIDENTIFIER) { + number1=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind); + return 0; + } + if(currentToken->kind>=TOKEN_GT && currentToken->kind <= TOKEN_NE) { + op=currentToken->kind; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUMOP expected\n",currentToken->kind); + return 0; + } + if(currentToken->kind==TOKEN_NUM || + currentToken->kind==TOKEN_NUMIDENTIFIER) { + number2=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind); + return 0; + } + ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount); + if(number1->kind==TOKEN_NUM) + n1=getvalue(number1); + if(number2->kind==TOKEN_NUM) + n2=getvalue(number2); + for(i=0;i<rb->tagdbheader->filecount;i++) { + loadentry(i); + if(number1->kind==TOKEN_NUMIDENTIFIER) + n1=getvalue(number1); + if(number2->kind==TOKEN_NUMIDENTIFIER) + n2=getvalue(number2); + switch(op) { + case TOKEN_GT: + ret[i]=n1 > n2; + break; + case TOKEN_GTE: + ret[i]=n1 >= n2; + break; + case TOKEN_LT: + ret[i]=n1 < n2; + break; + case TOKEN_LTE: + ret[i]=n1 <= n2; + break; + case TOKEN_EQ: + ret[i]=n1 == n2; + break; + case TOKEN_NE: + ret[i]=n1 != n2; + break; + } + } + return ret; +} + +unsigned char *parseCompareString() { + struct token *string1,*string2; + unsigned char *ret; + char *s1=NULL,*s2=NULL; + int i,contains; + if(syntaxerror) return 0; + PUTS("parseCompareString"); + if(currentToken->kind==TOKEN_STRING || + currentToken->kind==TOKEN_STRINGIDENTIFIER) { + string1=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind); + return 0; + } + + contains=currentToken->kind==TOKEN_CONTAINS; + if(currentToken->kind==TOKEN_CONTAINS || + currentToken->kind==TOKEN_EQUALS) + parser_acceptIt(); + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where CONTAINS/EQUALS expected\n",currentToken->kind); + return 0; + } + + if(currentToken->kind==TOKEN_STRING || + currentToken->kind==TOKEN_STRINGIDENTIFIER) { + string2=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind); + return 0; + } + ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount); + if(string1->kind==TOKEN_STRING) + s1=getstring(string1); + if(string2->kind==TOKEN_STRING) + s2=getstring(string2); + for(i=0;i<rb->tagdbheader->filecount;i++) { + loadentry(i); + if(string1->kind==TOKEN_STRINGIDENTIFIER) + s1=getstring(string1); + if(string2->kind==TOKEN_STRINGIDENTIFIER) + s2=getstring(string2); + if(contains) + ret[i]=rb->strcasestr(s1,s2)!=0; + else + ret[i]=rb->strcasecmp(s1,s2)==0; + } + return ret; +} + +unsigned char *parseExpr() { + unsigned char *ret; + int i; + if(syntaxerror) return 0; + PUTS("parseExpr"); + switch(currentToken->kind) { + case TOKEN_NOT: + parser_accept(TOKEN_NOT); + PUTS("parseNot"); + ret = parseExpr(); + if(ret==NULL) return 0; + for(i=0;i<rb->tagdbheader->filecount;i++) + ret[i]=!ret[i]; + break; + case TOKEN_LPAREN: + parser_accept(TOKEN_LPAREN); + ret = parseMExpr(); + if(ret==NULL) return 0; + parser_accept(TOKEN_RPAREN); + break; + case TOKEN_NUM: + case TOKEN_NUMIDENTIFIER: + ret = parseCompareNum(); + if(ret==NULL) return 0; + break; + case TOKEN_STRING: + case TOKEN_STRINGIDENTIFIER: + ret = parseCompareString(); + if(ret==NULL) return 0; + break; + default: + // error, unexpected symbol + syntaxerror=1; + rb->snprintf(errormsg,250,"unexpected '%d' found at parseExpr\n",currentToken->kind); + ret=0; + break; + } + return ret; +} + +unsigned char *parseMExpr() { + unsigned char *ret,*ret2; + int i; + if(syntaxerror) return 0; + PUTS("parseMExpr"); + ret=parseExpr(); + while(currentToken->kind==TOKEN_AND||currentToken->kind==TOKEN_OR) { + switch(currentToken->kind) { + case TOKEN_AND: + parser_accept(TOKEN_AND); + PUTS("parseAnd"); + ret2 = parseExpr(); + if(ret2==NULL) return 0; + for(i=0;i<rb->tagdbheader->filecount;i++) + ret[i]=ret[i] && ret2[i]; + break; + case TOKEN_OR: + parser_accept(TOKEN_OR); + PUTS("parseOr"); + ret2 = parseExpr(); + if(ret2==NULL) return 0; + for(i=0;i<rb->tagdbheader->filecount;i++) + ret[i]=ret[i] || ret2[i]; + break; + } + } + return ret; +} |