/* **This file contains the specification of QUEL recognized by the parser. */ /* COMMANDS */ %term APPEND COPY CREATE DELETE DESTROY HELP INDEX MODIFY %term PRINT RANGE REPLACE RETRIEVE SAVE %term DEFINE PERMIT VIEW INTEGRITY /*DDD*/%term DISTRIBUTE /* 'NOISE' WORDS */ %term ALL BY FROM IN INTO UNIQUE AT %term IS OF ON ONTO TO UNTIL WHERE /*DDD*/%term DISTRD /* CONSTANTS */ %term NAME SCONST I2CONST I4CONST F4CONST F8CONST /* PUNCTUATION */ %term COMMA LPAREN PERIOD RPAREN COLON BGNCMNT ENDCMNT /* UNARY ARITHMETIC OPERATORS */ %term UAOP /* BINARY ARITHMETIC OPERATORS */ %term BAOP BAOPH /* BOUNDS OPERATORS */ %term BDOP /* EQUALITY OPERATORS */ %term EOP /* LOGICAL OPERATORS */ %term LBOP LUOP /* FUNCTIONAL OPERATORS */ %term FOP FBOP /* AGGREGATE OPERATORS */ %term AGOP /* DEFINE ASCENDING PRECEDENCE FOR OPERATORS */ %left LBOP %left LUOP %left UAOP %left BAOP %left BAOPH %binary unaryop %{ /* SCANNER/PARSER GLOBALS & TABLES */ # include "../ingres.h" # include "../aux.h" # include "../tree.h" # include "../symbol.h" # include "parser.h" %} %% %{ register int i; register struct atstash *aptr; char permbuf[3]; /* space for two names, their null bytes and the seperator */ char modbuf[(2 * (MAXNAME + 1)) + 1]; static char hqmbuf[2]; %} program: xprogram | ; xprogram: xprogram stmnt = endquelst(Opflag); | stmnt = endquelst(Opflag); ; stmnt: append | copy | create | delete | destroy /*DDD*/ | distribute | help | index | integrity | modify | permit | print | range | replace | retrieve | save | view ; range: rngstmnt OF NAME IS NAME = { if ((i = openr(&Reldesc, -1, $5)) < 0) syserr("relname: error in openr '%d'", i); if (i > 0) /* invalid relation name */ yyerror(RNGEXIST, $5, 0); rngent(R_EXTERNAL, $3, $5, Reldesc.relowner, Reldesc.relatts, Reldesc.relstat); } ; rngstmnt: RANGE = { Opflag = mdRANGE; } ; append: apstmnt apto relation tlclause qualclause = { /* make root node */ Lastree = tree($4, $5, ROOT, 0, 0); } ; apstmnt: APPEND = { Opflag = mdAPP; } ; apto: INTO | ONTO | TO | ON | ; ; delete: delstmnt delwd relation qualclause = { /* make root node for delete, with a TIDNODE at leftmost */ Lastree = tree(tree(NULL, Tidnode, RESDOM, 4, NULL), $4, ROOT, 0, 0); } ; delstmnt: DELETE = { Opflag = mdDEL; } ; delwd: IN | ON | FROM | ; ; replace: repstmnt repkwd relation tlclause qualclause = { /* make root node for replace */ Lastree = tree($4, $5, ROOT, 0, 0); } ; repstmnt: REPLACE = { Opflag = mdREPL; } ; repkwd: INTO | IN | ON | ; ; retrieve: retstmnt retclause tlclause qualclause = { /* make root node for retrieve */ Lastree = tree($3, $4, ROOT, 0, 0); } ; retstmnt: RETRIEVE = { Opflag = mdRETR; } ; retclause: retkwd relation = { /* set up pipe block and save relname for create */ Rsdmno = 0; setp("0"); /* relstat = nil */ setp(Resrng->relnm); } | = { /* no result relation, output to terminal */ Rsdmno = 0; Resrng = 0; } | UNIQUE = { Opflag = mdRET_UNI; Rsdmno = 0; Resrng = 0; } ; retkwd: INTO | TO | ; ; view: viewclause tlclause qualclause = { Lastree = tree($2, $3, ROOT, 0, 0); } ; viewclause: viewstmnt relation = { Rsdmno = 0; setp("0040"); /* relstat = S_VIEW */ setp(Resrng->relnm); } ; viewstmnt: DEFINE VIEW = { Opflag = mdVIEW; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); } ; permit: permstmnt permlist permrel permtarg permwho permplace permtd qualclause = { Lastree = tree($4, $8, ROOT, 0, 0); } ; permstmnt: DEFINE PERMIT = { Opflag = mdPROT; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); } ; permlist: permxlist | permlist COMMA permxlist ; permxlist: ALL = permcom(-1); /* means 'all' commands */ | RETRIEVE = permcom(mdRETR); | DELETE = permcom(mdDEL); | APPEND = permcom(mdAPP); | REPLACE = permcom(mdREPL); ; permrel: permword relation = { /* put command vector into list now since this always happens */ setp(iocv(Permcomd)); Permcomd = 0; /* reset command map */ setp(Resrng->relnm); bmove(Resrng->relnowner, permbuf, 2); permbuf[2] = 0; setp(permbuf); } ; permword: ON | OF | TO ; permtarg: LPAREN permtlist RPAREN = { $$ = $2; } | = { $$ = NULL; } ; permtlist: permtlelm | permtlist COMMA permtlelm = { /* ** attach bulk of permit tl to leftmost node of new elem */ $$ = tlprepend($1, $3); } ; permtlelm: NAME = { /* Resrng is set by the "relation" production */ Trname = $1; aptr = attlookup(Resrng, Trname); $$ = tree(NULL, NULL, VAR, 6, Resrng->rentno, aptr); $$ = addresdom(NULL, $$); } ; permwho: TO NAME = setp($2); | TO ALL = setp("all"); ; permplace: AT NAME = setp($2); | AT ALL = setp("all"); | = setp("all"); /* default is all */ ; permtd: permtime permday | permdeftime permday | permtime permdefday | permdeftime permdefday ; permdeftime: = { setp("0"); setp("1440"); } ; permdefday: = { setp("sun"); setp("sat"); } ; permtime: FROM I2CONST COLON I2CONST TO I2CONST COLON I2CONST = { setp(iocv(timeofday($2, $4))); setp(iocv(timeofday($6, $8))); } ; permday: ON NAME TO NAME = { setp($2); setp($4); } ; integrity: integstmnt integnoise relation integis qual = { Lastree = tree(NULL, norml($5), ROOT, 0, 0); Qlflag--; /* turn off here */ } ; integstmnt: DEFINE INTEGRITY = { Opflag = mdINTEG; Qlflag++; /* OK to turn on here because integrity doesn't have a targ list */ if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); } ; integnoise: ON | ONTO | IN | OF | /* null */ ; integis: IS | /* null*/ ; /*DDD*/distribute: diststmnt relation AT distcrits = /*DDD*/ { /*DDD*/ $$ = tree(NULL, NULL, QLEND, 0); /*DDD*/ Lastree = tree($4, $$, ROOT, 0); /*DDD*/ } /*DDD*/; /*DDD*/diststmnt: DISTRIBUTE = /*DDD*/ Opflag = mdDISTRIB; /*DDD*/; /*DDD*/distcrits: dcriterion = /*DDD*/ { /*DDD*/ $$ = $1; /*DDD*/ } /*DDD*/ | distcrits dcriterion = /*DDD*/ { /*DDD*/ $$ = tlprepend($1, $2); /*DDD*/ } /*DDD*/; /*DDD*/dcriterion: NAME where qual = /*DDD*/ { /*DDD*/ Qlflag--; /*DDD*/ $$ = tree(NULL, norml($3), SITE, 2, $1); /*DDD*/ } /*DDD*/; relation: NAME = { # ifdef xPTR2 tTfp(32, 0, "res rel name/var: '%s'\n", $1); # endif switch (Opflag) { case mdRETR: case mdVIEW: /* result better not be a rel name */ if ((i = openr(&Reldesc, -1, $1)) < 0) syserr("relation: err openr '%d'", i); if (i == 0) { /* reln exists */ if (bequal(Reldesc.relowner, Usercode, 2)) { /* same owner, can't duplicate name */ yyerror(RESEXIST, $1, 0); } else { /* owned by dba -- purge range table */ rngdel($1); } } Resrng = rngent(R_INTERNAL, "", $1, Usercode, 0, 0); break; case mdAPP: /* result is a rel name */ Resrng = rnglook($1, LOOKREL); if (Resrng == 0) { if ((i = openr(&Reldesc, -1, $1)) < 0) syserr("relation: err openr '%d'", i); if (i) /* invalid relation name */ yyerror(RESAPPEX, $1, 0); Resrng = rngent(R_INTERNAL, "", $1, Reldesc.relowner, Reldesc.relatts, Reldesc.relstat); } checkupd(Resrng); break; case mdPROT: case mdINTEG: # ifdef DISTRIB case mdDISTRIB: # endif /* the result is a tuple variable */ Resrng = rnglook($1, LOOKVAR); if (Resrng == 0) /* variable not declared */ yyerror(NOVBLE, $1, 0); break; case mdREPL: case mdDEL: /* the result is a tuple variable */ Resrng = rnglook($1, LOOKVAR); if (Resrng == 0) /* variable not declared */ yyerror(NOVBLE, $1, 0); checkupd(Resrng); Tidnode = tree(NULL, NULL, VAR, 6, Resrng->rentno, &Faketid); break; } } ; tlclause: LPAREN tlist RPAREN = { if (Patflag) /* no patt match in targ list */ yyerror(NOPATMAT, 0); $$ = $2; /* ** replace must have tid node as left branch ** (so does delete but it doesn't have a targ list) */ if (Opflag == mdREPL) { $$ = tlprepend(tree(NULL, Tidnode, RESDOM, 4, 0), $$); } } ; tlist: tlelm | tlist COMMA tlelm = { /* ** attach bulk of targ list to leftmost node ** of new element */ $$ = tlprepend($1, $3); } ; tlelm: NAME is afcn = { Trname = $1; /* make a new resdom entry for targ list */ $$ = addresdom(NULL, $3); } | attrib = { /* makes a new resdom entry for targ list */ $$ = addresdom(NULL, $1); } | var PERIOD ALL = { if (Opflag == mdREPL) /* ALL not defined for REPLACE */ yyerror(REPALL, $1->varname, 0); /* makes set of new resdom entries for targ list */ $$ = xdot($1); } ; is: IS | BY ; qualclause: where qual = { # ifdef xPTM if (tTf(76, 2)) timtrace(25, 0); # endif $$ = norml($2); Qlflag--; # ifdef xPTM if (tTf(76, 2)) timtrace(26, 0); # endif } | = { /* null qualification */ $$ = norml(NULL); } ; where: WHERE = Qlflag++; ; qual: LPAREN qual RPAREN = $$ = $2; | LUOP qual = $$ = tree(NULL, $2, UOP, 2, $1); | qual LBOP qual = $$ = tree($1, $3, $2, 0, 0); | clause ; clause: afcn relop afcn = $$ = tree($1, $3, BOP, 2, $2); ; relop: EOP | IS | BDOP ; afcn: aggrfcn | attribfcn | afcn BAOPH afcn = $$ = tree($1, $3, BOP, 2, $2); | afcn BAOP afcn = $$ = tree($1, $3, BOP, 2, $2); | afcn UAOP afcn = $$ = tree($1, $3, BOP, 2, $2); | LPAREN afcn RPAREN = $$ = $2; | uop afcn %prec unaryop = $$ = tree(NULL, $2, UOP, 2, $1); | FOP LPAREN afcn RPAREN = $$ = tree($3, NULL, UOP, 2, $1); | FBOP LPAREN afcn COMMA afcn RPAREN = $$ = tree($3, $5, BOP, 2, $1); ; aggrfcn: AGOP LPAREN afcn BY domseq qualclause RPAREN = { # ifdef xPTR2 tTfp(35, 0, "agg func\n"); # endif windup($5); $$ = tree(tree($5, tree(NULL, $3, AOP, 6, $1), BYHEAD, 0, 0), $6, AGHEAD, 0, 0); } | AGOP LPAREN afcn qualclause RPAREN = { $$ = tree(tree(NULL, $3, AOP, 6, $1), $4, AGHEAD, 0, 0); } ; domseq: targdom | domseq COMMA targdom = { $$ = tlprepend($1, $3); } ; targdom: afcn = { $$ = tree(NULL, $1, RESDOM, 4, Rsdmno); } ; attrib: var PERIOD NAME = { # ifdef xPTR2 tTfp(37, 0, "attrib %s.%s found\n", $1->varname, $3); # endif /* remember attribute name */ Trname = $3; /* look up attribute */ aptr = attlookup($1, Trname); $$ = tree(NULL, NULL, VAR, 6, $1->rentno, aptr); } ; var: NAME = { $$ = rnglook($1, LOOKVAR); if ($$ == 0) /* variable not declared */ yyerror(NOVBLE, $1, 0); } ; attribfcn: I2CONST = { $$ = tree(NULL, NULL, INT, 2, $1); } | I4CONST = { $$ = tree(NULL, NULL, INT, 4, $1); } | F4CONST = { $$ = tree(NULL, NULL, FLOAT, 4, $1); } | F8CONST = { $$ = tree(NULL, NULL, FLOAT, 8, $1); } | SCONST = { if (patmat($1) && !Qlflag) Patflag = 1; $$ = tree(NULL, NULL, CHAR, length($1), $1); } | NAME = { $$ = tree(NULL, NULL, COP, 2, $1); } | attrib ; uop: UAOP %prec unaryop = { if ($1 == opADD) $$ = opPLUS; else if ($1 == opSUB) $$ = opMINUS; } ; copy: copstmnt alias LPAREN coparam RPAREN keywd SCONST = { # ifdef xPTR2 tTfp(41, 0, "copy %s,%s\n", $2, $7); # endif setp($7); } ; copstmnt: COPY = { Opflag = mdCOPY; } ; coparam: cospecs | ; ; cospecs: alias is coent | cospecs COMMA alias is coent ; coent: alias | SCONST = { setp($1); } ; alias: NAME = { setp($1); if (Opflag == mdDESTROY || Opflag == mdCREATE # ifdef DISTRIB || Opflag == mdDCREATE # endif ) rngdel($1); } ; specs: alias is alias | specs COMMA alias is alias ; keywd: INTO = { setp("\0"); setp("i"); } | FROM = { setp("\0"); setp("f"); } ; create: crestmnt alias LPAREN specs RPAREN ; crestmnt: CREATE = { Opflag = mdCREATE; /* set up parameters for regular create */ setp("0"); /* relstat = nil */ } /*DDD*/ | CREATE DISTRD = /*DDD*/ { /*DDD*/ Opflag = mdDCREATE; /*DDD*/ /*DDD*/ /* setup parameters for distributed create */ /*DDD*/ setp("U"); /*DDD*/ setp(""); /*DDD*/ setp("01000"); /* relstat = S_DISTRIBUTED */ /*DDD*/ } ; destroy: destmnt keys | destqm destlist ; destmnt: DESTROY = { Opflag = mdDESTROY; } ; destqm: destmnt INTEGRITY NAME = { Opflag = mdREMQM; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); setp("6"); setp($3); } | destmnt PERMIT NAME = { Opflag = mdREMQM; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); setp("5"); setp($3); } ; destlist: I2CONST = setp(iocv(i2deref($1))); | destlist COMMA I2CONST = setp(iocv(i2deref($3))); | ALL ; help: helstmnt hlist | helstmnt = setp("2"); /* all relns */ | helqmstmnt hqmlist ; helstmnt: HELP = { Opflag = mdHELP; } ; helqmstmnt: HELP VIEW = { Opflag = mdDISPLAY; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); smove("4", hqmbuf); } | HELP PERMIT = { Opflag = mdDISPLAY; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); smove("5", hqmbuf); } | HELP INTEGRITY = { Opflag = mdDISPLAY; if (!Qrymod) /* no qrymod in database */ yyerror(NOQRYMOD, 0); smove("6", hqmbuf); } ; hlist: hparam | hlist COMMA hparam | ALL = setp("3"); ; hparam: NAME = { /* relation */ setp("0"); setp($1); } | SCONST = { /* manual page */ setp("1"); setp($1); } ; hqmlist: NAME = { setp(hqmbuf); setp($1); } | hqmlist COMMA NAME = { setp(hqmbuf); setp($3); } ; index: instmnt LPAREN keys RPAREN = { if (Rsdmno > MAXKEYS) /* too many attributes in key */ yyerror(INDEXTRA, 0); } ; instmnt: INDEX ON NAME IS NAME = { /* init INDEX command */ Opflag = mdINDEX; Rsdmno = 0; setp($3); setp($5); Indexname = $5; } ; modify: modstmnt alias TO modstorage modkeys modqual ; modstmnt: MODIFY = { Opflag = mdMODIFY; Rsdmno = 0; } ; modstorage: NAME = setp($1); modkeys: modstkey modrptkey | ; ; modstkey: ON = setp("name"); ; modrptkey: modbasekey | modrptkey COMMA modbasekey ; modbasekey: NAME = setp($1); | NAME COLON NAME = { concat($1, ztack(":", $3), modbuf); setp(modbuf); } ; modqual: modcond modfill | ; ; modcond: WHERE = setp("\0"); ; modfill: modfillnum | modfill COMMA modfillnum ; modfillnum: NAME IS I2CONST = { setp($1); setp(iocv(i2deref($3))); } ; keys: alias = Rsdmno++; | keys COMMA alias = Rsdmno++; ; print: prinstmnt keys ; prinstmnt: PRINT = { Opflag = mdPRINT; } ; save: savstmnt alias UNTIL date ; savstmnt: SAVE = { Opflag = mdSAVE; } ; date: month day_year day_year ; month: alias | day_year ; day_year: I2CONST = { i = iocv(i2deref($1)); # ifdef xPTR3 tTfp(57, 1, "day_year: %s\n", i); # endif setp(i); } ; %% # include "../scanner.h" # include "../unix.h" # include "tables.y" # include "yyerror.y"