1 %{
2 /* Copyright (c) 1982 Regents of the University of California */
3 
4 static char sccsid[] = "@(#)grammar.y 1.2 01/20/82";
5 
6 /*
7  * yacc grammar for debugger commands
8  */
9 
10 #include "defs.h"
11 #include "command.h"
12 #include "sym.h"
13 #include "symtab.h"
14 #include "tree.h"
15 #include "process.h"
16 #include "source.h"
17 
18 %}
19 
20 %term ALIAS ASSIGN CALL CHFILE
21 %term CONT DUMP EDIT
22 %term GRIPE HELP LIST NEXT
23 %term QUIT REMAKE PRINT
24 %term RUN SH SOURCE
25 %term STATUS STEP
26 %term STOP STOPI TRACE TRACEI
27 %term DELETE
28 %term WHATIS WHICH WHERE
29 %term XI XD
30 
31 %term AT IN IF
32 %term FILENAME
33 %term INT REAL NAME STRING
34 %term DIV MOD
35 %term AND OR NOT
36 
37 %binary '<' '=' '>' IN
38 %left '+' '-' OR '|'
39 %left UNARYSIGN
40 %left '*' '/' DIV MOD AND '&'
41 %left NOT
42 
43 %union {
44 	SYM *y_sym;
45 	NODE *y_node;
46 	int y_int;
47 	OP y_op;
48 	long y_long;
49 	double y_real;
50 	char *y_string;
51 	BOOLEAN y_bool;
52 };
53 
54 %type <y_int> trace TRACE TRACEI stop STOP STOPI
55 %type <y_long> INT
56 %type <y_real> REAL
57 %type <y_op> addop mulop relop
58 %type <y_string> STRING FILENAME SH opt_filename
59 %type <y_sym> NAME
60 %type <y_node> command rcommand what where opt_arglist opt_cond
61 %type <y_node> exp_list exp boolean_exp term constant
62 %type <y_node> line_list line_number address_list
63 %%
64 input:
65 	input command_nl
66 {
67 		prompt();
68 }
69 |	/* empty */
70 ;
71 command_nl:
72 	command_line '\n'
73 |	'\n'
74 ;
75 
76 /*
77  * There are two kinds of commands, those that can be redirected
78  * and those that can't.
79  */
80 
81 command_line:
82 	command
83 {
84 		eval($1);
85 }
86 |	rcommand
87 {
88 		eval($1);
89 }
90 |	rcommand '>' FILENAME
91 {
92 		setout($3);
93 		eval($1);
94 		unsetout();
95 }
96 |	SH
97 {
98 		shell($1);
99 }
100 |	run args
101 {
102 		run();
103 }
104 ;
105 run:
106 	RUN
107 {
108 		arginit();
109 }
110 ;
111 args:
112 	arg args
113 |	/* empty */
114 ;
115 arg:
116 	FILENAME
117 {
118 		newarg($1);
119 }
120 |	'<' FILENAME
121 {
122 		inarg($2);
123 }
124 |	'>' FILENAME
125 {
126 		outarg($2);
127 }
128 ;
129 command:
130 	ASSIGN term exp
131 {
132 		$$ = build(O_ASSIGN, $2, $3);
133 }
134 |	CHFILE opt_filename
135 {
136 		$$ = build(O_CHFILE, $2);
137 }
138 |	CONT
139 {
140 		$$ = build(O_CONT);
141 }
142 |	LIST line_list
143 {
144 		$$ = build(O_LIST, $2);
145 }
146 |	LIST NAME
147 {
148 		$$ = build(O_LIST, build(O_NAME, $2));
149 }
150 |	NEXT
151 {
152 		$$ = build(O_NEXT);
153 }
154 |	PRINT exp_list
155 {
156 		$$ = build(O_PRINT, $2);
157 }
158 |	QUIT
159 {
160 		quit(0);
161 }
162 |	STEP
163 {
164 		$$ = build(O_STEP);
165 }
166 |	stop where opt_cond
167 {
168 		$$ = build($1, NIL, $2, $3);
169 }
170 |	stop what opt_cond
171 {
172 		$$ = build($1, $2, NIL, $3);
173 }
174 |	stop IF boolean_exp
175 {
176 		$$ = build($1, NIL, NIL, $3);
177 }
178 |	trace what where opt_cond
179 {
180 		$$ = build($1, $2, $3, $4);
181 }
182 |	trace where opt_cond
183 {
184 		$$ = build($1, NIL, $2, $3);
185 }
186 |	trace what opt_cond
187 {
188 		$$ = build($1, $2, NIL, $3);
189 }
190 |	trace opt_cond
191 {
192 		$$ = build($1, NIL, NIL, $2);
193 }
194 |	DELETE INT
195 {
196 		$$ = build(O_DELETE, $2);
197 }
198 |	WHATIS term
199 {
200 		$$ = build(O_WHATIS, $2);
201 }
202 |	WHICH NAME
203 {
204 		$$ = build(O_WHICH, $2);
205 }
206 |	WHERE
207 {
208 		$$ = build(O_WHERE);
209 }
210 |	XI address_list
211 {
212 		$$ = build(O_XI, $2);
213 }
214 |	XD address_list
215 {
216 		$$ = build(O_XD, $2);
217 }
218 ;
219 rcommand:
220 	ALIAS FILENAME opt_filename
221 {
222 		$$ = build(O_ALIAS, $2, $3);
223 }
224 |	ALIAS
225 {
226 		$$ = build(O_ALIAS, NIL, NIL);
227 }
228 |	CALL term opt_arglist
229 {
230 		$$ = build(O_CALL, $2, $3);
231 }
232 |	EDIT opt_filename
233 {
234 		$$ = build(O_EDIT, $2);
235 }
236 |	DUMP
237 {
238 		$$ = build(O_DUMP);
239 }
240 |	GRIPE
241 {
242 		$$ = build(O_GRIPE);
243 }
244 |	HELP
245 {
246 		$$ = build(O_HELP);
247 }
248 |	REMAKE
249 {
250 		$$ = build(O_REMAKE);
251 }
252 |	SOURCE FILENAME
253 {
254 		$$ = build(O_SOURCE, $2);
255 }
256 |	STATUS
257 {
258 		$$ = build(O_STATUS);
259 }
260 ;
261 trace:
262 	TRACE
263 {
264 		$$ = O_TRACE;
265 }
266 |	TRACEI
267 {
268 		$$ = O_TRACEI;
269 }
270 ;
271 stop:
272 	STOP
273 {
274 		$$ = O_STOP;
275 }
276 |	STOPI
277 {
278 		$$ = O_STOPI;
279 }
280 ;
281 what:
282 	exp
283 |	FILENAME line_number
284 {
285 		$$ = build(O_QLINE, $1, $2);
286 }
287 ;
288 where:
289 	IN term
290 {
291 		$$ = $2;
292 }
293 |	AT line_number
294 {
295 		$$ = build(O_QLINE, cursource, $2);
296 }
297 |	AT FILENAME line_number
298 {
299 		$$ = build(O_QLINE, $2, $3);
300 }
301 ;
302 opt_filename:
303 	/* empty */
304 {
305 		$$ = NIL;
306 }
307 |	FILENAME
308 ;
309 opt_arglist:
310 	/* empty */
311 {
312 		$$ = NIL;
313 }
314 |	'(' exp_list ')'
315 {
316 		$$ = $2;
317 }
318 ;
319 line_list:
320 	/* empty */
321 {
322 		NODE *first, *last;
323 
324 		first = build(O_LCON, (long) 1);
325 		last = build(O_LCON, (long) lastlinenum);
326 		$$ = build(O_COMMA, first, last);
327 }
328 |	line_number
329 {
330 		$$ = build(O_COMMA, $1, $1);
331 }
332 |	line_number ',' line_number
333 {
334 		$$ = build(O_COMMA, $1, $3);
335 }
336 ;
337 line_number:
338 	INT
339 {
340 		$$ = build(O_LCON, $1);
341 }
342 |	'$'
343 {
344 		$$ = build(O_LCON, (long) lastlinenum);
345 }
346 ;
347 address_list:
348 	exp
349 {
350 		$$ = build(O_COMMA, $1, $1);
351 }
352 |	exp ',' exp
353 {
354 		$$ = build(O_COMMA, $1, $3);
355 }
356 ;
357 opt_cond:
358 	/* empty */
359 {
360 		$$ = NIL;
361 }
362 |	IF boolean_exp
363 {
364 		$$ = $2;
365 }
366 ;
367 exp_list:
368 	exp
369 {
370 		$$ = build(O_COMMA, $1, NIL);
371 }
372 |	exp ',' exp_list
373 {
374 		$$ = build(O_COMMA, $1, $3);
375 }
376 ;
377 exp:
378 	term
379 {
380 		$$ = build(O_RVAL, $1);
381 }
382 |	term '(' exp_list ')'
383 {
384 		$$ = build(O_CALL, $1, $3);
385 }
386 |	constant
387 |	'+' exp %prec UNARYSIGN
388 {
389 		$$ = $2;
390 }
391 |	'-' exp %prec UNARYSIGN
392 {
393 		$$ = build(O_NEG, $2);
394 }
395 |	exp addop exp %prec '+'
396 {
397 		$$ = build($2, $1, $3);
398 }
399 |	exp mulop exp %prec '*'
400 {
401 		$$ = build($2, $1, $3);
402 }
403 |	exp relop exp %prec '<'
404 {
405 		$$ = build($2, $1, $3);
406 }
407 |	'(' exp ')'
408 {
409 		$$ = $2;
410 }
411 ;
412 boolean_exp:
413 	exp
414 {
415 		chkboolean($$ = $1);
416 }
417 ;
418 term:
419 	NAME
420 {
421 		$$ = build(O_NAME, $1);
422 }
423 |	AT
424 {
425 		SYM *s;
426 
427 		s = st_lookup(symtab, "at");
428 		if (s == NIL) {
429 			error("\"at\" is not defined");
430 		}
431 		$$ = build(O_NAME, s);
432 }
433 |	term '[' exp_list ']'
434 {
435 		$$ = subscript($1, $3);
436 }
437 |	term '.' NAME
438 {
439 		$$ = dot($1, $3);
440 }
441 |	term '^'
442 {
443 		$$ = build(O_INDIR, $1);
444 }
445 ;
446 constant:
447 	INT
448 {
449 		$$ = build(O_LCON, $1);
450 }
451 |	REAL
452 {
453 		$$ = build(O_FCON, $1);
454 }
455 |	STRING
456 {
457 		$$ = build(O_SCON, $1);
458 }
459 ;
460 addop:
461 	'+'
462 {
463 		$$ = O_ADD;
464 }
465 |	'-'
466 {
467 		$$ = O_SUB;
468 }
469 |	OR
470 {
471 		$$ = O_OR;
472 }
473 |	'|'
474 {
475 		$$ = O_OR;
476 }
477 ;
478 mulop:
479 	'*'
480 {
481 		$$ = O_MUL;
482 }
483 |	'/'
484 {
485 		$$ = O_DIVF;
486 }
487 |	DIV
488 {
489 		$$ = O_DIV;
490 }
491 |	MOD
492 {
493 		$$ = O_MOD;
494 }
495 |	AND
496 {
497 		$$ = O_AND;
498 }
499 |	'&'
500 {
501 		$$ = O_AND;
502 }
503 ;
504 relop:
505 	'<'
506 {
507 		$$ = O_LT;
508 }
509 |	'<' '='
510 {
511 		$$ = O_LE;
512 }
513 |	'>'
514 {
515 		$$ = O_GT;
516 }
517 |	'>' '='
518 {
519 		$$ = O_GE;
520 }
521 |	'='
522 {
523 		$$ = O_EQ;
524 }
525 |	'<' '>'
526 {
527 		$$ = O_NE;
528 }
529 ;
530 %%
531 
532 /*
533  * parser error handling
534  */
535 
536 yyerror(s)
537 char *s;
538 {
539 	if (strcmp(s, "syntax error") == 0) {
540 		error("bad command syntax");
541 	} else {
542 		error(s);
543 	}
544 }
545 
546 /*
547  * In recovering from an error we gobble input up to a newline.
548  */
549 
550 gobble()
551 {
552 	register int t;
553 
554 	if (!nlflag) {
555 		while ((t = yylex()) != '\n' && t != 0);
556 	}
557 }
558