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