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