399 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			399 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| 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);
 | |
| 			}
 | |
| 		}
 | |
| 	;
 |