funarglist:
		{ $$ = 0; }
	| funargs
	;

funargs:  expr
		{ $$ = mkchain($1, 0); }
	| funargs SCOMMA expr
		{ $$ = hookup($1, mkchain($3,0) ); }
	;


expr:	  uexpr
	| SLPAR expr SRPAR	{ $$ = $2; }
	| complex_const
	;

uexpr:	  lhs
	| simple_const
	| expr addop expr   %prec SPLUS
		{ $$ = mkexpr($2, $1, $3); }
	| expr SSTAR expr
		{ $$ = mkexpr(OPSTAR, $1, $3); }
	| expr SSLASH expr
		{ $$ = mkexpr(OPSLASH, $1, $3); }
	| expr SPOWER expr
		{ $$ = mkexpr(OPPOWER, $1, $3); }
	| addop expr  %prec SSTAR
		{ if($1 == OPMINUS)
			$$ = mkexpr(OPNEG, $2, 0);
		  else 	$$ = $2;
		}
	| expr relop expr  %prec SEQ
		{ $$ = mkexpr($2, $1, $3); }
	| expr SEQV expr
		{ $$ = mkexpr(OPEQV, $1,$3); }
	| expr SNEQV expr
		{ $$ = mkexpr(OPNEQV, $1, $3); }
	| expr SOR expr
		{ $$ = mkexpr(OPOR, $1, $3); }
	| expr SAND expr
		{ $$ = mkexpr(OPAND, $1, $3); }
	| SNOT expr
		{ $$ = mkexpr(OPNOT, $2, 0); }
	| expr SCONCAT expr
		{ $$ = mkexpr(OPCONCAT, $1, $3); }
	;

addop:	  SPLUS		{ $$ = OPPLUS; }
	| SMINUS	{ $$ = OPMINUS; }
	;

relop:	  SEQ	{ $$ = OPEQ; }
	| SGT	{ $$ = OPGT; }
	| SLT	{ $$ = OPLT; }
	| SGE	{ $$ = OPGE; }
	| SLE	{ $$ = OPLE; }
	| SNE	{ $$ = OPNE; }
	;

lhs:	 name
		{ $$ = mkprim($1, 0, 0, 0); }
	| name SLPAR opt_expr SCOLON opt_expr SRPAR
		{ $$ = mkprim($1, 0, $3, $5); }
	| name SLPAR funarglist SRPAR
		{ $$ = mkprim($1, mklist($3), 0, 0); }
	| name SLPAR funarglist SRPAR SLPAR opt_expr SCOLON opt_expr SRPAR
		{ $$ = mkprim($1, mklist($3), $6, $8); }
	;

opt_expr:
		{ $$ = 0; }
	| expr
	;

simple:	  name
		{ if($1->vclass == CLPARAM)
			$$ = cpexpr($1->b_param.paramval);
		}
	| simple_const
	;

simple_const:   STRUE	{ $$ = mklogcon(1); }
	| SFALSE	{ $$ = mklogcon(0); }
	| SHOLLERITH  { $$ = mkstrcon(toklen, token); }
	| SICON	{ $$ = mkintcon( convci(toklen, token) ); }
	| SRCON	{ $$ = mkrealcon(TYREAL, convcd(toklen, token)); }
	| SDCON	{ $$ = mkrealcon(TYDREAL, convcd(toklen, token)); }
	;

complex_const:  SLPAR uexpr SCOMMA uexpr SRPAR
		{ $$ = mkcxcon($2,$4); }
	;

bit_const:  SHEXCON
		{ $$ = mkbitcon(4, toklen, token); }
	| SOCTCON
		{ $$ = mkbitcon(3, toklen, token); }
	| SBITCON
		{ $$ = mkbitcon(1, toklen, token); }
	;

fexpr:	  unpar_fexpr
	| SLPAR fexpr SRPAR
		{ $$ = $2; }
	;

unpar_fexpr:	  lhs
	| simple_const
	| fexpr addop fexpr   %prec SPLUS
		{ $$ = mkexpr($2, $1, $3); }
	| fexpr SSTAR fexpr
		{ $$ = mkexpr(OPSTAR, $1, $3); }
	| fexpr SSLASH fexpr
		{ $$ = mkexpr(OPSLASH, $1, $3); }
	| fexpr SPOWER fexpr
		{ $$ = mkexpr(OPPOWER, $1, $3); }
	| addop fexpr  %prec SSTAR
		{ if($1 == OPMINUS)
			$$ = mkexpr(OPNEG, $2, 0);
		  else	$$ = $2;
		}
	| fexpr SCONCAT fexpr
		{ $$ = mkexpr(OPCONCAT, $1, $3); }
	;
