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