xref: /plan9/sys/src/ape/cmd/expr/expr.y (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /* Yacc productions for "expr" command: */
2 
3 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
4 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
5 
6 /* operators listed below in increasing precedence: */
7 %left OR
8 %left AND
9 %left EQ LT GT GEQ LEQ NEQ
10 %left ADD SUBT
11 %left MULT DIV REM
12 %left MCH
13 %left MATCH
14 %left SUBSTR
15 %left LENGTH INDEX
16 
17 %{
18 #define YYSTYPE charp
19 
20 typedef char *charp;
21 %}
22 
23 %%
24 
25 /* a single `expression' is evaluated and printed: */
26 
27 expression:	expr NOARG = {
28 			prt(1, $1);
29 			exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
30 			}
31 	;
32 
33 
34 expr:	'(' expr ')' = { $$ = $2; }
35 	| expr OR expr   = { $$ = conj(OR, $1, $3); }
36 	| expr AND expr   = { $$ = conj(AND, $1, $3); }
37 	| expr EQ expr   = { $$ = rel(EQ, $1, $3); }
38 	| expr GT expr   = { $$ = rel(GT, $1, $3); }
39 	| expr GEQ expr   = { $$ = rel(GEQ, $1, $3); }
40 	| expr LT expr   = { $$ = rel(LT, $1, $3); }
41 	| expr LEQ expr   = { $$ = rel(LEQ, $1, $3); }
42 	| expr NEQ expr   = { $$ = rel(NEQ, $1, $3); }
43 	| expr ADD expr   = { $$ = arith(ADD, $1, $3); }
44 	| expr SUBT expr   = { $$ = arith(SUBT, $1, $3); }
45 	| expr MULT expr   = { $$ = arith(MULT, $1, $3); }
46 	| expr DIV expr   = { $$ = arith(DIV, $1, $3); }
47 	| expr REM expr   = { $$ = arith(REM, $1, $3); }
48 	| expr MCH expr	 = { $$ = match($1, $3); }
49 	| MATCH expr expr = { $$ = match($2, $3); }
50 	| SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
51 	| LENGTH expr       = { $$ = length($2); }
52 	| INDEX expr expr = { $$ = index($2, $3); }
53 	| A_STRING
54 	;
55 %%
56 /*	expression command */
57 #include <stdio.h>
58 /* get rid of yacc debug printf's */
59 #define printf
60 #define ESIZE	512
61 #define error(c)	errxx(c)
62 #define EQL(x,y) !strcmp(x,y)
63 long atol();
64 char *ltoa();
65 char	**Av;
66 int	Ac;
67 int	Argi;
68 
69 char Mstring[1][128];
70 char *malloc();
71 extern int nbra;
72 int yyparse(void);
73 
main(argc,argv)74 main(argc, argv) char **argv; {
75 	Ac = argc;
76 	Argi = 1;
77 	Av = argv;
78 	yyparse();
79 }
80 
81 char *operator[] = { "|", "&", "+", "-", "*", "/", "%", ":",
82 	"=", "==", "<", "<=", ">", ">=", "!=",
83 	"match", "substr", "length", "index", "\0" };
84 int op[] = { OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
85 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
86 	MATCH, SUBSTR, LENGTH, INDEX };
yylex()87 yylex() {
88 	register char *p;
89 	register i;
90 
91 	if(Argi >= Ac) return NOARG;
92 
93 	p = Av[Argi++];
94 
95 	if(*p == '(' || *p == ')')
96 		return (int)*p;
97 	for(i = 0; *operator[i]; ++i)
98 		if(EQL(operator[i], p))
99 			return op[i];
100 
101 	yylval = p;
102 	return A_STRING;
103 }
104 
rel(op,r1,r2)105 char *rel(op, r1, r2) register char *r1, *r2; {
106 	register i;
107 
108 	if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
109 		i = atol(r1) - atol(r2);
110 	else
111 		i = strcmp(r1, r2);
112 	switch(op) {
113 	case EQ: i = i==0; break;
114 	case GT: i = i>0; break;
115 	case GEQ: i = i>=0; break;
116 	case LT: i = i<0; break;
117 	case LEQ: i = i<=0; break;
118 	case NEQ: i = i!=0; break;
119 	}
120 	return i? "1": "0";
121 }
122 
arith(op,r1,r2)123 char *arith(op, r1, r2) char *r1, *r2; {
124 	long i1, i2;
125 	register char *rv;
126 
127 	if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
128 		yyerror("non-numeric argument");
129 	i1 = atol(r1);
130 	i2 = atol(r2);
131 
132 	switch(op) {
133 	case ADD: i1 = i1 + i2; break;
134 	case SUBT: i1 = i1 - i2; break;
135 	case MULT: i1 = i1 * i2; break;
136 	case DIV: i1 = i1 / i2; break;
137 	case REM: i1 = i1 % i2; break;
138 	}
139 	rv = malloc(16);
140 	strcpy(rv, ltoa(i1));
141 	return rv;
142 }
conj(op,r1,r2)143 char *conj(op, r1, r2) char *r1, *r2; {
144 	register char *rv;
145 
146 	switch(op) {
147 
148 	case OR:
149 		if(EQL(r1, "0")
150 		|| EQL(r1, ""))
151 			if(EQL(r2, "0")
152 			|| EQL(r2, ""))
153 				rv = "0";
154 			else
155 				rv = r2;
156 		else
157 			rv = r1;
158 		break;
159 	case AND:
160 		if(EQL(r1, "0")
161 		|| EQL(r1, ""))
162 			rv = "0";
163 		else if(EQL(r2, "0")
164 		|| EQL(r2, ""))
165 			rv = "0";
166 		else
167 			rv = r1;
168 		break;
169 	}
170 	return rv;
171 }
172 
substr(v,s,w)173 char *substr(v, s, w) char *v, *s, *w; {
174 register si, wi;
175 register char *res;
176 
177 	si = atol(s);
178 	wi = atol(w);
179 	while(--si) if(*v) ++v;
180 
181 	res = v;
182 
183 	while(wi--) if(*v) ++v;
184 
185 	*v = '\0';
186 	return res;
187 }
188 
length(s)189 char *length(s) register char *s; {
190 	register i = 0;
191 	register char *rv;
192 
193 	while(*s++) ++i;
194 
195 	rv = malloc(8);
196 	strcpy(rv, ltoa((long)i));
197 	return rv;
198 }
199 
index(s,t)200 char *index(s, t) char *s, *t; {
201 	register i, j;
202 	register char *rv;
203 
204 	for(i = 0; s[i] ; ++i)
205 		for(j = 0; t[j] ; ++j)
206 			if(s[i]==t[j]) {
207 				strcpy(rv=malloc(8), ltoa((long)++i));
208 				return rv;
209 			}
210 	return "0";
211 }
212 
match(s,p)213 char *match(s, p)
214 {
215 	register char *rv;
216 
217 	strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
218 	if(nbra) {
219 		rv = malloc(strlen(Mstring[0])+1);
220 		strcpy(rv, Mstring[0]);
221 	}
222 	return rv;
223 }
224 
225 #define INIT	register char *sp = instring;
226 #define GETC()		(*sp++)
227 #define PEEKC()		(*sp)
228 #define UNGETC(c)	(--sp)
229 #define RETURN(c)	return
230 #define ERROR(c)	errxx(c)
231 
232 
ematch(s,p)233 ematch(s, p)
234 char *s;
235 register char *p;
236 {
237 	static char expbuf[ESIZE];
238 	char *compile();
239 	register num;
240 	extern char *braslist[], *braelist[], *loc2;
241 
242 	compile(p, expbuf, &expbuf[ESIZE], 0);
243 	if(nbra > 1)
244 		yyerror("Too many '\\('s");
245 	if(advance(s, expbuf)) {
246 		if(nbra == 1) {
247 			p = braslist[0];
248 			num = braelist[0] - p;
249 			strncpy(Mstring[0], p, num);
250 			Mstring[0][num] = '\0';
251 		}
252 		return(loc2-s);
253 	}
254 	return(0);
255 }
256 
errxx(c)257 errxx(c)
258 {
259 	yyerror("RE error");
260 }
261 
262 #include  "regexp.h"
yyerror(s)263 yyerror(s)
264 
265 {
266 	write(2, "expr: ", 6);
267 	prt(2, s);
268 	exit(2);
269 }
prt(fd,s)270 prt(fd, s)
271 char *s;
272 {
273 	write(fd, s, strlen(s));
274 	write(fd, "\n", 1);
275 }
ltoa(l)276 char *ltoa(l)
277 long l;
278 {
279 	static char str[20];
280 	register char *sp = &str[18];
281 	register i;
282 	register neg = 0;
283 
284 	if(l < 0)
285 		++neg, l *= -1;
286 	str[19] = '\0';
287 	do {
288 		i = l % 10;
289 		*sp-- = '0' + i;
290 		l /= 10;
291 	} while(l);
292 	if(neg)
293 		*sp-- = '-';
294 	return ++sp;
295 }
296