%{ #include #include #include #include "dat.h" char *yylp; /* next character to be lex'd */ char *yybuffer; char *yyend; /* end of buffer to be parsed */ %} %term LOR %term LAND %term WORD %term NE %right '!' %left '|' %left '&' %left LOR %left LAND %start filter %% filter : expr { filter = $$; } ; expr : WORD { $$ = $1; } | WORD '=' WORD { $2->l = $1; $2->r = $3; $$ = $2; } | WORD NE WORD { $2->l = newfilter(); $2->l->op = '='; $2->l->l = $1; $2->l->r = $3; $2->op = '!'; $$ = $2; } | WORD '(' expr ')' { $1->l = $3; free($2); free($4); $$ = $1; } | '(' expr ')' { free($1); free($3); $$ = $2; } | expr LOR expr { $2->l = $1; $2->r = $3; $$ = $2; } | expr LAND expr { $2->l = $1; $2->r = $3; $$ = $2; } | '!' expr { $1->l = $2; $$ = $1; } ; %% /* * Initialize the parsing. Done once for each header field. */ void yyinit(char *p) { yylp = p; } int yylex(void) { char *p; int c; if(yylp == nil) return 0; while(isspace(*yylp)) yylp++; if(*yylp == 0) return 0; yylval = newfilter(); p = strpbrk(yylp, "!|&()= "); if(p == 0){ yylval->op = WORD; yylval->s = strdup(yylp); if(yylval->s == nil) sysfatal("parsing filter: %r"); yylp = nil; return WORD; } c = *p; if(p != yylp){ yylval->op = WORD; *p = 0; yylval->s = strdup(yylp); if(yylval->s == nil) sysfatal("parsing filter: %r"); *p = c; yylp = p; return WORD; } yylp++; if(c == '!' && *yylp == '='){ c = NE; yylp++; } else if(c == '&' && *yylp == '&'){ c = LAND; yylp++; } else if(c == '|' && *yylp == '|'){ c = LOR; yylp++; } yylval->op = c; return c; } void yyerror(char*) { sysfatal("error parsing filter"); }