Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

%{
#include <u.h>
#include <libc.h>
#include <ctype.h>
#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");
}