summaryrefslogtreecommitdiff
path: root/apps/plugins/searchengine/parser.c
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-04-28 12:33:38 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-04-28 12:33:38 +0000
commit9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8 (patch)
tree0276c6299a3b26705b028f399ceadf3ac7867b2f /apps/plugins/searchengine/parser.c
parenta7f7781dca4db172a507e7e6f73bee03fc7deb2f (diff)
downloadrockbox-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.c240
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;
+}