rockbox/apps/plugins/databox/editparser.c
Michiel Van Der Kolk f5eae08361 Starts with and ends with support (for strings), as requested.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6454 a1c6a512-1295-4272-9138-f99709370657
2005-05-10 23:44:22 +00:00

205 lines
5.7 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Michiel van der Kolk
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "databox.h"
#include "edittoken.h"
#include "editparser.h"
struct token *currenttoken,*lasttoken,*tokenstream;
int currentindex;
int lparencount,acceptedmask;
int tokensleft;
int invalid;
int invalid_mode;
void check_accepted(struct token *tstream, int count) {
parse_stream(tstream,count+1,INVALID_EXPERT);
}
void parse_stream(struct token *tstream, int count, int inv_mode) {
invalid_mode=inv_mode;
acceptedmask=0;
lparencount=0;
tokensleft=count;
currentindex=0;
invalid=0;
tokenstream=tstream;
currenttoken=&tokenstream[currentindex];
parseMExpr();
}
int check_tokenstream(struct token *tstream, int inv_mode) {
int inval=0;
int i;
parse_stream(tstream,-1,inv_mode);
inval=invalid;
while( (inv_mode==INVALID_STRIP||inv_mode==INVALID_MARK) && invalid)
parse_stream(tstream,-1,inv_mode);
i=0;
while(tstream[i].kind!=TOKEN_EOF)
if(tstream[i++].kind==TOKEN_INVALID) {
inval=1;
break;
}
return inval==0;
}
void parse_accept_rparen(void) {
if(!tokensleft) return;
if(lparencount) {
acceptedmask|=ACCEPT_RPAREN;
}
}
void parse_accept(int bitmask) {
if(!tokensleft) return;
acceptedmask|=bitmask;
if(lparencount) {
acceptedmask&=~ACCEPT_EOF;
}
}
void parse_checktoken() {
int ok=0;
if(!tokensleft) return;
lasttoken=currenttoken;
switch(lasttoken->kind) {
case TOKEN_EOF:
ok=acceptedmask&ACCEPT_EOF;
break;
case TOKEN_NOT:
ok=acceptedmask&ACCEPT_NOT;
break;
case TOKEN_AND:
case TOKEN_OR:
ok=acceptedmask&ACCEPT_BOOLOP;
break;
case TOKEN_GT:
case TOKEN_GTE:
case TOKEN_LT:
case TOKEN_LTE:
case TOKEN_NE:
case TOKEN_EQ:
ok=acceptedmask&ACCEPT_NUMOP;
break;
case TOKEN_EQUALS:
case TOKEN_CONTAINS:
case TOKEN_STARTSWITH:
case TOKEN_ENDSWITH:
ok=acceptedmask&ACCEPT_STROP;
break;
case TOKEN_STRING:
case TOKEN_STRINGIDENTIFIER:
ok=acceptedmask&ACCEPT_STRARG;
break;
case TOKEN_NUM:
case TOKEN_NUMIDENTIFIER:
ok=acceptedmask&ACCEPT_NUMARG;
break;
case TOKEN_LPAREN:
ok=acceptedmask&ACCEPT_LPAREN;
if(ok) lparencount++;
break;
case TOKEN_RPAREN:
ok=acceptedmask&ACCEPT_RPAREN;
if(ok) lparencount--;
break;
case TOKEN_INVALID:
if(invalid_mode!=INVALID_STRIP)
ok=1;
break;
}
tokensleft--;
if(lasttoken->kind==TOKEN_EOF)
tokensleft=0;
if(!ok&&tokensleft) {
// delete token
int i=currentindex;
//printf("Syntax error. accepted: 0x%x index:%d token: %d %s\n",acceptedmask,currentindex,currenttoken->kind,tokentostring(currenttoken));
switch (invalid_mode) {
case INVALID_STRIP:
do {
rb->memcpy(currenttoken,&tokenstream[++i],sizeof(struct token));;
currenttoken=&tokenstream[i];
} while (currenttoken->kind!=TOKEN_EOF);
currenttoken=&tokenstream[currentindex];
break;
case INVALID_MARK:
currenttoken->kind=TOKEN_INVALID;
break;
}
tokensleft=0;
invalid=1;
}
if(tokensleft) {
currenttoken=&tokenstream[++currentindex];
acceptedmask=0;
}
}
void parseCompareNum() {
parse_accept(ACCEPT_NUMOP);
parse_checktoken();
parse_accept(ACCEPT_NUMARG);
parse_checktoken();
}
void parseCompareString() {
parse_accept(ACCEPT_STROP);
parse_checktoken();
parse_accept(ACCEPT_STRARG);
parse_checktoken();
}
void parseExpr() {
if(!tokensleft) return;
parse_accept(ACCEPT_NOT|ACCEPT_LPAREN|ACCEPT_NUMARG|ACCEPT_STRARG);
parse_checktoken();
switch(lasttoken->kind) {
case TOKEN_NOT:
parseExpr();
break;
case TOKEN_LPAREN:
parseMExpr();
break;
case TOKEN_NUM:
case TOKEN_NUMIDENTIFIER:
parseCompareNum();
break;
case TOKEN_STRING:
case TOKEN_STRINGIDENTIFIER:
parseCompareString();
break;
}
}
void parseMExpr() {
parseExpr();
parse_accept_rparen();
parse_accept(ACCEPT_BOOLOP|ACCEPT_EOF);
parse_checktoken();
while(lasttoken->kind==TOKEN_OR || lasttoken->kind == TOKEN_AND) {
parseExpr();
parse_accept_rparen();
parse_accept(ACCEPT_BOOLOP|ACCEPT_EOF);
parse_checktoken();
if(!tokensleft)
return;
}
}