ack/lang/fortran/comp/gram.dcl

400 lines
7.9 KiB
Plaintext
Raw Normal View History

1991-10-07 16:35:03 +00:00
spec: dcl
| common
| external
| intrinsic
| equivalence
| data
| implicit
| namelist
| SSAVE
{ NO66("SAVE statement");
saveall = YES; }
| SSAVE savelist
{ NO66("SAVE statement"); }
| SFORMAT
{ fmtstmt(thislabel); setfmt(thislabel); }
| SPARAM in_dcl SLPAR paramlist SRPAR
{ NO66("PARAMETER statement"); }
;
dcl: type opt_comma name in_dcl new_dcl dims lengspec
{ settype($3, $1, $7);
if(ndim>0) setbound($3,ndim,dims);
}
| dcl SCOMMA name dims lengspec
{ settype($3, $1, $5);
if(ndim>0) setbound($3,ndim,dims);
}
| dcl SSLASHD datainit vallist SSLASHD
{ if (new_dcl == 2) {
err("attempt to give DATA in type-declaration");
new_dcl = 1;
}
}
;
new_dcl: { new_dcl = 2; }
type: typespec lengspec
{ varleng = $2;
if (vartype == TYLOGICAL && varleng == 1) {
varleng = 0;
err("treating LOGICAL*1 as LOGICAL");
--nerr; /* allow generation of .c file */
}
}
;
typespec: typename
{ varleng = ($1<0 || $1==TYLONG ? 0 : typesize[$1]);
vartype = $1; }
;
typename: SINTEGER { $$ = TYLONG; }
| SREAL { $$ = tyreal; }
| SCOMPLEX { ++complex_seen; $$ = tycomplex; }
| SDOUBLE { $$ = TYDREAL; }
| SDCOMPLEX { ++dcomplex_seen; NOEXT("DOUBLE COMPLEX statement"); $$ = TYDCOMPLEX; }
| SLOGICAL { $$ = TYLOGICAL; }
| SCHARACTER { NO66("CHARACTER statement"); $$ = TYCHAR; }
| SUNDEFINED { $$ = TYUNKNOWN; }
| SDIMENSION { $$ = TYUNKNOWN; }
| SAUTOMATIC { NOEXT("AUTOMATIC statement"); $$ = - STGAUTO; }
| SSTATIC { NOEXT("STATIC statement"); $$ = - STGBSS; }
;
lengspec:
{ $$ = varleng; }
| SSTAR intonlyon expr intonlyoff
{
expptr p;
p = $3;
NO66("length specification *n");
if( ! ISICON(p) || p->constblock.Const.ci <= 0 )
{
$$ = 0;
dclerr("length must be a positive integer constant",
NPNULL);
}
else {
if (vartype == TYCHAR)
$$ = p->constblock.Const.ci;
else switch((int)p->constblock.Const.ci) {
case 1: $$ = 1; break;
case 2: $$ = typesize[TYSHORT]; break;
case 4: $$ = typesize[TYLONG]; break;
case 8: $$ = typesize[TYDREAL]; break;
case 16: $$ = typesize[TYDCOMPLEX]; break;
default:
dclerr("invalid length",NPNULL);
$$ = varleng;
}
}
}
| SSTAR intonlyon SLPAR SSTAR SRPAR intonlyoff
{ NO66("length specification *(*)"); $$ = -1; }
;
common: SCOMMON in_dcl var
{ incomm( $$ = comblock("") , $3 ); }
| SCOMMON in_dcl comblock var
{ $$ = $3; incomm($3, $4); }
| common opt_comma comblock opt_comma var
{ $$ = $3; incomm($3, $5); }
| common SCOMMA var
{ incomm($1, $3); }
;
comblock: SCONCAT
{ $$ = comblock(""); }
| SSLASH SNAME SSLASH
{ $$ = comblock(token); }
;
external: SEXTERNAL in_dcl name
{ setext($3); }
| external SCOMMA name
{ setext($3); }
;
intrinsic: SINTRINSIC in_dcl name
{ NO66("INTRINSIC statement"); setintr($3); }
| intrinsic SCOMMA name
{ setintr($3); }
;
equivalence: SEQUIV in_dcl equivset
| equivalence SCOMMA equivset
;
equivset: SLPAR equivlist SRPAR
{
struct Equivblock *p;
if(nequiv >= maxequiv)
many("equivalences", 'q', maxequiv);
p = & eqvclass[nequiv++];
p->eqvinit = NO;
p->eqvbottom = 0;
p->eqvtop = 0;
p->equivs = $2;
}
;
equivlist: lhs
{ $$=ALLOC(Eqvchain);
$$->eqvitem.eqvlhs = (struct Primblock *)$1;
}
| equivlist SCOMMA lhs
{ $$=ALLOC(Eqvchain);
$$->eqvitem.eqvlhs = (struct Primblock *) $3;
$$->eqvnextp = $1;
}
;
data: SDATA in_data datalist
| data opt_comma datalist
;
in_data:
{ if(parstate == OUTSIDE)
{
newproc();
startproc(ESNULL, CLMAIN);
}
if(parstate < INDATA)
{
enddcl();
parstate = INDATA;
datagripe = 1;
}
}
;
datalist: datainit datavarlist SSLASH datapop vallist SSLASH
{ ftnint junk;
if(nextdata(&junk) != NULL)
err("too few initializers");
frdata($2);
frrpl();
}
;
datainit: /* nothing */ { frchain(&datastack); curdtp = 0; }
datapop: /* nothing */ { pop_datastack(); }
vallist: { toomanyinit = NO; } val
| vallist SCOMMA val
;
val: value
{ dataval(ENULL, $1); }
| simple SSTAR value
{ dataval($1, $3); }
;
value: simple
| addop simple
{ if( $1==OPMINUS && ISCONST($2) )
consnegop((Constp)$2);
$$ = $2;
}
| complex_const
;
savelist: saveitem
| savelist SCOMMA saveitem
;
saveitem: name
{ int k;
$1->vsave = YES;
k = $1->vstg;
if( ! ONEOF(k, M(STGUNKNOWN)|M(STGBSS)|M(STGINIT)) )
dclerr("can only save static variables", $1);
}
| comblock
;
paramlist: paramitem
| paramlist SCOMMA paramitem
;
paramitem: name SEQUALS expr
{ if($1->vclass == CLUNKNOWN)
make_param((struct Paramblock *)$1, $3);
else dclerr("cannot make into parameter", $1);
}
;
var: name dims
{ if(ndim>0) setbound($1, ndim, dims); }
;
datavar: lhs
{ Namep np;
np = ( (struct Primblock *) $1) -> namep;
vardcl(np);
if(np->vstg == STGCOMMON)
extsymtab[np->vardesc.varno].extinit = YES;
else if(np->vstg==STGEQUIV)
eqvclass[np->vardesc.varno].eqvinit = YES;
else if(np->vstg!=STGINIT && np->vstg!=STGBSS)
dclerr("inconsistent storage classes", np);
$$ = mkchain((char *)$1, CHNULL);
}
| SLPAR datavarlist SCOMMA dospec SRPAR
{ chainp p; struct Impldoblock *q;
pop_datastack();
q = ALLOC(Impldoblock);
q->tag = TIMPLDO;
(q->varnp = (Namep) ($4->datap))->vimpldovar = 1;
p = $4->nextp;
if(p) { q->implb = (expptr)(p->datap); p = p->nextp; }
if(p) { q->impub = (expptr)(p->datap); p = p->nextp; }
if(p) { q->impstep = (expptr)(p->datap); }
frchain( & ($4) );
$$ = mkchain((char *)q, CHNULL);
q->datalist = hookup($2, $$);
}
;
datavarlist: datavar
{ if (!datastack)
curdtp = 0;
datastack = mkchain((char *)curdtp, datastack);
curdtp = $1; curdtelt = 0;
}
| datavarlist SCOMMA datavar
{ $$ = hookup($1, $3); }
;
dims:
{ ndim = 0; }
| SLPAR dimlist SRPAR
;
dimlist: { ndim = 0; } dim
| dimlist SCOMMA dim
;
dim: ubound
{
if(ndim == maxdim)
err("too many dimensions");
else if(ndim < maxdim)
{ dims[ndim].lb = 0;
dims[ndim].ub = $1;
}
++ndim;
}
| expr SCOLON ubound
{
if(ndim == maxdim)
err("too many dimensions");
else if(ndim < maxdim)
{ dims[ndim].lb = $1;
dims[ndim].ub = $3;
}
++ndim;
}
;
ubound: SSTAR
{ $$ = 0; }
| expr
;
labellist: label
{ nstars = 1; labarray[0] = $1; }
| labellist SCOMMA label
{ if(nstars < MAXLABLIST) labarray[nstars++] = $3; }
;
label: SICON
{ $$ = execlab( convci(toklen, token) ); }
;
implicit: SIMPLICIT in_dcl implist
{ NO66("IMPLICIT statement"); }
| implicit SCOMMA implist
;
implist: imptype SLPAR letgroups SRPAR
| imptype
{ if (vartype != TYUNKNOWN)
dclerr("-- expected letter range",NPNULL);
setimpl(vartype, varleng, 'a', 'z'); }
;
imptype: { needkwd = 1; } type
/* { vartype = $2; } */
;
letgroups: letgroup
| letgroups SCOMMA letgroup
;
letgroup: letter
{ setimpl(vartype, varleng, $1, $1); }
| letter SMINUS letter
{ setimpl(vartype, varleng, $1, $3); }
;
letter: SNAME
{ if(toklen!=1 || token[0]<'a' || token[0]>'z')
{
dclerr("implicit item must be single letter", NPNULL);
$$ = 0;
}
else $$ = token[0];
}
;
namelist: SNAMELIST
| namelist namelistentry
;
namelistentry: SSLASH name SSLASH namelistlist
{
if($2->vclass == CLUNKNOWN)
{
$2->vclass = CLNAMELIST;
$2->vtype = TYINT;
$2->vstg = STGBSS;
$2->varxptr.namelist = $4;
$2->vardesc.varno = ++lastvarno;
}
else dclerr("cannot be a namelist name", $2);
}
;
namelistlist: name
{ $$ = mkchain((char *)$1, CHNULL); }
| namelistlist SCOMMA name
{ $$ = hookup($1, mkchain((char *)$3, CHNULL)); }
;
in_dcl:
{ switch(parstate)
{
case OUTSIDE: newproc();
startproc(ESNULL, CLMAIN);
case INSIDE: parstate = INDCL;
case INDCL: break;
case INDATA:
if (datagripe) {
errstr(
"Statement order error: declaration after DATA",
CNULL);
datagripe = 0;
}
break;
default:
dclerr("declaration among executables", NPNULL);
}
}
;