123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /* 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;
- }
|