AUSAM/source/S/expr.y
/* Yacc productions for "expr" command: */
%token A_STRING SUBSTR LENGTH INDEX NOARG
/* operators listed below in increasing precedence: */
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left SUBSTR
%left LENGTH INDEX
%%
/* a single `expression' is evaluated and printed: */
expression: expr NOARG = { printf("%s\n", $1); exit(0); }
;
expr: '(' expr ')' = { $$ = $2; }
| expr '|' expr = { $$ = binop('|', $1, $3); }
| expr '&' expr = { $$ = binop('&', $1, $3); }
| expr '+' expr = { $$ = binop('+', $1, $3); }
| expr '-' expr = { $$ = binop('-', $1, $3); }
| expr '*' expr = { $$ = binop('*', $1, $3); }
| expr '/' expr = { $$ = binop('/', $1, $3); }
| expr '%' expr = { $$ = binop('%', $1, $3); }
| SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
| LENGTH expr = { $$ = length($2); }
| INDEX expr expr = { $$ = index($2, $3); }
| A_STRING
;
%%
/* expression command - 1.2 of 6/6/76 */
char **av;
int ac;
char tmp[100][6];
int tmpi;
int argi;
int yyline 0;
main(argc, argv) char **argv; {
ac = argc;
argi = 1;
av = argv;
yyinit();
yyparse();
}
yylex() {
register char *p;
if(argi >= ac) return NOARG;
p = av[argi++];
switch(*p) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '(':
case ')':
if(*(p+1) == '\0') return *p;
}
if(eq(p, "substr")) return SUBSTR;
if(eq(p, "length")) return LENGTH;
if(eq(p, "index")) return INDEX;
yylval = p;
return A_STRING;
}
binop(op, r1, r2) char op, *r1, *r2; {
register i1, i2;
i1 = atoi(r1);
i2 = atoi(r2);
switch(op) {
case '+': i1 = i1 + i2; break;
case '-': i1 = i1 - i2; break;
case '*': i1 = i1 * i2; break;
case '/': i1 = i1 / i2; break;
case '%': i1 = i1 % i2; break;
case '&': i1 = i1 & i2; break;
case '|': i1 = i1 | i2; break;
}
copy(itoa(i1), tmp[tmpi]);
return tmp[tmpi++];
}
substr(v, s, w) char *v, *s, *w; {
register si, wi;
register char *res;
si = atoi(s);
wi = atoi(w);
while(--si) if(*v) ++v;
res = v;
while(wi--) if(*v) ++v;
*v = '\0';
return res;
}
length(s) register char *s; {
register i 0;
while(*s++) ++i;
copy(itoa(i), tmp[tmpi]);
return tmp[tmpi++];
}
index(s, t) char *s, *t; {
register i, j;
for(i = 0; s[i] ; ++i)
for(j = 0; t[j] ; ++j)
if(s[i]==t[j]) {
copy(itoa(++i), tmp[tmpi]);
return tmp[tmpi++];
}
return "0";
}
eq(a, b)
char *a, *b;
{
register int i;
i = 0;
l:
if(a[i] != b[i])
return(0);
if(a[i++] == '\0')
return(1);
goto l;
}
atoi(s) register char *s; {
register i 0, neg 0;
if(*s == '-') {
++neg;
++s;
}
while(*s) {
if(*s < '0' || *s > '9') {
write(2, "non-numeric argument\n", 21);
putchar('\n');
exit(1);
}
i = i * 10 + (*s - '0');
++s;
}
return neg? -i: i;
}
itoa(n) register n; {
register char *cp;
static char *str[10];
register neg = 0;
if(n < 0) {
neg++;
n= -n;
}
for(cp = &str[8]; ;--cp) {
*cp = n % 10 + '0';
n = n / 10;
if (n == 0) {
if(neg)
*--cp = '-';
return cp;
}
}
}
copy(source, sink) register char *source, *sink; {
while(*sink++ = *source++);
}