Subversion Repositories planix.SVN

Rev

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

/* Yacc productions for "expr" command: */

%token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
%token A_STRING SUBSTR LENGTH INDEX NOARG MATCH

/* operators listed below in increasing precedence: */
%left OR
%left AND
%left EQ LT GT GEQ LEQ NEQ
%left ADD SUBT
%left MULT DIV REM
%left MCH
%left MATCH
%left SUBSTR
%left LENGTH INDEX

%{
#define YYSTYPE charp

typedef char *charp;
%}

%%

/* a single `expression' is evaluated and printed: */

expression:     expr NOARG = {
                        prt(1, $1);
                        exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
                        }
        ;


expr:   '(' expr ')' = { $$ = $2; }
        | expr OR expr   = { $$ = conj(OR, $1, $3); }
        | expr AND expr   = { $$ = conj(AND, $1, $3); }
        | expr EQ expr   = { $$ = rel(EQ, $1, $3); }
        | expr GT expr   = { $$ = rel(GT, $1, $3); }
        | expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
        | expr LT expr   = { $$ = rel(LT, $1, $3); }
        | expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
        | expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
        | expr ADD expr   = { $$ = arith(ADD, $1, $3); }
        | expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
        | expr MULT expr   = { $$ = arith(MULT, $1, $3); }
        | expr DIV expr   = { $$ = arith(DIV, $1, $3); }
        | expr REM expr   = { $$ = arith(REM, $1, $3); }
        | expr MCH expr  = { $$ = match($1, $3); }
        | MATCH expr expr = { $$ = match($2, $3); }
        | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
        | LENGTH expr       = { $$ = length($2); }
        | INDEX expr expr = { $$ = index($2, $3); }
        | A_STRING
        ;
%%
/*      expression command */
#include <stdio.h>
/* get rid of yacc debug printf's */
#define printf
#define ESIZE   512
#define error(c)        errxx(c)
#define EQL(x,y) !strcmp(x,y)
long atol();
char *ltoa();
char    **Av;
int     Ac;
int     Argi;

char Mstring[1][128];
char *malloc();
extern int nbra;
int yyparse(void);

main(argc, argv) char **argv; {
        Ac = argc;
        Argi = 1;
        Av = argv;
        yyparse();
}

char *operator[] = { "|", "&", "+", "-", "*", "/", "%", ":",
        "=", "==", "<", "<=", ">", ">=", "!=",
        "match", "substr", "length", "index", "\0" };
int op[] = { OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
        EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
        MATCH, SUBSTR, LENGTH, INDEX };
yylex() {
        register char *p;
        register i;

        if(Argi >= Ac) return NOARG;

        p = Av[Argi++];

        if(*p == '(' || *p == ')')
                return (int)*p;
        for(i = 0; *operator[i]; ++i)
                if(EQL(operator[i], p))
                        return op[i];

        yylval = p;
        return A_STRING;
}

char *rel(op, r1, r2) register char *r1, *r2; {
        register i;

        if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
                i = atol(r1) - atol(r2);
        else
                i = strcmp(r1, r2);
        switch(op) {
        case EQ: i = i==0; break;
        case GT: i = i>0; break;
        case GEQ: i = i>=0; break;
        case LT: i = i<0; break;
        case LEQ: i = i<=0; break;
        case NEQ: i = i!=0; break;
        }
        return i? "1": "0";
}

char *arith(op, r1, r2) char *r1, *r2; {
        long i1, i2;
        register char *rv;

        if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
                yyerror("non-numeric argument");
        i1 = atol(r1);
        i2 = atol(r2);

        switch(op) {
        case ADD: i1 = i1 + i2; break;
        case SUBT: i1 = i1 - i2; break;
        case MULT: i1 = i1 * i2; break;
        case DIV: i1 = i1 / i2; break;
        case REM: i1 = i1 % i2; break;
        }
        rv = malloc(16);
        strcpy(rv, ltoa(i1));
        return rv;
}
char *conj(op, r1, r2) char *r1, *r2; {
        register char *rv;

        switch(op) {

        case OR:
                if(EQL(r1, "0")
                || EQL(r1, ""))
                        if(EQL(r2, "0")
                        || EQL(r2, ""))
                                rv = "0";
                        else
                                rv = r2;
                else
                        rv = r1;
                break;
        case AND:
                if(EQL(r1, "0")
                || EQL(r1, ""))
                        rv = "0";
                else if(EQL(r2, "0")
                || EQL(r2, ""))
                        rv = "0";
                else
                        rv = r1;
                break;
        }
        return rv;
}

char *substr(v, s, w) char *v, *s, *w; {
register si, wi;
register char *res;

        si = atol(s);
        wi = atol(w);
        while(--si) if(*v) ++v;

        res = v;

        while(wi--) if(*v) ++v;

        *v = '\0';
        return res;
}

char *length(s) register char *s; {
        register i = 0;
        register char *rv;

        while(*s++) ++i;

        rv = malloc(8);
        strcpy(rv, ltoa((long)i));
        return rv;
}

char *index(s, t) char *s, *t; {
        register i, j;
        register char *rv;

        for(i = 0; s[i] ; ++i)
                for(j = 0; t[j] ; ++j)
                        if(s[i]==t[j]) {
                                strcpy(rv=malloc(8), ltoa((long)++i));
                                return rv;
                        }
        return "0";
}

char *match(s, p)
{
        register char *rv;

        strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
        if(nbra) {
                rv = malloc(strlen(Mstring[0])+1);
                strcpy(rv, Mstring[0]);
        }
        return rv;
}

#define INIT    register char *sp = instring;
#define GETC()          (*sp++)
#define PEEKC()         (*sp)
#define UNGETC(c)       (--sp)
#define RETURN(c)       return
#define ERROR(c)        errxx(c)


ematch(s, p)
char *s;
register char *p;
{
        static char expbuf[ESIZE];
        char *compile();
        register num;
        extern char *braslist[], *braelist[], *loc2;

        compile(p, expbuf, &expbuf[ESIZE], 0);
        if(nbra > 1)
                yyerror("Too many '\\('s");
        if(advance(s, expbuf)) {
                if(nbra == 1) {
                        p = braslist[0];
                        num = braelist[0] - p;
                        strncpy(Mstring[0], p, num);
                        Mstring[0][num] = '\0';
                }
                return(loc2-s);
        }
        return(0);
}

errxx(c)
{
        yyerror("RE error");
}

#include  "regexp.h"
yyerror(s)

{
        write(2, "expr: ", 6);
        prt(2, s);
        exit(2);
}
prt(fd, s)
char *s;
{
        write(fd, s, strlen(s));
        write(fd, "\n", 1);
}
char *ltoa(l)
long l;
{
        static char str[20];
        register char *sp = &str[18];
        register i;
        register neg = 0;

        if(l < 0)
                ++neg, l *= -1;
        str[19] = '\0';
        do {
                i = l % 10;
                *sp-- = '0' + i;
                l /= 10;
        } while(l);
        if(neg)
                *sp-- = '-';
        return ++sp;
}