1: /* 2: **This file contains the specification of QUEL recognized by the parser. 3: */ 4: 5: /* COMMANDS */ 6: %term APPEND COPY CREATE DELETE DESTROY HELP INDEX MODIFY 7: %term PRINT RANGE REPLACE RETRIEVE SAVE 8: %term DEFINE PERMIT VIEW INTEGRITY 9: /*DDD*/%term DISTRIBUTE 10: 11: /* 'NOISE' WORDS */ 12: %term ALL BY FROM IN INTO UNIQUE AT 13: %term IS OF ON ONTO TO UNTIL WHERE 14: /*DDD*/%term DISTRD 15: 16: /* CONSTANTS */ 17: %term NAME SCONST I2CONST I4CONST F4CONST F8CONST 18: 19: /* PUNCTUATION */ 20: %term COMMA LPAREN PERIOD RPAREN COLON BGNCMNT ENDCMNT 21: 22: /* UNARY ARITHMETIC OPERATORS */ 23: %term UAOP 24: 25: /* BINARY ARITHMETIC OPERATORS */ 26: %term BAOP BAOPH 27: 28: /* BOUNDS OPERATORS */ 29: %term BDOP 30: 31: /* EQUALITY OPERATORS */ 32: %term EOP 33: 34: /* LOGICAL OPERATORS */ 35: %term LBOP LUOP 36: 37: /* FUNCTIONAL OPERATORS */ 38: %term FOP FBOP 39: 40: /* AGGREGATE OPERATORS */ 41: %term AGOP 42: 43: 44: /* DEFINE ASCENDING PRECEDENCE FOR OPERATORS */ 45: %left LBOP 46: %left LUOP 47: %left UAOP 48: %left BAOP 49: %left BAOPH 50: %binary unaryop 51: 52: %{ 53: /* SCANNER/PARSER GLOBALS & TABLES */ 54: # include "../ingres.h" 55: # include "../aux.h" 56: # include "../tree.h" 57: # include "../symbol.h" 58: # include "parser.h" 59: %} 60: %% 61: %{ 62: register int i; 63: register struct atstash *aptr; 64: char permbuf[3]; 65: /* space for two names, their null bytes and the seperator */ 66: char modbuf[(2 * (MAXNAME + 1)) + 1]; 67: static char hqmbuf[2]; 68: %} 69: program: xprogram 70: | 71: ; 72: xprogram: xprogram stmnt = 73: endquelst(Opflag); 74: | stmnt = 75: endquelst(Opflag); 76: ; 77: stmnt: append 78: | copy 79: | create 80: | delete 81: | destroy 82: /*DDD*/ | distribute 83: | help 84: | index 85: | integrity 86: | modify 87: | permit 88: | print 89: | range 90: | replace 91: | retrieve 92: | save 93: | view 94: ; 95: range: rngstmnt OF NAME IS NAME = 96: { 97: if ((i = openr(&Reldesc, -1, $5)) < 0) 98: syserr("relname: error in openr '%d'", i); 99: if (i > 0) 100: /* invalid relation name */ 101: yyerror(RNGEXIST, $5, 0); 102: rngent(R_EXTERNAL, $3, $5, Reldesc.relowner, Reldesc.relatts, Reldesc.relstat); 103: } 104: ; 105: rngstmnt: RANGE = 106: { 107: Opflag = mdRANGE; 108: } 109: ; 110: append: apstmnt apto relation tlclause qualclause = 111: { 112: /* make root node */ 113: Lastree = tree($4, $5, ROOT, 0, 0); 114: } 115: ; 116: apstmnt: APPEND = 117: { 118: Opflag = mdAPP; 119: } 120: ; 121: apto: INTO 122: | ONTO 123: | TO 124: | ON 125: | ; 126: ; 127: delete: delstmnt delwd relation qualclause = 128: { 129: /* make root node for delete, with a TIDNODE at leftmost */ 130: Lastree = tree(tree(NULL, Tidnode, RESDOM, 4, NULL), $4, ROOT, 0, 0); 131: } 132: ; 133: delstmnt: DELETE = 134: { 135: Opflag = mdDEL; 136: } 137: ; 138: delwd: IN 139: | ON 140: | FROM 141: | ; 142: ; 143: replace: repstmnt repkwd relation tlclause qualclause = 144: { 145: /* make root node for replace */ 146: Lastree = tree($4, $5, ROOT, 0, 0); 147: } 148: ; 149: repstmnt: REPLACE = 150: { 151: Opflag = mdREPL; 152: } 153: ; 154: repkwd: INTO 155: | IN 156: | ON 157: | ; 158: ; 159: retrieve: retstmnt retclause tlclause qualclause = 160: { 161: /* make root node for retrieve */ 162: Lastree = tree($3, $4, ROOT, 0, 0); 163: } 164: ; 165: retstmnt: RETRIEVE = 166: { 167: Opflag = mdRETR; 168: } 169: ; 170: retclause: retkwd relation = 171: { 172: /* set up pipe block and save relname for create */ 173: Rsdmno = 0; 174: setp("0"); /* relstat = nil */ 175: setp(Resrng->relnm); 176: } 177: | = 178: { 179: /* no result relation, output to terminal */ 180: Rsdmno = 0; 181: Resrng = 0; 182: } 183: | UNIQUE = 184: { 185: Opflag = mdRET_UNI; 186: Rsdmno = 0; 187: Resrng = 0; 188: } 189: ; 190: retkwd: INTO 191: | TO 192: | ; 193: ; 194: view: viewclause tlclause qualclause = 195: { 196: Lastree = tree($2, $3, ROOT, 0, 0); 197: } 198: ; 199: viewclause: viewstmnt relation = 200: { 201: Rsdmno = 0; 202: setp("0040"); /* relstat = S_VIEW */ 203: setp(Resrng->relnm); 204: } 205: ; 206: viewstmnt: DEFINE VIEW = 207: { 208: Opflag = mdVIEW; 209: if (!Qrymod) 210: /* no qrymod in database */ 211: yyerror(NOQRYMOD, 0); 212: } 213: ; 214: permit: permstmnt permlist permrel permtarg permwho permplace permtd qualclause = 215: { 216: Lastree = tree($4, $8, ROOT, 0, 0); 217: } 218: ; 219: permstmnt: DEFINE PERMIT = 220: { 221: Opflag = mdPROT; 222: if (!Qrymod) 223: /* no qrymod in database */ 224: yyerror(NOQRYMOD, 0); 225: } 226: ; 227: permlist: permxlist 228: | permlist COMMA permxlist 229: ; 230: permxlist: ALL = 231: permcom(-1); /* means 'all' commands */ 232: | RETRIEVE = 233: permcom(mdRETR); 234: | DELETE = 235: permcom(mdDEL); 236: | APPEND = 237: permcom(mdAPP); 238: | REPLACE = 239: permcom(mdREPL); 240: ; 241: permrel: permword relation = 242: { 243: /* put command vector into list now since this always happens */ 244: setp(iocv(Permcomd)); 245: Permcomd = 0; /* reset command map */ 246: setp(Resrng->relnm); 247: bmove(Resrng->relnowner, permbuf, 2); 248: permbuf[2] = 0; 249: setp(permbuf); 250: } 251: ; 252: permword: ON 253: | OF 254: | TO 255: ; 256: permtarg: LPAREN permtlist RPAREN = 257: { 258: $$ = $2; 259: } 260: | = 261: { 262: $$ = NULL; 263: } 264: ; 265: permtlist: permtlelm 266: | permtlist COMMA permtlelm = 267: { 268: /* 269: ** attach bulk of permit tl to leftmost node of new elem 270: */ 271: $$ = tlprepend($1, $3); 272: } 273: ; 274: permtlelm: NAME = 275: { 276: /* Resrng is set by the "relation" production */ 277: Trname = $1; 278: aptr = attlookup(Resrng, Trname); 279: $$ = tree(NULL, NULL, VAR, 6, Resrng->rentno, aptr); 280: $$ = addresdom(NULL, $$); 281: } 282: ; 283: permwho: TO NAME = 284: setp($2); 285: | TO ALL = 286: setp("all"); 287: ; 288: permplace: AT NAME = 289: setp($2); 290: | AT ALL = 291: setp("all"); 292: | = 293: setp("all"); /* default is all */ 294: ; 295: permtd: permtime permday 296: | permdeftime permday 297: | permtime permdefday 298: | permdeftime permdefday 299: ; 300: permdeftime: = 301: { 302: setp("0"); 303: setp("1440"); 304: } 305: ; 306: permdefday: = 307: { 308: setp("sun"); 309: setp("sat"); 310: } 311: ; 312: permtime: FROM I2CONST COLON I2CONST TO I2CONST COLON I2CONST = 313: { 314: setp(iocv(timeofday($2, $4))); 315: setp(iocv(timeofday($6, $8))); 316: } 317: ; 318: permday: ON NAME TO NAME = 319: { 320: setp($2); 321: setp($4); 322: } 323: ; 324: integrity: integstmnt integnoise relation integis qual = 325: { 326: Lastree = tree(NULL, norml($5), ROOT, 0, 0); 327: Qlflag--; /* turn off here */ 328: } 329: ; 330: integstmnt: DEFINE INTEGRITY = 331: { 332: Opflag = mdINTEG; 333: Qlflag++; /* OK to turn on here because integrity doesn't have a targ list */ 334: if (!Qrymod) 335: /* no qrymod in database */ 336: yyerror(NOQRYMOD, 0); 337: } 338: ; 339: integnoise: ON 340: | ONTO 341: | IN 342: | OF 343: | /* null */ 344: ; 345: integis: IS 346: | /* null*/ 347: ; 348: /*DDD*/distribute: diststmnt relation AT distcrits = 349: /*DDD*/ { 350: /*DDD*/ $$ = tree(NULL, NULL, QLEND, 0); 351: /*DDD*/ Lastree = tree($4, $$, ROOT, 0); 352: /*DDD*/ } 353: /*DDD*/; 354: /*DDD*/diststmnt: DISTRIBUTE = 355: /*DDD*/ Opflag = mdDISTRIB; 356: /*DDD*/; 357: /*DDD*/distcrits: dcriterion = 358: /*DDD*/ { 359: /*DDD*/ $$ = $1; 360: /*DDD*/ } 361: /*DDD*/ | distcrits dcriterion = 362: /*DDD*/ { 363: /*DDD*/ $$ = tlprepend($1, $2); 364: /*DDD*/ } 365: /*DDD*/; 366: /*DDD*/dcriterion: NAME where qual = 367: /*DDD*/ { 368: /*DDD*/ Qlflag--; 369: /*DDD*/ $$ = tree(NULL, norml($3), SITE, 2, $1); 370: /*DDD*/ } 371: /*DDD*/; 372: relation: NAME = 373: { 374: # ifdef xPTR2 375: tTfp(32, 0, "res rel name/var: '%s'\n", $1); 376: # endif 377: switch (Opflag) 378: { 379: case mdRETR: 380: case mdVIEW: 381: /* result better not be a rel name */ 382: if ((i = openr(&Reldesc, -1, $1)) < 0) 383: syserr("relation: err openr '%d'", i); 384: if (i == 0) 385: { 386: /* reln exists */ 387: if (bequal(Reldesc.relowner, Usercode, 2)) 388: { 389: /* same owner, can't duplicate name */ 390: yyerror(RESEXIST, $1, 0); 391: } 392: else 393: { 394: /* owned by dba -- purge range table */ 395: rngdel($1); 396: } 397: } 398: Resrng = rngent(R_INTERNAL, "", $1, Usercode, 0, 0); 399: break; 400: 401: case mdAPP: 402: /* result is a rel name */ 403: Resrng = rnglook($1, LOOKREL); 404: if (Resrng == 0) 405: { 406: if ((i = openr(&Reldesc, -1, $1)) < 0) 407: syserr("relation: err openr '%d'", i); 408: if (i) 409: /* invalid relation name */ 410: yyerror(RESAPPEX, $1, 0); 411: Resrng = rngent(R_INTERNAL, "", $1, Reldesc.relowner, Reldesc.relatts, Reldesc.relstat); 412: } 413: checkupd(Resrng); 414: break; 415: 416: case mdPROT: 417: case mdINTEG: 418: # ifdef DISTRIB 419: case mdDISTRIB: 420: # endif 421: /* the result is a tuple variable */ 422: Resrng = rnglook($1, LOOKVAR); 423: if (Resrng == 0) 424: /* variable not declared */ 425: yyerror(NOVBLE, $1, 0); 426: break; 427: 428: case mdREPL: 429: case mdDEL: 430: /* the result is a tuple variable */ 431: Resrng = rnglook($1, LOOKVAR); 432: if (Resrng == 0) 433: /* variable not declared */ 434: yyerror(NOVBLE, $1, 0); 435: checkupd(Resrng); 436: Tidnode = tree(NULL, NULL, VAR, 6, Resrng->rentno, &Faketid); 437: break; 438: } 439: } 440: ; 441: tlclause: LPAREN tlist RPAREN = 442: { 443: if (Patflag) 444: /* no patt match in targ list */ 445: yyerror(NOPATMAT, 0); 446: $$ = $2; 447: 448: /* 449: ** replace must have tid node as left branch 450: ** (so does delete but it doesn't have a targ list) 451: */ 452: if (Opflag == mdREPL) 453: { 454: $$ = tlprepend(tree(NULL, Tidnode, RESDOM, 4, 0), $$); 455: } 456: } 457: ; 458: tlist: tlelm 459: | tlist COMMA tlelm = 460: { 461: /* 462: ** attach bulk of targ list to leftmost node 463: ** of new element 464: */ 465: $$ = tlprepend($1, $3); 466: } 467: ; 468: tlelm: NAME is afcn = 469: { 470: Trname = $1; 471: /* make a new resdom entry for targ list */ 472: $$ = addresdom(NULL, $3); 473: } 474: | attrib = 475: { 476: /* makes a new resdom entry for targ list */ 477: $$ = addresdom(NULL, $1); 478: } 479: | var PERIOD ALL = 480: { 481: if (Opflag == mdREPL) 482: /* ALL not defined for REPLACE */ 483: yyerror(REPALL, $1->varname, 0); 484: /* makes set of new resdom entries for targ list */ 485: $$ = xdot($1); 486: } 487: ; 488: is: IS 489: | BY 490: ; 491: qualclause: where qual = 492: { 493: # ifdef xPTM 494: if (tTf(76, 2)) 495: timtrace(25, 0); 496: # endif 497: $$ = norml($2); 498: Qlflag--; 499: # ifdef xPTM 500: if (tTf(76, 2)) 501: timtrace(26, 0); 502: # endif 503: } 504: | = 505: { 506: /* null qualification */ 507: $$ = norml(NULL); 508: } 509: ; 510: where: WHERE = 511: Qlflag++; 512: ; 513: qual: LPAREN qual RPAREN = 514: $$ = $2; 515: | LUOP qual = 516: $$ = tree(NULL, $2, UOP, 2, $1); 517: | qual LBOP qual = 518: $$ = tree($1, $3, $2, 0, 0); 519: | clause 520: ; 521: clause: afcn relop afcn = 522: $$ = tree($1, $3, BOP, 2, $2); 523: ; 524: relop: EOP 525: | IS 526: | BDOP 527: ; 528: afcn: aggrfcn 529: | attribfcn 530: | afcn BAOPH afcn = 531: $$ = tree($1, $3, BOP, 2, $2); 532: | afcn BAOP afcn = 533: $$ = tree($1, $3, BOP, 2, $2); 534: | afcn UAOP afcn = 535: $$ = tree($1, $3, BOP, 2, $2); 536: | LPAREN afcn RPAREN = 537: $$ = $2; 538: | uop afcn %prec unaryop = 539: $$ = tree(NULL, $2, UOP, 2, $1); 540: | FOP LPAREN afcn RPAREN = 541: $$ = tree($3, NULL, UOP, 2, $1); 542: | FBOP LPAREN afcn COMMA afcn RPAREN = 543: $$ = tree($3, $5, BOP, 2, $1); 544: ; 545: aggrfcn: AGOP LPAREN afcn BY domseq qualclause RPAREN = 546: { 547: # ifdef xPTR2 548: tTfp(35, 0, "agg func\n"); 549: # endif 550: windup($5); 551: $$ = tree(tree($5, tree(NULL, $3, AOP, 6, $1), BYHEAD, 0, 0), $6, AGHEAD, 0, 0); 552: } 553: | AGOP LPAREN afcn qualclause RPAREN = 554: { 555: $$ = tree(tree(NULL, $3, AOP, 6, $1), $4, AGHEAD, 0, 0); 556: } 557: ; 558: domseq: targdom 559: | domseq COMMA targdom = 560: { 561: $$ = tlprepend($1, $3); 562: } 563: ; 564: targdom: afcn = 565: { 566: $$ = tree(NULL, $1, RESDOM, 4, Rsdmno); 567: } 568: ; 569: attrib: var PERIOD NAME = 570: { 571: # ifdef xPTR2 572: tTfp(37, 0, "attrib %s.%s found\n", $1->varname, $3); 573: # endif 574: 575: /* remember attribute name */ 576: Trname = $3; 577: 578: /* look up attribute */ 579: aptr = attlookup($1, Trname); 580: $$ = tree(NULL, NULL, VAR, 6, $1->rentno, aptr); 581: } 582: ; 583: var: NAME = 584: { 585: $$ = rnglook($1, LOOKVAR); 586: if ($$ == 0) 587: /* variable not declared */ 588: yyerror(NOVBLE, $1, 0); 589: } 590: ; 591: attribfcn: I2CONST = 592: { 593: $$ = tree(NULL, NULL, INT, 2, $1); 594: } 595: | I4CONST = 596: { 597: $$ = tree(NULL, NULL, INT, 4, $1); 598: } 599: | F4CONST = 600: { 601: $$ = tree(NULL, NULL, FLOAT, 4, $1); 602: } 603: | F8CONST = 604: { 605: $$ = tree(NULL, NULL, FLOAT, 8, $1); 606: } 607: | SCONST = 608: { 609: if (patmat($1) && !Qlflag) 610: Patflag = 1; 611: $$ = tree(NULL, NULL, CHAR, length($1), $1); 612: } 613: | NAME = 614: { 615: $$ = tree(NULL, NULL, COP, 2, $1); 616: } 617: | attrib 618: ; 619: uop: UAOP %prec unaryop = 620: { 621: if ($1 == opADD) 622: $$ = opPLUS; 623: else 624: if ($1 == opSUB) 625: $$ = opMINUS; 626: } 627: ; 628: copy: copstmnt alias LPAREN coparam RPAREN keywd SCONST = 629: { 630: # ifdef xPTR2 631: tTfp(41, 0, "copy %s,%s\n", $2, $7); 632: # endif 633: setp($7); 634: } 635: ; 636: copstmnt: COPY = 637: { 638: Opflag = mdCOPY; 639: } 640: ; 641: coparam: cospecs 642: | ; 643: ; 644: cospecs: alias is coent 645: | cospecs COMMA alias is coent 646: ; 647: coent: alias 648: | SCONST = 649: { 650: setp($1); 651: } 652: ; 653: alias: NAME = 654: { 655: setp($1); 656: if (Opflag == mdDESTROY || Opflag == mdCREATE 657: # ifdef DISTRIB 658: || Opflag == mdDCREATE 659: # endif 660: ) 661: rngdel($1); 662: } 663: ; 664: specs: alias is alias 665: | specs COMMA alias is alias 666: ; 667: keywd: INTO = 668: { 669: setp("\0"); 670: setp("i"); 671: } 672: | FROM = 673: { 674: setp("\0"); 675: setp("f"); 676: } 677: ; 678: create: crestmnt alias LPAREN specs RPAREN 679: ; 680: crestmnt: CREATE = 681: { 682: Opflag = mdCREATE; 683: 684: /* set up parameters for regular create */ 685: setp("0"); /* relstat = nil */ 686: } 687: /*DDD*/ | CREATE DISTRD = 688: /*DDD*/ { 689: /*DDD*/ Opflag = mdDCREATE; 690: /*DDD*/ 691: /*DDD*/ /* setup parameters for distributed create */ 692: /*DDD*/ setp("U"); 693: /*DDD*/ setp(""); 694: /*DDD*/ setp("01000"); /* relstat = S_DISTRIBUTED */ 695: /*DDD*/ } 696: ; 697: destroy: destmnt keys 698: | destqm destlist 699: ; 700: destmnt: DESTROY = 701: { 702: Opflag = mdDESTROY; 703: } 704: ; 705: destqm: destmnt INTEGRITY NAME = 706: { 707: Opflag = mdREMQM; 708: if (!Qrymod) 709: /* no qrymod in database */ 710: yyerror(NOQRYMOD, 0); 711: setp("6"); 712: setp($3); 713: } 714: | destmnt PERMIT NAME = 715: { 716: Opflag = mdREMQM; 717: if (!Qrymod) 718: /* no qrymod in database */ 719: yyerror(NOQRYMOD, 0); 720: setp("5"); 721: setp($3); 722: } 723: ; 724: destlist: I2CONST = 725: setp(iocv(i2deref($1))); 726: | destlist COMMA I2CONST = 727: setp(iocv(i2deref($3))); 728: | ALL 729: ; 730: help: helstmnt hlist 731: | helstmnt = 732: setp("2"); /* all relns */ 733: | helqmstmnt hqmlist 734: ; 735: helstmnt: HELP = 736: { 737: Opflag = mdHELP; 738: } 739: ; 740: helqmstmnt: HELP VIEW = 741: { 742: Opflag = mdDISPLAY; 743: if (!Qrymod) 744: /* no qrymod in database */ 745: yyerror(NOQRYMOD, 0); 746: smove("4", hqmbuf); 747: } 748: | HELP PERMIT = 749: { 750: Opflag = mdDISPLAY; 751: if (!Qrymod) 752: /* no qrymod in database */ 753: yyerror(NOQRYMOD, 0); 754: smove("5", hqmbuf); 755: } 756: | HELP INTEGRITY = 757: { 758: Opflag = mdDISPLAY; 759: if (!Qrymod) 760: /* no qrymod in database */ 761: yyerror(NOQRYMOD, 0); 762: smove("6", hqmbuf); 763: } 764: ; 765: hlist: hparam 766: | hlist COMMA hparam 767: | ALL = 768: setp("3"); 769: ; 770: hparam: NAME = 771: { 772: /* relation */ 773: setp("0"); 774: setp($1); 775: } 776: | SCONST = 777: { 778: /* manual page */ 779: setp("1"); 780: setp($1); 781: } 782: ; 783: hqmlist: NAME = 784: { 785: setp(hqmbuf); 786: setp($1); 787: } 788: | hqmlist COMMA NAME = 789: { 790: setp(hqmbuf); 791: setp($3); 792: } 793: ; 794: index: instmnt LPAREN keys RPAREN = 795: { 796: if (Rsdmno > MAXKEYS) 797: /* too many attributes in key */ 798: yyerror(INDEXTRA, 0); 799: } 800: ; 801: instmnt: INDEX ON NAME IS NAME = 802: { 803: /* init INDEX command */ 804: Opflag = mdINDEX; 805: Rsdmno = 0; 806: setp($3); 807: setp($5); 808: Indexname = $5; 809: } 810: ; 811: modify: modstmnt alias TO modstorage modkeys modqual 812: ; 813: modstmnt: MODIFY = 814: { 815: Opflag = mdMODIFY; 816: Rsdmno = 0; 817: } 818: ; 819: modstorage: NAME = 820: setp($1); 821: modkeys: modstkey modrptkey 822: | ; 823: ; 824: modstkey: ON = 825: setp("name"); 826: ; 827: modrptkey: modbasekey 828: | modrptkey COMMA modbasekey 829: ; 830: modbasekey: NAME = 831: setp($1); 832: | NAME COLON NAME = 833: { 834: concat($1, ztack(":", $3), modbuf); 835: setp(modbuf); 836: } 837: ; 838: modqual: modcond modfill 839: | ; 840: ; 841: modcond: WHERE = 842: setp("\0"); 843: ; 844: modfill: modfillnum 845: | modfill COMMA modfillnum 846: ; 847: modfillnum: NAME IS I2CONST = 848: { 849: setp($1); 850: setp(iocv(i2deref($3))); 851: } 852: ; 853: keys: alias = 854: Rsdmno++; 855: | keys COMMA alias = 856: Rsdmno++; 857: ; 858: print: prinstmnt keys 859: ; 860: prinstmnt: PRINT = 861: { 862: Opflag = mdPRINT; 863: } 864: ; 865: save: savstmnt alias UNTIL date 866: ; 867: savstmnt: SAVE = 868: { 869: Opflag = mdSAVE; 870: } 871: ; 872: date: month day_year day_year 873: ; 874: month: alias 875: | day_year 876: ; 877: day_year: I2CONST = 878: { 879: i = iocv(i2deref($1)); 880: # ifdef xPTR3 881: tTfp(57, 1, "day_year: %s\n", i); 882: # endif 883: setp(i); 884: } 885: ; 886: %% 887: # include "../scanner.h" 888: # include "../unix.h" 889: # include "tables.y" 890: # include "yyerror.y"