/*- * Copyright (c) 1980 The Regents of the University of California. * All rights reserved. * * %sccs.include.proprietary.c% * * @(#)gram.head 5.2 (Berkeley) 04/12/91 */ /* * gram.head * * First part of the f77 grammar, f77 compiler pass 1. * * University of Utah CS Dept modification history: * * $Log: gram.head,v $ * Revision 3.2 84/11/06 17:40:52 donn * Fixed bug with redundant labels causing errors when they appear on (e.g.) * PROGRAM statements. * * Revision 3.1 84/10/13 00:22:16 donn * Merged Jerry Berkman's version into mine. * * Revision 2.2 84/08/04 21:13:02 donn * Moved some code out of gram.head into gram.exec in accordance with * Jerry Berkman's fixes to make ASSIGNs work right. * * Revision 2.1 84/07/19 12:03:20 donn * Changed comment headers for UofU. * * Revision 1.2 84/03/23 22:43:06 donn * The subroutine argument temporary fixes from Bob Corbett didn't take into * account the fact that the code generator collects all the assignments to * temporaries at the start of a statement -- hence the temporaries need to * be initialized once per statement instead of once per call. * */ %{ # include "defs.h" # include "data.h" #ifdef SDB # include # ifndef N_SO # include # endif #endif static int equivlisterr; static int do_name_err; static int nstars; static int ndim; static int vartype; static ftnint varleng; static struct { expptr lb, ub; } dims[MAXDIM+1]; static struct Labelblock *labarray[MAXLABLIST]; static int lastwasbranch = NO; static int thiswasbranch = NO; extern ftnint yystno; extern flag intonly; ftnint convci(); double convcd(); expptr mklogcon(), mkaddcon(), mkrealcon(), mkstrcon(), mkbitcon(); expptr mkcxcon(); struct Listblock *mklist(); struct Listblock *mklist(); struct Impldoblock *mkiodo(); struct Extsym *comblock(); %} /* Specify precedences and associativities. */ %union { int ival; char *charpval; chainp chval; tagptr tagval; expptr expval; struct Labelblock *labval; struct Nameblock *namval; struct Eqvchain *eqvval; struct Extsym *extval; union Vexpr *vexpval; struct ValList *drvals; struct Vlist *dvals; union Delt *deltp; struct Rpair *rpairp; struct Elist *elistp; } %left SCOMMA %nonassoc SCOLON %right SEQUALS %left SEQV SNEQV %left SOR %left SAND %left SNOT %nonassoc SLT SGT SLE SGE SEQ SNE %left SCONCAT %left SPLUS SMINUS %left SSTAR SSLASH %right SPOWER %start program %type thislabel label assignlabel %type other inelt %type lengspec type typespec typename dcl letter addop relop stop nameeq %type filename %type namelistlist funarglist funargs dospec %type callarglist arglist args exprlist inlist outlist out2 substring %type name arg call var entryname progname %type lhs expr uexpr opt_expr fexpr unpar_fexpr %type ubound callarg complex_const simple_const %type common comblock %type equivlist %type datavalue real_const unsignedreal bit_const %type unsignedint int_const %type dataname %type iconprimary iconfactor iconterm iconexpr opticonexpr %type datarval datarvals %type iconexprlist datasubs %type dataelt dataimplieddo datalval %type datarange %type dlist datalvals %% program: | program stat SEOS ; stat: thislabel entry { lastwasbranch = NO; } | thislabel spec | thislabel exec { if($1 && ($1->labelno==dorange)) enddo($1->labelno); if(lastwasbranch && thislabel==NULL) warn("statement cannot be reached"); lastwasbranch = thiswasbranch; thiswasbranch = NO; if($1) { if($1->labtype == LABFORMAT) err("label already that of a format"); else $1->labtype = LABEXEC; } if(!optimflag) { argtemplist = hookup(argtemplist, activearglist); activearglist = CHNULL; } } | thislabel SINCLUDE filename { doinclude( $3 ); } | thislabel SEND end_spec { lastwasbranch = NO; endproc(); } | thislabel SUNKNOWN { execerr("unclassifiable statement", CNULL); flline(); }; | error { flline(); needkwd = NO; inioctl = NO; yyerrok; yyclearin; } ; thislabel: SLABEL { #ifdef SDB if( sdbflag ) { linenostab(lineno); } #endif if(yystno != 0) { $$ = thislabel = mklabel(yystno); if(thislabel->labdefined) execerr("label %s already defined", convic(thislabel->stateno) ); else { if(thislabel->blklevel!=0 && thislabel->blklevellabtype!=LABFORMAT) warn1("there is a branch to label %s from outside block", convic( (ftnint) (thislabel->stateno) ) ); thislabel->blklevel = blklevel; thislabel->labdefined = YES; } } else $$ = thislabel = NULL; } ; entry: SPROGRAM new_proc progname {startproc($3, CLMAIN); } | SBLOCK new_proc progname { if($3) NO66("named BLOCKDATA"); startproc($3, CLBLOCK); } | SSUBROUTINE new_proc entryname arglist { entrypt(CLPROC, TYSUBR, (ftnint) 0, $3, $4); } | SFUNCTION new_proc entryname arglist { entrypt(CLPROC, TYUNKNOWN, (ftnint) 0, $3, $4); } | type SFUNCTION new_proc entryname arglist { entrypt(CLPROC, $1, varleng, $4, $5); } | SENTRY entryname arglist { if(parstate==OUTSIDE || procclass==CLMAIN || procclass==CLBLOCK) execerr("misplaced entry statement", CNULL); entrypt(CLENTRY, 0, (ftnint) 0, $2, $3); } ; new_proc: { newproc(); } ; entryname: name ; name: SNAME { $$ = mkname(toklen, token); } ; progname: { $$ = NULL; } | entryname ; arglist: { $$ = 0; } | SLPAR SRPAR { NO66(" () argument list"); $$ = 0; } | SLPAR args SRPAR {$$ = $2; } ; args: arg { $$ = ($1 ? mkchain($1,CHNULL) : CHNULL ); } | args SCOMMA arg { if($3) $1 = $$ = hookup($1, mkchain($3,CHNULL)); } ; arg: name { if(($1->vstg!=STGUNKNOWN && $1->vstg!=STGARG) || ($1->vclass == CLPARAM) ) { dclerr("name declared as argument after use", $1); $$ = NULL; } else $1->vstg = STGARG; } | SSTAR { NO66("altenate return argument"); $$ = 0; substars = YES; } ; filename: SHOLLERITH { char *s; s = copyn(toklen+1, token); s[toklen] = '\0'; $$ = s; } ;