Working toward single smart playlist/query parser

This commit is contained in:
Ron Pedde 2006-03-07 23:37:42 +00:00
parent 32add9e77c
commit 43afe26932
2 changed files with 64 additions and 69 deletions

View File

@ -5,13 +5,11 @@
#include <stdio.h> #include <stdio.h>
#include "conf.h" #include "conf.h"
#include "err.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int err; int err;
err_debuglevel = 9;
printf("Reading %s\n",argv[1]); printf("Reading %s\n",argv[1]);
if((err=conf_read(argv[1])) != CONF_E_SUCCESS) { if((err=conf_read(argv[1])) != CONF_E_SUCCESS) {

View File

@ -184,7 +184,35 @@ typedef struct tag_fieldlookup {
char *name; char *name;
} FIELDLOOKUP; } FIELDLOOKUP;
FIELDLOOKUP sp_fields[] = { /* normal terminators, in-string terminators, escapes */
char *sp_terminators[2][3] = {
{ " \t\n\r\"<>=()|&!", "\"","\"" },
{ "()'+: -,", "')", "\\*'" }
};
FIELDLOOKUP sp_symbols_0[] = {
{ T_OR, "||" },
{ T_AND, "&&" },
{ T_EQUAL, "=" },
{ T_LESSEQUAL, "<=" },
{ T_LESS, "<" },
{ T_GREATEREQUAL, ">=" },
{ T_GREATER, ">" },
{ T_OPENPAREN, "(" },
{ T_CLOSEPAREN, ")" },
{ T_NOT, "!" },
{ 0, NULL }
};
FIELDLOOKUP sp_symbols_1[] = {
{ 0, NULL }
};
FIELDLOOKUP *sp_symbols[2] = {
sp_symbols_0, sp_symbols_1
};
FIELDLOOKUP sp_fields_0[] = {
{ T_INT_FIELD, "id" }, { T_INT_FIELD, "id" },
{ T_STRING_FIELD, "path" }, { T_STRING_FIELD, "path" },
{ T_STRING_FIELD, "fname" }, { T_STRING_FIELD, "fname" },
@ -245,11 +273,20 @@ FIELDLOOKUP sp_fields[] = {
{ T_ENDSWITH, "endswith" }, { T_ENDSWITH, "endswith" },
/* end */ /* end */
{ 0, NULL }, { 0, NULL }
};
FIELDLOOKUP sp_fields_1[] = {
{ 0, NULL }
};
FIELDLOOKUP *sp_fields[2] = {
sp_fields_0, sp_fields_1
}; };
typedef struct tag_parsetree { typedef struct tag_parsetree {
int in_string; int in_string;
int token_list;
char *term; char *term;
char *current; char *current;
SP_TOKEN token; SP_TOKEN token;
@ -371,11 +408,12 @@ int sp_scan(PARSETREE tree) {
char *terminator=NULL; char *terminator=NULL;
char *tail; char *tail;
int advance=0; int advance=0;
FIELDLOOKUP *pfield=sp_fields; FIELDLOOKUP *pfield=sp_fields[tree->token_list];
int len; int len;
int found; int found;
int numval; int numval;
time_t tval; time_t tval;
int found_symbol;
if(tree->token.token_id & 0x2000) { if(tree->token.token_id & 0x2000) {
if(tree->token.data.cvalue) if(tree->token.data.cvalue)
@ -404,84 +442,40 @@ int sp_scan(PARSETREE tree) {
tree->token_pos, *(tree->current)); tree->token_pos, *(tree->current));
/* check singletons */ /* check singletons */
found_symbol=0;
if(!tree->in_string) { if(!tree->in_string) {
switch(*(tree->current)) { pfield=sp_symbols[tree->token_list];
case '|': while((pfield->name) && (!found_symbol)) {
if((*(tree->current + 1) == '|')) { if(!strncmp(pfield->name,tree->current,strlen(pfield->name))) {
advance = 2; /* that's a match */
tree->token.token_id = T_OR; tree->current += strlen(pfield->name);
tree->token.token_id = pfield->type;
found_symbol = 1;
} }
break; pfield++;
case '&':
if((*(tree->current + 1) == '&')) {
advance = 2;
tree->token.token_id = T_AND;
}
break;
case '=':
advance=1;
tree->token.token_id = T_EQUAL;
break;
case '<':
if((*(tree->current + 1)) == '=') {
advance = 2;
tree->token.token_id = T_LESSEQUAL;
} else {
advance = 1;
tree->token.token_id = T_LESS;
}
break;
case '>':
if((*(tree->current + 1)) == '=') {
advance = 2;
tree->token.token_id = T_GREATEREQUAL;
} else {
advance = 1;
tree->token.token_id = T_GREATER;
}
break;
case '(':
advance=1;
tree->token.token_id = T_OPENPAREN;
break;
case ')':
advance=1;
tree->token.token_id = T_CLOSEPAREN;
break;
case '!':
advance=1;
tree->token.token_id = T_NOT;
break;
} }
} }
if(*tree->current == '"') { if((!found_symbol) && (*tree->current == '"')) {
advance = 1; tree->current++;
tree->in_string = !tree->in_string; tree->in_string = !tree->in_string;
tree->token.token_id = T_QUOTE; tree->token.token_id = T_QUOTE;
} }
if(advance) { /* singleton */ if(!found_symbol) { /* either a keyword token or a quoted string */
tree->current += advance;
} else { /* either a keyword token or a quoted string */
DPRINTF(E_SPAM,L_PARSE,"keyword or string!\n"); DPRINTF(E_SPAM,L_PARSE,"keyword or string!\n");
/* walk to a terminator */ /* walk to a terminator */
tail = tree->current; tail = tree->current;
terminator = " \t\n\r\"<>=()|&!"; /* out-of-string terminator */
if(tree->in_string) { terminator = sp_terminators[tree->token_list][0];
terminator="\""; if(tree->in_string) { /* in-string terminator */
terminator=sp_terminators[tree->token_list][1];
} }
/* FIXME: escaped characters */
while((*tail) && (!strchr(terminator,*tail))) { while((*tail) && (!strchr(terminator,*tail))) {
tail++; tail++;
} }
@ -491,7 +485,7 @@ int sp_scan(PARSETREE tree) {
if(!tree->in_string) { if(!tree->in_string) {
/* find it in the token list */ /* find it in the token list */
pfield=sp_fields; pfield=sp_fields[tree->token_list];
DPRINTF(E_SPAM,L_PARSE,"Len is %d\n",len); DPRINTF(E_SPAM,L_PARSE,"Len is %d\n",len);
while(pfield->name) { while(pfield->name) {
if(strlen(pfield->name) == len) { if(strlen(pfield->name) == len) {
@ -567,6 +561,9 @@ PARSETREE sp_init(void) {
DPRINTF(E_FATAL,L_PARSE,"Alloc error\n"); DPRINTF(E_FATAL,L_PARSE,"Alloc error\n");
memset(ptree,0,sizeof(PARSESTRUCT)); memset(ptree,0,sizeof(PARSESTRUCT));
/* this sets the default token list as well (0) */
return ptree; return ptree;
} }