xref: /plan9-contrib/sys/src/cmd/spin/spin.y (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1219b2ee8SDavid du Colombier /***** spin: spin.y *****/
2219b2ee8SDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  */
8219b2ee8SDavid du Colombier 
9219b2ee8SDavid du Colombier %{
10219b2ee8SDavid du Colombier #include "spin.h"
1100d97012SDavid du Colombier #include <sys/types.h>
1200d97012SDavid du Colombier #ifndef PC
1300d97012SDavid du Colombier #include <unistd.h>
1400d97012SDavid du Colombier #endif
15219b2ee8SDavid du Colombier #include <stdarg.h>
16219b2ee8SDavid du Colombier 
17*de2caf28SDavid du Colombier #define YYMAXDEPTH	20000	/* default is 10000 */
18219b2ee8SDavid du Colombier #define YYDEBUG		0
19219b2ee8SDavid du Colombier #define Stop	nn(ZN,'@',ZN,ZN)
20*de2caf28SDavid du Colombier #define PART0	"place initialized declaration of "
2100d97012SDavid du Colombier #define PART1	"place initialized chan decl of "
2200d97012SDavid du Colombier #define PART2	" at start of proctype "
2300d97012SDavid du Colombier 
2400d97012SDavid du Colombier static	Lextok *ltl_to_string(Lextok *);
25219b2ee8SDavid du Colombier 
26219b2ee8SDavid du Colombier extern  Symbol	*context, *owner;
2700d97012SDavid du Colombier extern	Lextok *for_body(Lextok *, int);
2800d97012SDavid du Colombier extern	void for_setup(Lextok *, Lextok *, Lextok *);
2900d97012SDavid du Colombier extern	Lextok *for_index(Lextok *, Lextok *);
3000d97012SDavid du Colombier extern	Lextok *sel_index(Lextok *, Lextok *, Lextok *);
31*de2caf28SDavid du Colombier extern  void    keep_track_off(Lextok *);
32*de2caf28SDavid du Colombier extern	void	safe_break(void);
33*de2caf28SDavid du Colombier extern	void	restore_break(void);
3400d97012SDavid du Colombier extern  int	u_sync, u_async, dumptab, scope_level;
35*de2caf28SDavid du Colombier extern	int	initialization_ok;
36*de2caf28SDavid du Colombier extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np, has_priority;
37*de2caf28SDavid du Colombier extern	short	has_code, has_state, has_ltl, has_io;
38*de2caf28SDavid du Colombier extern	void	check_mtypes(Lextok *, Lextok *);
39312a1df1SDavid du Colombier extern	void	count_runs(Lextok *);
40f3793cddSDavid du Colombier extern	void	no_internals(Lextok *);
41f3793cddSDavid du Colombier extern	void	any_runs(Lextok *);
42*de2caf28SDavid du Colombier extern	void	explain(int);
4300d97012SDavid du Colombier extern	void	ltl_list(char *, char *);
447dd7cddfSDavid du Colombier extern	void	validref(Lextok *, Lextok *);
45*de2caf28SDavid du Colombier extern  void	sanity_check(Lextok *);
467dd7cddfSDavid du Colombier extern	char	yytext[];
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier int	Mpars = 0;	/* max nr of message parameters  */
4900d97012SDavid du Colombier int	nclaims = 0;	/* nr of never claims */
5000d97012SDavid du Colombier int	ltl_mode = 0;	/* set when parsing an ltl formula */
517dd7cddfSDavid du Colombier int	Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
52*de2caf28SDavid du Colombier int	in_for = 0, in_seq = 0, par_cnt = 0;
53*de2caf28SDavid du Colombier int	dont_simplify = 0;
54219b2ee8SDavid du Colombier char	*claimproc = (char *) 0;
557dd7cddfSDavid du Colombier char	*eventmap = (char *) 0;
567dd7cddfSDavid du Colombier 
57*de2caf28SDavid du Colombier static	char *ltl_name;
587dd7cddfSDavid du Colombier static	int  Embedded = 0, inEventMap = 0, has_ini = 0;
597dd7cddfSDavid du Colombier 
60219b2ee8SDavid du Colombier %}
61219b2ee8SDavid du Colombier 
62*de2caf28SDavid du Colombier %token	ASSERT PRINT PRINTM PREPROC
63312a1df1SDavid du Colombier %token	C_CODE C_DECL C_EXPR C_STATE C_TRACK
64*de2caf28SDavid du Colombier %token	RUN LEN ENABLED SET_P GET_P EVAL PC_VAL
65*de2caf28SDavid du Colombier %token	TYPEDEF MTYPE INLINE RETURN LABEL OF
66*de2caf28SDavid du Colombier %token	GOTO BREAK ELSE SEMI ARROW
6700d97012SDavid du Colombier %token	IF FI DO OD FOR SELECT IN SEP DOTDOT
68219b2ee8SDavid du Colombier %token	ATOMIC NON_ATOMIC D_STEP UNLESS
697dd7cddfSDavid du Colombier %token  TIMEOUT NONPROGRESS
707dd7cddfSDavid du Colombier %token	ACTIVE PROCTYPE D_PROCTYPE
717dd7cddfSDavid du Colombier %token	HIDDEN SHOW ISLOCAL
727dd7cddfSDavid du Colombier %token	PRIORITY PROVIDED
73219b2ee8SDavid du Colombier %token	FULL EMPTY NFULL NEMPTY
74219b2ee8SDavid du Colombier %token	CONST TYPE XU			/* val */
757dd7cddfSDavid du Colombier %token	NAME UNAME PNAME INAME		/* sym */
7600d97012SDavid du Colombier %token	STRING CLAIM TRACE INIT	LTL	/* sym */
77219b2ee8SDavid du Colombier 
78219b2ee8SDavid du Colombier %right	ASGN
797dd7cddfSDavid du Colombier %left	SND O_SND RCV R_RCV /* SND doubles as boolean negation */
8000d97012SDavid du Colombier %left	IMPLIES EQUIV			/* ltl */
81219b2ee8SDavid du Colombier %left	OR
82219b2ee8SDavid du Colombier %left	AND
8300d97012SDavid du Colombier %left	ALWAYS EVENTUALLY		/* ltl */
8400d97012SDavid du Colombier %left	UNTIL WEAK_UNTIL RELEASE	/* ltl */
8500d97012SDavid du Colombier %right	NEXT				/* ltl */
86219b2ee8SDavid du Colombier %left	'|'
877dd7cddfSDavid du Colombier %left	'^'
88219b2ee8SDavid du Colombier %left	'&'
89219b2ee8SDavid du Colombier %left	EQ NE
90219b2ee8SDavid du Colombier %left	GT LT GE LE
91219b2ee8SDavid du Colombier %left	LSHIFT RSHIFT
92219b2ee8SDavid du Colombier %left	'+' '-'
93219b2ee8SDavid du Colombier %left	'*' '/' '%'
94219b2ee8SDavid du Colombier %left	INCR DECR
95219b2ee8SDavid du Colombier %right	'~' UMIN NEG
96219b2ee8SDavid du Colombier %left	DOT
97219b2ee8SDavid du Colombier %%
98219b2ee8SDavid du Colombier 
997dd7cddfSDavid du Colombier /** PROMELA Grammar Rules **/
100219b2ee8SDavid du Colombier 
1017dd7cddfSDavid du Colombier program	: units		{ yytext[0] = '\0'; }
102219b2ee8SDavid du Colombier 	;
103219b2ee8SDavid du Colombier 
104219b2ee8SDavid du Colombier units	: unit
105219b2ee8SDavid du Colombier 	| units unit
106219b2ee8SDavid du Colombier 	;
107219b2ee8SDavid du Colombier 
108219b2ee8SDavid du Colombier unit	: proc		/* proctype { }       */
109219b2ee8SDavid du Colombier 	| init		/* init { }           */
110219b2ee8SDavid du Colombier 	| claim		/* never claim        */
11100d97012SDavid du Colombier 	| ltl		/* ltl formula        */
1127dd7cddfSDavid du Colombier 	| events	/* event assertions   */
113219b2ee8SDavid du Colombier 	| one_decl	/* variables, chans   */
114219b2ee8SDavid du Colombier 	| utype		/* user defined types */
115312a1df1SDavid du Colombier 	| c_fcts	/* c functions etc.   */
1167dd7cddfSDavid du Colombier 	| ns		/* named sequence     */
117*de2caf28SDavid du Colombier 	| semi		/* optional separator */
118219b2ee8SDavid du Colombier 	| error
119219b2ee8SDavid du Colombier 	;
120219b2ee8SDavid du Colombier 
121*de2caf28SDavid du Colombier l_par	: '('		{ par_cnt++; }
122*de2caf28SDavid du Colombier 	;
123*de2caf28SDavid du Colombier 
124*de2caf28SDavid du Colombier r_par	: ')'		{ par_cnt--; }
125*de2caf28SDavid du Colombier 	;
126*de2caf28SDavid du Colombier 
127*de2caf28SDavid du Colombier 
128219b2ee8SDavid du Colombier proc	: inst		/* optional instantiator */
1297dd7cddfSDavid du Colombier 	  proctype NAME	{
130*de2caf28SDavid du Colombier 			  setptype(ZN, $3, PROCTYPE, ZN);
131219b2ee8SDavid du Colombier 			  setpname($3);
132219b2ee8SDavid du Colombier 			  context = $3->sym;
1337dd7cddfSDavid du Colombier 			  context->ini = $2; /* linenr and file */
134219b2ee8SDavid du Colombier 			  Expand_Ok++; /* expand struct names in decl */
1357dd7cddfSDavid du Colombier 			  has_ini = 0;
136219b2ee8SDavid du Colombier 			}
137*de2caf28SDavid du Colombier 	  l_par decl r_par	{ Expand_Ok--;
1387dd7cddfSDavid du Colombier 			  if (has_ini)
1397dd7cddfSDavid du Colombier 			  fatal("initializer in parameter list", (char *) 0);
1407dd7cddfSDavid du Colombier 			}
1417dd7cddfSDavid du Colombier 	  Opt_priority
1427dd7cddfSDavid du Colombier 	  Opt_enabler
1437dd7cddfSDavid du Colombier 	  body		{ ProcList *rl;
144219b2ee8SDavid du Colombier 			  if ($1 != ZN && $1->val > 0)
145219b2ee8SDavid du Colombier 			  {	int j;
146*de2caf28SDavid du Colombier 				rl = mk_rdy($3->sym, $6, $11->sq, $2->val, $10, A_PROC);
147219b2ee8SDavid du Colombier 			  	for (j = 0; j < $1->val; j++)
14800d97012SDavid du Colombier 				{	runnable(rl, $9?$9->val:1, 1);
1497dd7cddfSDavid du Colombier 					announce(":root:");
150*de2caf28SDavid du Colombier 				}
1517dd7cddfSDavid du Colombier 				if (dumptab) $3->sym->ini = $1;
15200d97012SDavid du Colombier 			  } else
153*de2caf28SDavid du Colombier 			  {	rl = mk_rdy($3->sym, $6, $11->sq, $2->val, $10, P_PROC);
15400d97012SDavid du Colombier 			  }
15500d97012SDavid du Colombier 			  if (rl && has_ini == 1) /* global initializations, unsafe */
15600d97012SDavid du Colombier 			  {	/* printf("proctype %s has initialized data\n",
15700d97012SDavid du Colombier 					$3->sym->name);
15800d97012SDavid du Colombier 				 */
15900d97012SDavid du Colombier 				rl->unsafe = 1;
160219b2ee8SDavid du Colombier 			  }
161219b2ee8SDavid du Colombier 			  context = ZS;
162219b2ee8SDavid du Colombier 			}
163219b2ee8SDavid du Colombier 	;
164219b2ee8SDavid du Colombier 
1657dd7cddfSDavid du Colombier proctype: PROCTYPE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 0; }
1667dd7cddfSDavid du Colombier 	| D_PROCTYPE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
1677dd7cddfSDavid du Colombier 	;
1687dd7cddfSDavid du Colombier 
169219b2ee8SDavid du Colombier inst	: /* empty */	{ $$ = ZN; }
170219b2ee8SDavid du Colombier 	| ACTIVE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
171*de2caf28SDavid du Colombier 	| ACTIVE '[' const_expr ']' {
172219b2ee8SDavid du Colombier 			  $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
173312a1df1SDavid du Colombier 			  if ($3->val > 255)
174312a1df1SDavid du Colombier 				non_fatal("max nr of processes is 255\n", "");
175219b2ee8SDavid du Colombier 			}
1767dd7cddfSDavid du Colombier 	| ACTIVE '[' NAME ']' {
1777dd7cddfSDavid du Colombier 			  $$ = nn(ZN,CONST,ZN,ZN);
1787dd7cddfSDavid du Colombier 			  $$->val = 0;
1797dd7cddfSDavid du Colombier 			  if (!$3->sym->type)
18000d97012SDavid du Colombier 				fatal("undeclared variable %s",
181312a1df1SDavid du Colombier 					$3->sym->name);
1827dd7cddfSDavid du Colombier 			  else if ($3->sym->ini->ntyp != CONST)
18300d97012SDavid du Colombier 				fatal("need constant initializer for %s\n",
1847dd7cddfSDavid du Colombier 					$3->sym->name);
1857dd7cddfSDavid du Colombier 			  else
1867dd7cddfSDavid du Colombier 				$$->val = $3->sym->ini->val;
1877dd7cddfSDavid du Colombier 			}
188219b2ee8SDavid du Colombier 	;
189219b2ee8SDavid du Colombier 
190219b2ee8SDavid du Colombier init	: INIT		{ context = $1->sym; }
1917dd7cddfSDavid du Colombier 	  Opt_priority
1927dd7cddfSDavid du Colombier 	  body		{ ProcList *rl;
193*de2caf28SDavid du Colombier 			  rl = mk_rdy(context, ZN, $4->sq, 0, ZN, I_PROC);
1947dd7cddfSDavid du Colombier 			  runnable(rl, $3?$3->val:1, 1);
1957dd7cddfSDavid du Colombier 			  announce(":root:");
196219b2ee8SDavid du Colombier 			  context = ZS;
197219b2ee8SDavid du Colombier         		}
198219b2ee8SDavid du Colombier 	;
199219b2ee8SDavid du Colombier 
20000d97012SDavid du Colombier ltl	: LTL optname2	{ ltl_mode = 1; ltl_name = $2->sym->name; }
20100d97012SDavid du Colombier 	  ltl_body	{ if ($4) ltl_list($2->sym->name, $4->sym->name);
202*de2caf28SDavid du Colombier 			  ltl_mode = 0; has_ltl = 1;
20300d97012SDavid du Colombier 			}
20400d97012SDavid du Colombier 	;
20500d97012SDavid du Colombier 
20600d97012SDavid du Colombier ltl_body: '{' full_expr OS '}' { $$ = ltl_to_string($2); }
20700d97012SDavid du Colombier 	| error		{ $$ = NULL; }
20800d97012SDavid du Colombier 	;
20900d97012SDavid du Colombier 
21000d97012SDavid du Colombier claim	: CLAIM	optname	{ if ($2 != ZN)
21100d97012SDavid du Colombier 			  {	$1->sym = $2->sym;	/* new 5.3.0 */
21200d97012SDavid du Colombier 			  }
21300d97012SDavid du Colombier 			  nclaims++;
21400d97012SDavid du Colombier 			  context = $1->sym;
21500d97012SDavid du Colombier 			  if (claimproc && !strcmp(claimproc, $1->sym->name))
21600d97012SDavid du Colombier 			  {	fatal("claim %s redefined", claimproc);
21700d97012SDavid du Colombier 			  }
218219b2ee8SDavid du Colombier 			  claimproc = $1->sym->name;
219219b2ee8SDavid du Colombier 			}
220*de2caf28SDavid du Colombier 	  body		{ (void) mk_rdy($1->sym, ZN, $4->sq, 0, ZN, N_CLAIM);
221219b2ee8SDavid du Colombier         		  context = ZS;
222219b2ee8SDavid du Colombier         		}
223219b2ee8SDavid du Colombier 	;
224219b2ee8SDavid du Colombier 
22500d97012SDavid du Colombier optname : /* empty */	{ char tb[32];
22600d97012SDavid du Colombier 			  memset(tb, 0, 32);
22700d97012SDavid du Colombier 			  sprintf(tb, "never_%d", nclaims);
22800d97012SDavid du Colombier 			  $$ = nn(ZN, NAME, ZN, ZN);
22900d97012SDavid du Colombier 			  $$->sym = lookup(tb);
23000d97012SDavid du Colombier 			}
23100d97012SDavid du Colombier 	| NAME		{ $$ = $1; }
23200d97012SDavid du Colombier 	;
23300d97012SDavid du Colombier 
23400d97012SDavid du Colombier optname2 : /* empty */ { char tb[32]; static int nltl = 0;
23500d97012SDavid du Colombier 			  memset(tb, 0, 32);
23600d97012SDavid du Colombier 			  sprintf(tb, "ltl_%d", nltl++);
23700d97012SDavid du Colombier 			  $$ = nn(ZN, NAME, ZN, ZN);
23800d97012SDavid du Colombier 			  $$->sym = lookup(tb);
23900d97012SDavid du Colombier 			}
24000d97012SDavid du Colombier 	| NAME		{ $$ = $1; }
24100d97012SDavid du Colombier 	;
24200d97012SDavid du Colombier 
2437dd7cddfSDavid du Colombier events : TRACE		{ context = $1->sym;
2447dd7cddfSDavid du Colombier 			  if (eventmap)
2457dd7cddfSDavid du Colombier 				non_fatal("trace %s redefined", eventmap);
2467dd7cddfSDavid du Colombier 			  eventmap = $1->sym->name;
2477dd7cddfSDavid du Colombier 			  inEventMap++;
2487dd7cddfSDavid du Colombier 			}
24900d97012SDavid du Colombier 	  body		{
25000d97012SDavid du Colombier 			  if (strcmp($1->sym->name, ":trace:") == 0)
251*de2caf28SDavid du Colombier 			  {	(void) mk_rdy($1->sym, ZN, $3->sq, 0, ZN, E_TRACE);
25200d97012SDavid du Colombier 			  } else
253*de2caf28SDavid du Colombier 			  {	(void) mk_rdy($1->sym, ZN, $3->sq, 0, ZN, N_TRACE);
25400d97012SDavid du Colombier 			  }
2557dd7cddfSDavid du Colombier         		  context = ZS;
2567dd7cddfSDavid du Colombier 			  inEventMap--;
2577dd7cddfSDavid du Colombier 			}
258219b2ee8SDavid du Colombier 	;
2597dd7cddfSDavid du Colombier 
260*de2caf28SDavid du Colombier utype	: TYPEDEF NAME '{' 	{  if (context)
261*de2caf28SDavid du Colombier 				   { fatal("typedef %s must be global",
262219b2ee8SDavid du Colombier 					$2->sym->name);
263219b2ee8SDavid du Colombier 				   }
264*de2caf28SDavid du Colombier 				   owner = $2->sym;
265*de2caf28SDavid du Colombier 				   in_seq = $1->ln;
266*de2caf28SDavid du Colombier 				}
267*de2caf28SDavid du Colombier 	  decl_lst '}'		{ setuname($5);
268*de2caf28SDavid du Colombier 				  owner = ZS;
269*de2caf28SDavid du Colombier 				  in_seq = 0;
270*de2caf28SDavid du Colombier 				}
271219b2ee8SDavid du Colombier 	;
272219b2ee8SDavid du Colombier 
2737dd7cddfSDavid du Colombier nm	: NAME			{ $$ = $1; }
2747dd7cddfSDavid du Colombier 	| INAME			{ $$ = $1;
2757dd7cddfSDavid du Colombier 				  if (IArgs)
2767dd7cddfSDavid du Colombier 				  fatal("invalid use of '%s'", $1->sym->name);
2777dd7cddfSDavid du Colombier 				}
2787dd7cddfSDavid du Colombier 	;
2797dd7cddfSDavid du Colombier 
280*de2caf28SDavid du Colombier ns	: INLINE nm l_par		{ NamesNotAdded++; }
281*de2caf28SDavid du Colombier 	  args r_par		{ prep_inline($2->sym, $5);
282312a1df1SDavid du Colombier 				  NamesNotAdded--;
283312a1df1SDavid du Colombier 				}
284312a1df1SDavid du Colombier 	;
285312a1df1SDavid du Colombier 
286312a1df1SDavid du Colombier c_fcts	: ccode			{ /* leaves pseudo-inlines with sym of
287312a1df1SDavid du Colombier 				   * type CODE_FRAG or CODE_DECL in global context
288312a1df1SDavid du Colombier 				   */
289312a1df1SDavid du Colombier 				}
290312a1df1SDavid du Colombier 	| cstate
291312a1df1SDavid du Colombier 	;
292312a1df1SDavid du Colombier 
293312a1df1SDavid du Colombier cstate	: C_STATE STRING STRING	{
294312a1df1SDavid du Colombier 				  c_state($2->sym, $3->sym, ZS);
295312a1df1SDavid du Colombier 				  has_code = has_state = 1;
296312a1df1SDavid du Colombier 				}
297312a1df1SDavid du Colombier 	| C_TRACK STRING STRING {
298312a1df1SDavid du Colombier 				  c_track($2->sym, $3->sym, ZS);
299312a1df1SDavid du Colombier 				  has_code = has_state = 1;
300312a1df1SDavid du Colombier 				}
301312a1df1SDavid du Colombier 	| C_STATE STRING STRING	STRING {
302312a1df1SDavid du Colombier 				  c_state($2->sym, $3->sym, $4->sym);
303312a1df1SDavid du Colombier 				  has_code = has_state = 1;
304312a1df1SDavid du Colombier 				}
305312a1df1SDavid du Colombier 	| C_TRACK STRING STRING STRING {
306312a1df1SDavid du Colombier 				  c_track($2->sym, $3->sym, $4->sym);
307312a1df1SDavid du Colombier 				  has_code = has_state = 1;
308312a1df1SDavid du Colombier 				}
309312a1df1SDavid du Colombier 	;
310312a1df1SDavid du Colombier 
311312a1df1SDavid du Colombier ccode	: C_CODE		{ Symbol *s;
312312a1df1SDavid du Colombier 				  NamesNotAdded++;
313312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
314312a1df1SDavid du Colombier 				  NamesNotAdded--;
315312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_CODE, ZN, ZN);
316312a1df1SDavid du Colombier 				  $$->sym = s;
317*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
318*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
319312a1df1SDavid du Colombier 				  has_code = 1;
320312a1df1SDavid du Colombier 				}
321312a1df1SDavid du Colombier 	| C_DECL		{ Symbol *s;
322312a1df1SDavid du Colombier 				  NamesNotAdded++;
323312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
324312a1df1SDavid du Colombier 				  NamesNotAdded--;
325312a1df1SDavid du Colombier 				  s->type = CODE_DECL;
326312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_CODE, ZN, ZN);
327312a1df1SDavid du Colombier 				  $$->sym = s;
328*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
329*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
330312a1df1SDavid du Colombier 				  has_code = 1;
331312a1df1SDavid du Colombier 				}
332312a1df1SDavid du Colombier 	;
333312a1df1SDavid du Colombier cexpr	: C_EXPR		{ Symbol *s;
334312a1df1SDavid du Colombier 				  NamesNotAdded++;
335312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
336*de2caf28SDavid du Colombier /* if context is 0 this was inside an ltl formula
337*de2caf28SDavid du Colombier    mark the last inline added to seqnames */
338*de2caf28SDavid du Colombier 				  if (!context)
339*de2caf28SDavid du Colombier 				  {	mark_last();
340*de2caf28SDavid du Colombier 				  }
341312a1df1SDavid du Colombier 				  NamesNotAdded--;
342312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_EXPR, ZN, ZN);
343312a1df1SDavid du Colombier 				  $$->sym = s;
344*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
345*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
346312a1df1SDavid du Colombier 				  no_side_effects(s->name);
347312a1df1SDavid du Colombier 				  has_code = 1;
348312a1df1SDavid du Colombier 				}
3497dd7cddfSDavid du Colombier 	;
3507dd7cddfSDavid du Colombier 
351*de2caf28SDavid du Colombier body	: '{'			{ open_seq(1); in_seq = $1->ln; }
352219b2ee8SDavid du Colombier           sequence OS		{ add_seq(Stop); }
353*de2caf28SDavid du Colombier           '}'			{ $$->sq = close_seq(0); in_seq = 0;
35400d97012SDavid du Colombier 				  if (scope_level != 0)
35500d97012SDavid du Colombier 				  {	non_fatal("missing '}' ?", 0);
35600d97012SDavid du Colombier 					scope_level = 0;
35700d97012SDavid du Colombier 				  }
35800d97012SDavid du Colombier 				}
359219b2ee8SDavid du Colombier 	;
360219b2ee8SDavid du Colombier 
361219b2ee8SDavid du Colombier sequence: step			{ if ($1) add_seq($1); }
362219b2ee8SDavid du Colombier 	| sequence MS step	{ if ($3) add_seq($3); }
363219b2ee8SDavid du Colombier 	;
364219b2ee8SDavid du Colombier 
365219b2ee8SDavid du Colombier step    : one_decl		{ $$ = ZN; }
366219b2ee8SDavid du Colombier 	| XU vref_lst		{ setxus($2, $1->val); $$ = ZN; }
367312a1df1SDavid du Colombier 	| NAME ':' one_decl	{ fatal("label preceding declaration,", (char *)0); }
368*de2caf28SDavid du Colombier 	| NAME ':' XU		{ fatal("label preceding xr/xs claim,", 0); }
369219b2ee8SDavid du Colombier 	| stmnt			{ $$ = $1; }
370*de2caf28SDavid du Colombier 	| stmnt UNLESS		{ if ($1->ntyp == DO) { safe_break(); } }
371*de2caf28SDavid du Colombier 	  stmnt			{ if ($1->ntyp == DO) { restore_break(); }
372*de2caf28SDavid du Colombier 				  $$ = do_unless($1, $4);
373*de2caf28SDavid du Colombier 				}
374*de2caf28SDavid du Colombier 	| error
375219b2ee8SDavid du Colombier 	;
376219b2ee8SDavid du Colombier 
377219b2ee8SDavid du Colombier vis	: /* empty */		{ $$ = ZN; }
378219b2ee8SDavid du Colombier 	| HIDDEN		{ $$ = $1; }
3797dd7cddfSDavid du Colombier 	| SHOW			{ $$ = $1; }
3807dd7cddfSDavid du Colombier 	| ISLOCAL		{ $$ = $1; }
3817dd7cddfSDavid du Colombier 	;
3827dd7cddfSDavid du Colombier 
383*de2caf28SDavid du Colombier asgn	: /* empty */		{ $$ = ZN; }
384*de2caf28SDavid du Colombier 	| ':' NAME ASGN		{ $$ = $2; /* mtype decl */ }
385*de2caf28SDavid du Colombier 	| ASGN			{ $$ = ZN; /* mtype decl */ }
386219b2ee8SDavid du Colombier 	;
387219b2ee8SDavid du Colombier 
388*de2caf28SDavid du Colombier osubt	: /* empty */		{ $$ = ZN; }
389*de2caf28SDavid du Colombier 	| ':' NAME		{ $$ = $2; }
390*de2caf28SDavid du Colombier 	;
391*de2caf28SDavid du Colombier 
392*de2caf28SDavid du Colombier one_decl: vis TYPE osubt var_list { setptype($3, $4, $2->val, $1);
393*de2caf28SDavid du Colombier 				  $4->val = $2->val;
394*de2caf28SDavid du Colombier 				  $$ = $4;
39500d97012SDavid du Colombier 				}
396219b2ee8SDavid du Colombier 	| vis UNAME var_list	{ setutype($3, $2->sym, $1);
397219b2ee8SDavid du Colombier 				  $$ = expand($3, Expand_Ok);
398219b2ee8SDavid du Colombier 				}
3997dd7cddfSDavid du Colombier 	| vis TYPE asgn '{' nlst '}' {
4007dd7cddfSDavid du Colombier 				  if ($2->val != MTYPE)
4017dd7cddfSDavid du Colombier 					fatal("malformed declaration", 0);
402*de2caf28SDavid du Colombier 				  setmtype($3, $5);
4037dd7cddfSDavid du Colombier 				  if ($1)
4047dd7cddfSDavid du Colombier 					non_fatal("cannot %s mtype (ignored)",
4057dd7cddfSDavid du Colombier 						$1->sym->name);
4067dd7cddfSDavid du Colombier 				  if (context != ZS)
4077dd7cddfSDavid du Colombier 					fatal("mtype declaration must be global", 0);
4087dd7cddfSDavid du Colombier 				}
409219b2ee8SDavid du Colombier 	;
410219b2ee8SDavid du Colombier 
411219b2ee8SDavid du Colombier decl_lst: one_decl       	{ $$ = nn(ZN, ',', $1, ZN); }
412219b2ee8SDavid du Colombier 	| one_decl SEMI
413219b2ee8SDavid du Colombier 	  decl_lst		{ $$ = nn(ZN, ',', $1, $3); }
414219b2ee8SDavid du Colombier 	;
415219b2ee8SDavid du Colombier 
416219b2ee8SDavid du Colombier decl    : /* empty */		{ $$ = ZN; }
417219b2ee8SDavid du Colombier 	| decl_lst      	{ $$ = $1; }
418219b2ee8SDavid du Colombier 	;
419219b2ee8SDavid du Colombier 
420219b2ee8SDavid du Colombier vref_lst: varref		{ $$ = nn($1, XU, $1, ZN); }
421219b2ee8SDavid du Colombier 	| varref ',' vref_lst	{ $$ = nn($1, XU, $1, $3); }
422219b2ee8SDavid du Colombier 	;
423219b2ee8SDavid du Colombier 
424219b2ee8SDavid du Colombier var_list: ivar           	{ $$ = nn($1, TYPE, ZN, ZN); }
425219b2ee8SDavid du Colombier 	| ivar ',' var_list	{ $$ = nn($1, TYPE, ZN, $3); }
426219b2ee8SDavid du Colombier 	;
427219b2ee8SDavid du Colombier 
428*de2caf28SDavid du Colombier c_list	: CONST			{ $1->ntyp = CONST; $$ = $1; }
429*de2caf28SDavid du Colombier 	| CONST ',' c_list	{ $1->ntyp = CONST; $$ = nn($1, ',', $1, $3); }
430*de2caf28SDavid du Colombier 	;
431*de2caf28SDavid du Colombier 
4327dd7cddfSDavid du Colombier ivar    : vardcl           	{ $$ = $1;
4337dd7cddfSDavid du Colombier 				  $1->sym->ini = nn(ZN,CONST,ZN,ZN);
4347dd7cddfSDavid du Colombier 				  $1->sym->ini->val = 0;
435*de2caf28SDavid du Colombier 				  if (!initialization_ok)
436*de2caf28SDavid du Colombier 				  {	Lextok *zx, *xz;
437*de2caf28SDavid du Colombier 					zx = nn(ZN, NAME, ZN, ZN);
438*de2caf28SDavid du Colombier 					zx->sym = $1->sym;
439*de2caf28SDavid du Colombier 					xz = nn(zx, ASGN, zx, $1->sym->ini);
440*de2caf28SDavid du Colombier 					keep_track_off(xz);
441*de2caf28SDavid du Colombier 					/* make sure zx doesnt turn out to be a STRUCT later */
442*de2caf28SDavid du Colombier 					add_seq(xz);
4437dd7cddfSDavid du Colombier 				  }
444*de2caf28SDavid du Colombier 				}
445*de2caf28SDavid du Colombier 	| vardcl ASGN '{' c_list '}'	{	/* array initialization */
446*de2caf28SDavid du Colombier 				  if (!$1->sym->isarray)
447*de2caf28SDavid du Colombier 					fatal("%s must be an array", $1->sym->name);
448*de2caf28SDavid du Colombier 				  $$ = $1;
449*de2caf28SDavid du Colombier 				  $1->sym->ini = $4;
450*de2caf28SDavid du Colombier 				  has_ini = 1;
451*de2caf28SDavid du Colombier 				  $1->sym->hidden |= (4|8);	/* conservative */
452*de2caf28SDavid du Colombier 				  if (!initialization_ok)
453*de2caf28SDavid du Colombier 				  {	Lextok *zx = nn(ZN, NAME, ZN, ZN);
454*de2caf28SDavid du Colombier 					zx->sym = $1->sym;
455*de2caf28SDavid du Colombier 					add_seq(nn(zx, ASGN, zx, $4));
456*de2caf28SDavid du Colombier 				  }
457*de2caf28SDavid du Colombier 				}
458*de2caf28SDavid du Colombier 	| vardcl ASGN expr   	{ $$ = $1;	/* initialized scalar */
45900d97012SDavid du Colombier 				  $1->sym->ini = $3;
46000d97012SDavid du Colombier 				  if ($3->ntyp == CONST
46100d97012SDavid du Colombier 				  || ($3->ntyp == NAME && $3->sym->context))
46200d97012SDavid du Colombier 				  {	has_ini = 2; /* local init */
46300d97012SDavid du Colombier 				  } else
46400d97012SDavid du Colombier 				  {	has_ini = 1; /* possibly global */
46500d97012SDavid du Colombier 				  }
466*de2caf28SDavid du Colombier 				  trackvar($1, $3);
467*de2caf28SDavid du Colombier 				  if (any_oper($3, RUN))
468*de2caf28SDavid du Colombier 				  {	fatal("cannot use 'run' in var init, saw", (char *) 0);
469*de2caf28SDavid du Colombier 				  }
470*de2caf28SDavid du Colombier 				  nochan_manip($1, $3, 0);
47100d97012SDavid du Colombier 				  no_internals($1);
472*de2caf28SDavid du Colombier 				  if (!initialization_ok)
473*de2caf28SDavid du Colombier 				  {	Lextok *zx = nn(ZN, NAME, ZN, ZN);
474*de2caf28SDavid du Colombier 					zx->sym = $1->sym;
475*de2caf28SDavid du Colombier 					add_seq(nn(zx, ASGN, zx, $3));
476*de2caf28SDavid du Colombier 					$1->sym->ini = 0;	/* Patrick Trentlin */
47700d97012SDavid du Colombier 				  }
4787dd7cddfSDavid du Colombier 				}
479*de2caf28SDavid du Colombier 	| vardcl ASGN ch_init	{ $1->sym->ini = $3;	/* channel declaration */
4807dd7cddfSDavid du Colombier 				  $$ = $1; has_ini = 1;
481*de2caf28SDavid du Colombier 				  if (!initialization_ok)
48200d97012SDavid du Colombier 				  {	non_fatal(PART1 "'%s'" PART2, $1->sym->name);
48300d97012SDavid du Colombier 				  }
4847dd7cddfSDavid du Colombier 				}
485219b2ee8SDavid du Colombier 	;
486219b2ee8SDavid du Colombier 
487*de2caf28SDavid du Colombier ch_init : '[' const_expr ']' OF
48800d97012SDavid du Colombier 	  '{' typ_list '}'	{ if ($2->val)
48900d97012SDavid du Colombier 					u_async++;
49000d97012SDavid du Colombier 				  else
49100d97012SDavid du Colombier 					u_sync++;
492219b2ee8SDavid du Colombier         			  {	int i = cnt_mpars($6);
493219b2ee8SDavid du Colombier 					Mpars = max(Mpars, i);
494219b2ee8SDavid du Colombier 				  }
495219b2ee8SDavid du Colombier         			  $$ = nn(ZN, CHAN, ZN, $6);
496219b2ee8SDavid du Colombier 				  $$->val = $2->val;
497*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
498*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
499219b2ee8SDavid du Colombier         			}
500219b2ee8SDavid du Colombier 	;
501219b2ee8SDavid du Colombier 
502219b2ee8SDavid du Colombier vardcl  : NAME  		{ $1->sym->nel = 1; $$ = $1; }
5037dd7cddfSDavid du Colombier 	| NAME ':' CONST	{ $1->sym->nbits = $3->val;
504312a1df1SDavid du Colombier 				  if ($3->val >= 8*sizeof(long))
505312a1df1SDavid du Colombier 				  {	non_fatal("width-field %s too large",
506312a1df1SDavid du Colombier 						$1->sym->name);
507312a1df1SDavid du Colombier 					$3->val = 8*sizeof(long)-1;
508312a1df1SDavid du Colombier 				  }
5097dd7cddfSDavid du Colombier 				  $1->sym->nel = 1; $$ = $1;
5107dd7cddfSDavid du Colombier 				}
511*de2caf28SDavid du Colombier 	| NAME '[' const_expr ']'	{ $1->sym->nel = $3->val; $1->sym->isarray = 1; $$ = $1; }
512*de2caf28SDavid du Colombier 	| NAME '[' NAME ']'	{	/* make an exception for an initialized scalars */
513*de2caf28SDavid du Colombier 					$$ = nn(ZN, CONST, ZN, ZN);
514*de2caf28SDavid du Colombier 					fprintf(stderr, "spin: %s:%d, warning: '%s' in array bound ",
515*de2caf28SDavid du Colombier 						$1->fn->name, $1->ln, $3->sym->name);
516*de2caf28SDavid du Colombier 					if ($3->sym->ini
517*de2caf28SDavid du Colombier 					&&  $3->sym->ini->val > 0)
518*de2caf28SDavid du Colombier 					{	fprintf(stderr, "evaluated as %d\n", $3->sym->ini->val);
519*de2caf28SDavid du Colombier 						$$->val = $3->sym->ini->val;
520*de2caf28SDavid du Colombier 					} else
521*de2caf28SDavid du Colombier 					{	fprintf(stderr, "evaluated as 1 by default (to avoid zero)\n");
522*de2caf28SDavid du Colombier 						$$->val = 1;
523*de2caf28SDavid du Colombier 					}
524*de2caf28SDavid du Colombier 					$1->sym->nel = $$->val;
525*de2caf28SDavid du Colombier 					$1->sym->isarray = 1;
526*de2caf28SDavid du Colombier 					$$ = $1;
527*de2caf28SDavid du Colombier 				}
528219b2ee8SDavid du Colombier 	;
529219b2ee8SDavid du Colombier 
530219b2ee8SDavid du Colombier varref	: cmpnd			{ $$ = mk_explicit($1, Expand_Ok, NAME); }
531219b2ee8SDavid du Colombier 	;
532219b2ee8SDavid du Colombier 
53300d97012SDavid du Colombier pfld	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
53400d97012SDavid du Colombier 				  if ($1->sym->isarray && !in_for)
53500d97012SDavid du Colombier 				  {	non_fatal("missing array index for '%s'",
53600d97012SDavid du Colombier 						$1->sym->name);
53700d97012SDavid du Colombier 				  }
53800d97012SDavid du Colombier 				}
539219b2ee8SDavid du Colombier 	| NAME			{ owner = ZS; }
540219b2ee8SDavid du Colombier 	  '[' expr ']'		{ $$ = nn($1, NAME, $4, ZN); }
541219b2ee8SDavid du Colombier 	;
542219b2ee8SDavid du Colombier 
543219b2ee8SDavid du Colombier cmpnd	: pfld			{ Embedded++;
544219b2ee8SDavid du Colombier 				  if ($1->sym->type == STRUCT)
545219b2ee8SDavid du Colombier 					owner = $1->sym->Snm;
546219b2ee8SDavid du Colombier 				}
547219b2ee8SDavid du Colombier 	  sfld			{ $$ = $1; $$->rgt = $3;
548219b2ee8SDavid du Colombier 				  if ($3 && $1->sym->type != STRUCT)
549219b2ee8SDavid du Colombier 					$1->sym->type = STRUCT;
5507dd7cddfSDavid du Colombier 				  Embedded--;
5517dd7cddfSDavid du Colombier 				  if (!Embedded && !NamesNotAdded
5527dd7cddfSDavid du Colombier 				  &&  !$1->sym->type)
55300d97012SDavid du Colombier 				   fatal("undeclared variable: %s",
554219b2ee8SDavid du Colombier 						$1->sym->name);
5557dd7cddfSDavid du Colombier 				  if ($3) validref($1, $3->lft);
556219b2ee8SDavid du Colombier 				  owner = ZS;
557219b2ee8SDavid du Colombier 				}
558219b2ee8SDavid du Colombier 	;
559219b2ee8SDavid du Colombier 
560219b2ee8SDavid du Colombier sfld	: /* empty */		{ $$ = ZN; }
561219b2ee8SDavid du Colombier 	| '.' cmpnd %prec DOT	{ $$ = nn(ZN, '.', $2, ZN); }
562219b2ee8SDavid du Colombier 	;
563219b2ee8SDavid du Colombier 
56400d97012SDavid du Colombier stmnt	: Special		{ $$ = $1; initialization_ok = 0; }
56500d97012SDavid du Colombier 	| Stmnt			{ $$ = $1; initialization_ok = 0;
566*de2caf28SDavid du Colombier 				  if (inEventMap) non_fatal("not an event", (char *)0);
5677dd7cddfSDavid du Colombier 				}
5687dd7cddfSDavid du Colombier 	;
5697dd7cddfSDavid du Colombier 
570*de2caf28SDavid du Colombier for_pre : FOR l_par		{ in_for = 1; }
571*de2caf28SDavid du Colombier 	  varref		{ trapwonly($4 /*, "for" */);
572*de2caf28SDavid du Colombier 				  pushbreak(); /* moved up */
573*de2caf28SDavid du Colombier 				  $$ = $4;
574*de2caf28SDavid du Colombier 				}
57500d97012SDavid du Colombier 	;
57600d97012SDavid du Colombier 
577*de2caf28SDavid du Colombier for_post: '{' sequence OS '}'
578*de2caf28SDavid du Colombier 	| SEMI '{' sequence OS '}'
57900d97012SDavid du Colombier 
5807dd7cddfSDavid du Colombier Special : varref RCV		{ Expand_Ok++; }
581312a1df1SDavid du Colombier 	  rargs			{ Expand_Ok--; has_io++;
5827dd7cddfSDavid du Colombier 				  $$ = nn($1,  'r', $1, $4);
5837dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'R');
5847dd7cddfSDavid du Colombier 				}
5857dd7cddfSDavid du Colombier 	| varref SND		{ Expand_Ok++; }
586312a1df1SDavid du Colombier 	  margs			{ Expand_Ok--; has_io++;
5877dd7cddfSDavid du Colombier 				  $$ = nn($1, 's', $1, $4);
5887dd7cddfSDavid du Colombier 				  $$->val=0; trackchanuse($4, ZN, 'S');
589f3793cddSDavid du Colombier 				  any_runs($4);
5907dd7cddfSDavid du Colombier 				}
591*de2caf28SDavid du Colombier 	| for_pre ':' expr DOTDOT expr r_par	{
59200d97012SDavid du Colombier 				  for_setup($1, $3, $5); in_for = 0;
59300d97012SDavid du Colombier 				}
59400d97012SDavid du Colombier 	  for_post		{ $$ = for_body($1, 1);
59500d97012SDavid du Colombier 				}
596*de2caf28SDavid du Colombier 	| for_pre IN varref r_par	{ $$ = for_index($1, $3); in_for = 0;
59700d97012SDavid du Colombier 				}
59800d97012SDavid du Colombier 	  for_post		{ $$ = for_body($5, 1);
59900d97012SDavid du Colombier 				}
600*de2caf28SDavid du Colombier 	| SELECT l_par varref ':' expr DOTDOT expr r_par {
601*de2caf28SDavid du Colombier 				  trapwonly($3 /*, "select" */);
60200d97012SDavid du Colombier 				  $$ = sel_index($3, $5, $7);
60300d97012SDavid du Colombier 				}
6047dd7cddfSDavid du Colombier 	| IF options FI 	{ $$ = nn($1, IF, ZN, ZN);
6057dd7cddfSDavid du Colombier         			  $$->sl = $2->sl;
606*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
607*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
6087dd7cddfSDavid du Colombier 				  prune_opts($$);
6097dd7cddfSDavid du Colombier         			}
6107dd7cddfSDavid du Colombier 	| DO    		{ pushbreak(); }
6117dd7cddfSDavid du Colombier           options OD    	{ $$ = nn($1, DO, ZN, ZN);
6127dd7cddfSDavid du Colombier         			  $$->sl = $3->sl;
613*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
614*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
6157dd7cddfSDavid du Colombier 				  prune_opts($$);
6167dd7cddfSDavid du Colombier         			}
6177dd7cddfSDavid du Colombier 	| BREAK  		{ $$ = nn(ZN, GOTO, ZN, ZN);
6187dd7cddfSDavid du Colombier 				  $$->sym = break_dest();
6197dd7cddfSDavid du Colombier 				}
6207dd7cddfSDavid du Colombier 	| GOTO NAME		{ $$ = nn($2, GOTO, ZN, ZN);
6217dd7cddfSDavid du Colombier 				  if ($2->sym->type != 0
6227dd7cddfSDavid du Colombier 				  &&  $2->sym->type != LABEL) {
6237dd7cddfSDavid du Colombier 				  	non_fatal("bad label-name %s",
6247dd7cddfSDavid du Colombier 					$2->sym->name);
6257dd7cddfSDavid du Colombier 				  }
6267dd7cddfSDavid du Colombier 				  $2->sym->type = LABEL;
6277dd7cddfSDavid du Colombier 				}
6287dd7cddfSDavid du Colombier 	| NAME ':' stmnt	{ $$ = nn($1, ':',$3, ZN);
6297dd7cddfSDavid du Colombier 				  if ($1->sym->type != 0
6307dd7cddfSDavid du Colombier 				  &&  $1->sym->type != LABEL) {
6317dd7cddfSDavid du Colombier 				  	non_fatal("bad label-name %s",
6327dd7cddfSDavid du Colombier 					$1->sym->name);
6337dd7cddfSDavid du Colombier 				  }
6347dd7cddfSDavid du Colombier 				  $1->sym->type = LABEL;
6357dd7cddfSDavid du Colombier 				}
636*de2caf28SDavid du Colombier 	| NAME ':'		{ $$ = nn($1, ':',ZN,ZN);
637*de2caf28SDavid du Colombier 				  if ($1->sym->type != 0
638*de2caf28SDavid du Colombier 				  &&  $1->sym->type != LABEL) {
639*de2caf28SDavid du Colombier 				  	non_fatal("bad label-name %s",
640*de2caf28SDavid du Colombier 					$1->sym->name);
641*de2caf28SDavid du Colombier 				  }
642*de2caf28SDavid du Colombier 				  $$->lft = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
643*de2caf28SDavid du Colombier 				  $$->lft->lft->val = 1; /* skip */
644*de2caf28SDavid du Colombier 				  $1->sym->type = LABEL;
645*de2caf28SDavid du Colombier 				}
646*de2caf28SDavid du Colombier 	| error			{ $$ = nn(ZN, 'c', nn(ZN,CONST,ZN,ZN), ZN);
647*de2caf28SDavid du Colombier 				  $$->lft->val = 1; /* skip */
648*de2caf28SDavid du Colombier 				}
6497dd7cddfSDavid du Colombier 	;
6507dd7cddfSDavid du Colombier 
651*de2caf28SDavid du Colombier Stmnt	: varref ASGN full_expr	{ $$ = nn($1, ASGN, $1, $3);	/* assignment */
6527dd7cddfSDavid du Colombier 				  trackvar($1, $3);
6537dd7cddfSDavid du Colombier 				  nochan_manip($1, $3, 0);
654f3793cddSDavid du Colombier 				  no_internals($1);
6557dd7cddfSDavid du Colombier 				}
656219b2ee8SDavid du Colombier 	| varref INCR		{ $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
657219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  '+', $1, $$);
658219b2ee8SDavid du Colombier 				  $$ = nn($1, ASGN, $1, $$);
6597dd7cddfSDavid du Colombier 				  trackvar($1, $1);
660f3793cddSDavid du Colombier 				  no_internals($1);
6617dd7cddfSDavid du Colombier 				  if ($1->sym->type == CHAN)
6627dd7cddfSDavid du Colombier 				   fatal("arithmetic on chan", (char *)0);
663219b2ee8SDavid du Colombier 				}
664219b2ee8SDavid du Colombier 	| varref DECR		{ $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
665219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  '-', $1, $$);
666219b2ee8SDavid du Colombier 				  $$ = nn($1, ASGN, $1, $$);
6677dd7cddfSDavid du Colombier 				  trackvar($1, $1);
668f3793cddSDavid du Colombier 				  no_internals($1);
6697dd7cddfSDavid du Colombier 				  if ($1->sym->type == CHAN)
6707dd7cddfSDavid du Colombier 				   fatal("arithmetic on chan id's", (char *)0);
671219b2ee8SDavid du Colombier 				}
672*de2caf28SDavid du Colombier 	| SET_P l_par two_args r_par	{ $$ = nn(ZN, SET_P, $3, ZN); has_priority++; }
673*de2caf28SDavid du Colombier 	| PRINT	l_par STRING	{ realread = 0; }
674*de2caf28SDavid du Colombier 	  prargs r_par		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
675*de2caf28SDavid du Colombier 	| PRINTM l_par varref r_par	{ $$ = nn(ZN, PRINTM, $3, ZN); }
676*de2caf28SDavid du Colombier 	| PRINTM l_par CONST r_par	{ $$ = nn(ZN, PRINTM, $3, ZN); }
677312a1df1SDavid du Colombier 	| ASSERT full_expr    	{ $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
678312a1df1SDavid du Colombier 	| ccode			{ $$ = $1; }
679219b2ee8SDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
680312a1df1SDavid du Colombier 	  rargs			{ Expand_Ok--; has_io++;
681219b2ee8SDavid du Colombier 				  $$ = nn($1,  'r', $1, $4);
682219b2ee8SDavid du Colombier 				  $$->val = has_random = 1;
6837dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'R');
6847dd7cddfSDavid du Colombier 				}
6857dd7cddfSDavid du Colombier 	| varref RCV		{ Expand_Ok++; }
686312a1df1SDavid du Colombier 	  LT rargs GT		{ Expand_Ok--; has_io++;
6877dd7cddfSDavid du Colombier 				  $$ = nn($1, 'r', $1, $5);
6887dd7cddfSDavid du Colombier 				  $$->val = 2;	/* fifo poll */
6897dd7cddfSDavid du Colombier 				  trackchanuse($5, ZN, 'R');
6907dd7cddfSDavid du Colombier 				}
6917dd7cddfSDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
692312a1df1SDavid du Colombier 	  LT rargs GT		{ Expand_Ok--; has_io++;	/* rrcv poll */
6937dd7cddfSDavid du Colombier 				  $$ = nn($1, 'r', $1, $5);
6947dd7cddfSDavid du Colombier 				  $$->val = 3; has_random = 1;
6957dd7cddfSDavid du Colombier 				  trackchanuse($5, ZN, 'R');
696219b2ee8SDavid du Colombier 				}
697219b2ee8SDavid du Colombier 	| varref O_SND		{ Expand_Ok++; }
698312a1df1SDavid du Colombier 	  margs			{ Expand_Ok--; has_io++;
699219b2ee8SDavid du Colombier 				  $$ = nn($1, 's', $1, $4);
700219b2ee8SDavid du Colombier 				  $$->val = has_sorted = 1;
7017dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'S');
702f3793cddSDavid du Colombier 				  any_runs($4);
703219b2ee8SDavid du Colombier 				}
704312a1df1SDavid du Colombier 	| full_expr		{ $$ = nn(ZN, 'c', $1, ZN); count_runs($$); }
705219b2ee8SDavid du Colombier 	| ELSE  		{ $$ = nn(ZN,ELSE,ZN,ZN);
706219b2ee8SDavid du Colombier 				}
707219b2ee8SDavid du Colombier 	| ATOMIC   '{'   	{ open_seq(0); }
708219b2ee8SDavid du Colombier           sequence OS '}'   	{ $$ = nn($1, ATOMIC, ZN, ZN);
709219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(3), 0);
710*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
711*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
712219b2ee8SDavid du Colombier 				  make_atomic($$->sl->this, 0);
713219b2ee8SDavid du Colombier         			}
71400d97012SDavid du Colombier 	| D_STEP '{'		{ open_seq(0);
71500d97012SDavid du Colombier 				  rem_Seq();
71600d97012SDavid du Colombier 				}
717219b2ee8SDavid du Colombier           sequence OS '}'   	{ $$ = nn($1, D_STEP, ZN, ZN);
718219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(4), 0);
719*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
720*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
721219b2ee8SDavid du Colombier         			  make_atomic($$->sl->this, D_ATOM);
722219b2ee8SDavid du Colombier 				  unrem_Seq();
723219b2ee8SDavid du Colombier         			}
724219b2ee8SDavid du Colombier 	| '{'			{ open_seq(0); }
725219b2ee8SDavid du Colombier 	  sequence OS '}'	{ $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
726219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(5), 0);
727*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
728*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
729219b2ee8SDavid du Colombier         			}
7307dd7cddfSDavid du Colombier 	| INAME			{ IArgs++; }
731*de2caf28SDavid du Colombier 	  l_par args r_par	{ initialization_ok = 0;
732*de2caf28SDavid du Colombier 				  pickup_inline($1->sym, $4, ZN);
733*de2caf28SDavid du Colombier 				  IArgs--;
734*de2caf28SDavid du Colombier 				}
7357dd7cddfSDavid du Colombier 	  Stmnt			{ $$ = $7; }
736*de2caf28SDavid du Colombier 
737*de2caf28SDavid du Colombier 	| varref ASGN INAME	{ IArgs++; /* inline call */ }
738*de2caf28SDavid du Colombier 	  l_par args r_par	{ initialization_ok = 0;
739*de2caf28SDavid du Colombier 				  pickup_inline($3->sym, $6, $1);
740*de2caf28SDavid du Colombier 				  IArgs--;
741*de2caf28SDavid du Colombier 				}
742*de2caf28SDavid du Colombier 	  Stmnt			{ $$ = $9; }
743*de2caf28SDavid du Colombier 	| RETURN full_expr	{ $$ = return_statement($2); }
744219b2ee8SDavid du Colombier 	;
745219b2ee8SDavid du Colombier 
746219b2ee8SDavid du Colombier options : option		{ $$->sl = seqlist($1->sq, 0); }
747219b2ee8SDavid du Colombier 	| option options	{ $$->sl = seqlist($1->sq, $2->sl); }
748219b2ee8SDavid du Colombier 	;
749219b2ee8SDavid du Colombier 
750219b2ee8SDavid du Colombier option  : SEP   		{ open_seq(0); }
7517dd7cddfSDavid du Colombier           sequence OS		{ $$ = nn(ZN,0,ZN,ZN);
752*de2caf28SDavid du Colombier 				  $$->sq = close_seq(6);
753*de2caf28SDavid du Colombier 				  $$->ln = $1->ln;
754*de2caf28SDavid du Colombier 				  $$->fn = $1->fn;
755*de2caf28SDavid du Colombier 				}
756219b2ee8SDavid du Colombier 	;
757219b2ee8SDavid du Colombier 
758219b2ee8SDavid du Colombier OS	: /* empty */
759*de2caf28SDavid du Colombier 	| semi			{ /* redundant semi at end of sequence */ }
760219b2ee8SDavid du Colombier 	;
761219b2ee8SDavid du Colombier 
762*de2caf28SDavid du Colombier semi	: SEMI
763*de2caf28SDavid du Colombier 	| ARROW
764*de2caf28SDavid du Colombier 	;
765*de2caf28SDavid du Colombier 
766*de2caf28SDavid du Colombier MS	: semi			{ /* at least one semi-colon */ }
767*de2caf28SDavid du Colombier 	| MS semi		{ /* but more are okay too   */ }
768219b2ee8SDavid du Colombier 	;
769219b2ee8SDavid du Colombier 
770219b2ee8SDavid du Colombier aname	: NAME			{ $$ = $1; }
771219b2ee8SDavid du Colombier 	| PNAME			{ $$ = $1; }
772219b2ee8SDavid du Colombier 	;
773219b2ee8SDavid du Colombier 
774*de2caf28SDavid du Colombier const_expr:	CONST			{ $$ = $1; }
775*de2caf28SDavid du Colombier 	| '-' const_expr %prec UMIN	{ $$ = $2; $$->val = -($2->val); }
776*de2caf28SDavid du Colombier 	| l_par const_expr r_par		{ $$ = $2; }
777*de2caf28SDavid du Colombier 	| const_expr '+' const_expr	{ $$ = $1; $$->val = $1->val + $3->val; }
778*de2caf28SDavid du Colombier 	| const_expr '-' const_expr	{ $$ = $1; $$->val = $1->val - $3->val; }
779*de2caf28SDavid du Colombier 	| const_expr '*' const_expr	{ $$ = $1; $$->val = $1->val * $3->val; }
780*de2caf28SDavid du Colombier 	| const_expr '/' const_expr	{ $$ = $1;
781*de2caf28SDavid du Colombier 					  if ($3->val == 0)
782*de2caf28SDavid du Colombier 					  { fatal("division by zero", (char *) 0);
783*de2caf28SDavid du Colombier 					  }
784*de2caf28SDavid du Colombier 					  $$->val = $1->val / $3->val;
785*de2caf28SDavid du Colombier 					}
786*de2caf28SDavid du Colombier 	| const_expr '%' const_expr	{ $$ = $1;
787*de2caf28SDavid du Colombier 					  if ($3->val == 0)
788*de2caf28SDavid du Colombier 					  { fatal("attempt to take modulo of zero", (char *) 0);
789*de2caf28SDavid du Colombier 					  }
790*de2caf28SDavid du Colombier 					  $$->val = $1->val % $3->val;
791*de2caf28SDavid du Colombier 					}
792*de2caf28SDavid du Colombier 	;
793*de2caf28SDavid du Colombier 
794*de2caf28SDavid du Colombier expr    : l_par expr r_par		{ $$ = $2; }
795219b2ee8SDavid du Colombier 	| expr '+' expr		{ $$ = nn(ZN, '+', $1, $3); }
796219b2ee8SDavid du Colombier 	| expr '-' expr		{ $$ = nn(ZN, '-', $1, $3); }
797219b2ee8SDavid du Colombier 	| expr '*' expr		{ $$ = nn(ZN, '*', $1, $3); }
798219b2ee8SDavid du Colombier 	| expr '/' expr		{ $$ = nn(ZN, '/', $1, $3); }
799219b2ee8SDavid du Colombier 	| expr '%' expr		{ $$ = nn(ZN, '%', $1, $3); }
800219b2ee8SDavid du Colombier 	| expr '&' expr		{ $$ = nn(ZN, '&', $1, $3); }
8017dd7cddfSDavid du Colombier 	| expr '^' expr		{ $$ = nn(ZN, '^', $1, $3); }
802219b2ee8SDavid du Colombier 	| expr '|' expr		{ $$ = nn(ZN, '|', $1, $3); }
803219b2ee8SDavid du Colombier 	| expr GT expr		{ $$ = nn(ZN,  GT, $1, $3); }
804219b2ee8SDavid du Colombier 	| expr LT expr		{ $$ = nn(ZN,  LT, $1, $3); }
805219b2ee8SDavid du Colombier 	| expr GE expr		{ $$ = nn(ZN,  GE, $1, $3); }
806219b2ee8SDavid du Colombier 	| expr LE expr		{ $$ = nn(ZN,  LE, $1, $3); }
807219b2ee8SDavid du Colombier 	| expr EQ expr		{ $$ = nn(ZN,  EQ, $1, $3); }
808219b2ee8SDavid du Colombier 	| expr NE expr		{ $$ = nn(ZN,  NE, $1, $3); }
809219b2ee8SDavid du Colombier 	| expr AND expr		{ $$ = nn(ZN, AND, $1, $3); }
810219b2ee8SDavid du Colombier 	| expr OR  expr		{ $$ = nn(ZN,  OR, $1, $3); }
811219b2ee8SDavid du Colombier 	| expr LSHIFT expr	{ $$ = nn(ZN, LSHIFT,$1, $3); }
812219b2ee8SDavid du Colombier 	| expr RSHIFT expr	{ $$ = nn(ZN, RSHIFT,$1, $3); }
813219b2ee8SDavid du Colombier 	| '~' expr		{ $$ = nn(ZN, '~', $2, ZN); }
814219b2ee8SDavid du Colombier 	| '-' expr %prec UMIN	{ $$ = nn(ZN, UMIN, $2, ZN); }
815219b2ee8SDavid du Colombier 	| SND expr %prec NEG	{ $$ = nn(ZN, '!', $2, ZN); }
816219b2ee8SDavid du Colombier 
817*de2caf28SDavid du Colombier 	| l_par expr ARROW expr ':' expr r_par {
818219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  OR, $4, $6);
819219b2ee8SDavid du Colombier 				  $$ = nn(ZN, '?', $2, $$);
820219b2ee8SDavid du Colombier 				}
821219b2ee8SDavid du Colombier 
8227dd7cddfSDavid du Colombier 	| RUN aname		{ Expand_Ok++;
8237dd7cddfSDavid du Colombier 				  if (!context)
824*de2caf28SDavid du Colombier 				   fatal("used 'run' outside proctype", (char *) 0);
8257dd7cddfSDavid du Colombier 				}
826*de2caf28SDavid du Colombier 	  l_par args r_par
8277dd7cddfSDavid du Colombier 	  Opt_priority		{ Expand_Ok--;
828219b2ee8SDavid du Colombier 				  $$ = nn($2, RUN, $5, ZN);
829*de2caf28SDavid du Colombier 				  $$->val = ($7) ? $7->val : 0;
8307dd7cddfSDavid du Colombier 				  trackchanuse($5, $2, 'A'); trackrun($$);
831219b2ee8SDavid du Colombier 				}
832*de2caf28SDavid du Colombier 	| LEN l_par varref r_par	{ $$ = nn($3, LEN, $3, ZN); }
833*de2caf28SDavid du Colombier 	| ENABLED l_par expr r_par	{ $$ = nn(ZN, ENABLED, $3, ZN); has_enabled++; }
834*de2caf28SDavid du Colombier 	| GET_P l_par expr r_par	{ $$ = nn(ZN, GET_P, $3, ZN); has_priority++; }
835219b2ee8SDavid du Colombier 	| varref RCV		{ Expand_Ok++; }
836312a1df1SDavid du Colombier 	  '[' rargs ']'		{ Expand_Ok--; has_io++;
837219b2ee8SDavid du Colombier 				  $$ = nn($1, 'R', $1, $5);
838219b2ee8SDavid du Colombier 				}
839219b2ee8SDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
840312a1df1SDavid du Colombier 	  '[' rargs ']'		{ Expand_Ok--; has_io++;
841219b2ee8SDavid du Colombier 				  $$ = nn($1, 'R', $1, $5);
842219b2ee8SDavid du Colombier 				  $$->val = has_random = 1;
843219b2ee8SDavid du Colombier 				}
84400d97012SDavid du Colombier 	| varref		{ $$ = $1; trapwonly($1 /*, "varref" */); }
845312a1df1SDavid du Colombier 	| cexpr			{ $$ = $1; }
846219b2ee8SDavid du Colombier 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
847219b2ee8SDavid du Colombier 				  $$->ismtyp = $1->ismtyp;
848*de2caf28SDavid du Colombier 				  $$->sym = $1->sym;
849219b2ee8SDavid du Colombier 				  $$->val = $1->val;
850219b2ee8SDavid du Colombier 				}
851219b2ee8SDavid du Colombier 	| TIMEOUT		{ $$ = nn(ZN,TIMEOUT, ZN, ZN); }
8527dd7cddfSDavid du Colombier 	| NONPROGRESS		{ $$ = nn(ZN,NONPROGRESS, ZN, ZN);
8537dd7cddfSDavid du Colombier 				  has_np++;
8547dd7cddfSDavid du Colombier 				}
855*de2caf28SDavid du Colombier 	| PC_VAL l_par expr r_par	{ $$ = nn(ZN, PC_VAL, $3, ZN);
8567dd7cddfSDavid du Colombier 				  has_pcvalue++;
8577dd7cddfSDavid du Colombier 				}
858312a1df1SDavid du Colombier 	| PNAME '[' expr ']' '@' NAME
859312a1df1SDavid du Colombier 	  			{ $$ = rem_lab($1->sym, $3, $6->sym); }
860312a1df1SDavid du Colombier 	| PNAME '[' expr ']' ':' pfld
861312a1df1SDavid du Colombier 	  			{ $$ = rem_var($1->sym, $3, $6->sym, $6->lft); }
862312a1df1SDavid du Colombier 	| PNAME '@' NAME	{ $$ = rem_lab($1->sym, ZN, $3->sym); }
863312a1df1SDavid du Colombier 	| PNAME ':' pfld	{ $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); }
864*de2caf28SDavid du Colombier 	| ltl_expr		{ $$ = $1; /* sanity_check($1); */ }
865219b2ee8SDavid du Colombier 	;
866219b2ee8SDavid du Colombier 
8677dd7cddfSDavid du Colombier Opt_priority:	/* none */	{ $$ = ZN; }
868*de2caf28SDavid du Colombier 	| PRIORITY CONST	{ $$ = $2; has_priority++; }
8697dd7cddfSDavid du Colombier 	;
8707dd7cddfSDavid du Colombier 
8717dd7cddfSDavid du Colombier full_expr:	expr		{ $$ = $1; }
8727dd7cddfSDavid du Colombier 	| Expr			{ $$ = $1; }
8737dd7cddfSDavid du Colombier 	;
8747dd7cddfSDavid du Colombier 
87500d97012SDavid du Colombier ltl_expr: expr UNTIL expr	{ $$ = nn(ZN, UNTIL,   $1, $3); }
87600d97012SDavid du Colombier 	| expr RELEASE expr	{ $$ = nn(ZN, RELEASE, $1, $3); }
87700d97012SDavid du Colombier 	| expr WEAK_UNTIL expr	{ $$ = nn(ZN, ALWAYS, $1, ZN);
87800d97012SDavid du Colombier 				  $$ = nn(ZN, OR, $$, nn(ZN, UNTIL, $1, $3));
87900d97012SDavid du Colombier 				}
880*de2caf28SDavid du Colombier 	| expr IMPLIES expr	{ $$ = nn(ZN, '!', $1, ZN);
88100d97012SDavid du Colombier 				  $$ = nn(ZN, OR,  $$, $3);
88200d97012SDavid du Colombier 				}
88300d97012SDavid du Colombier 	| expr EQUIV expr	{ $$ = nn(ZN, EQUIV,   $1, $3); }
88400d97012SDavid du Colombier 	| NEXT expr       %prec NEG { $$ = nn(ZN, NEXT,  $2, ZN); }
88500d97012SDavid du Colombier 	| ALWAYS expr     %prec NEG { $$ = nn(ZN, ALWAYS,$2, ZN); }
88600d97012SDavid du Colombier 	| EVENTUALLY expr %prec NEG { $$ = nn(ZN, EVENTUALLY, $2, ZN); }
88700d97012SDavid du Colombier 	;
88800d97012SDavid du Colombier 
88900d97012SDavid du Colombier 	/* an Expr cannot be negated - to protect Probe expressions */
89000d97012SDavid du Colombier Expr	: Probe			{ $$ = $1; }
891*de2caf28SDavid du Colombier 	| l_par Expr r_par	{ $$ = $2; }
89200d97012SDavid du Colombier 	| Expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
89300d97012SDavid du Colombier 	| Expr AND expr		{ $$ = nn(ZN, AND, $1, $3); }
89400d97012SDavid du Colombier 	| expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
89500d97012SDavid du Colombier 	| Expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
89600d97012SDavid du Colombier 	| Expr OR  expr		{ $$ = nn(ZN,  OR, $1, $3); }
89700d97012SDavid du Colombier 	| expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
89800d97012SDavid du Colombier 	;
89900d97012SDavid du Colombier 
900*de2caf28SDavid du Colombier Probe	: FULL l_par varref r_par	{ $$ = nn($3,  FULL, $3, ZN); }
901*de2caf28SDavid du Colombier 	| NFULL l_par varref r_par	{ $$ = nn($3, NFULL, $3, ZN); }
902*de2caf28SDavid du Colombier 	| EMPTY l_par varref r_par	{ $$ = nn($3, EMPTY, $3, ZN); }
903*de2caf28SDavid du Colombier 	| NEMPTY l_par varref r_par	{ $$ = nn($3,NEMPTY, $3, ZN); }
90400d97012SDavid du Colombier 	;
90500d97012SDavid du Colombier 
9067dd7cddfSDavid du Colombier Opt_enabler:	/* none */	{ $$ = ZN; }
907*de2caf28SDavid du Colombier 	| PROVIDED l_par full_expr r_par {
908*de2caf28SDavid du Colombier 				   if (!proper_enabler($3))
909*de2caf28SDavid du Colombier 				   { non_fatal("invalid PROVIDED clause", (char *)0);
9107dd7cddfSDavid du Colombier 				     $$ = ZN;
9117dd7cddfSDavid du Colombier 				   } else
912*de2caf28SDavid du Colombier 				   { $$ = $3;
913*de2caf28SDavid du Colombier 				 } }
9147dd7cddfSDavid du Colombier 	| PROVIDED error	 { $$ = ZN;
915*de2caf28SDavid du Colombier 				   non_fatal("usage: provided ( ..expr.. )", (char *)0);
9167dd7cddfSDavid du Colombier 				 }
9177dd7cddfSDavid du Colombier 	;
9187dd7cddfSDavid du Colombier 
919*de2caf28SDavid du Colombier oname	: /* empty */		{ $$ = ZN; }
920*de2caf28SDavid du Colombier 	| ':' NAME		{ $$ = $2; }
921*de2caf28SDavid du Colombier 	;
922*de2caf28SDavid du Colombier 
923*de2caf28SDavid du Colombier basetype: TYPE oname		{ if ($2)
924*de2caf28SDavid du Colombier 				  {	if ($1->val != MTYPE)
925*de2caf28SDavid du Colombier 					{	explain($1->val);
926*de2caf28SDavid du Colombier 						fatal("unexpected type", (char *) 0);
927*de2caf28SDavid du Colombier 				  }	}
928*de2caf28SDavid du Colombier 				  $$->sym = $2 ? $2->sym : ZS;
929219b2ee8SDavid du Colombier 				  $$->val = $1->val;
9307dd7cddfSDavid du Colombier 				  if ($$->val == UNSIGNED)
9317dd7cddfSDavid du Colombier 				  fatal("unsigned cannot be used as mesg type", 0);
932219b2ee8SDavid du Colombier 				}
933219b2ee8SDavid du Colombier 	| UNAME			{ $$->sym = $1->sym;
934219b2ee8SDavid du Colombier 				  $$->val = STRUCT;
935219b2ee8SDavid du Colombier 				}
9367dd7cddfSDavid du Colombier 	| error			/* e.g., unsigned ':' const */
937219b2ee8SDavid du Colombier 	;
938219b2ee8SDavid du Colombier 
939219b2ee8SDavid du Colombier typ_list: basetype		{ $$ = nn($1, $1->val, ZN, ZN); }
940219b2ee8SDavid du Colombier 	| basetype ',' typ_list	{ $$ = nn($1, $1->val, ZN, $3); }
941219b2ee8SDavid du Colombier 	;
942219b2ee8SDavid du Colombier 
943*de2caf28SDavid du Colombier two_args:	expr ',' expr	{ $$ = nn(ZN, ',', $1, $3); }
944*de2caf28SDavid du Colombier 	;
945*de2caf28SDavid du Colombier 
946219b2ee8SDavid du Colombier args    : /* empty */		{ $$ = ZN; }
947219b2ee8SDavid du Colombier 	| arg			{ $$ = $1; }
948219b2ee8SDavid du Colombier 	;
949219b2ee8SDavid du Colombier 
950219b2ee8SDavid du Colombier prargs  : /* empty */		{ $$ = ZN; }
951219b2ee8SDavid du Colombier 	| ',' arg		{ $$ = $2; }
952219b2ee8SDavid du Colombier 	;
953219b2ee8SDavid du Colombier 
954219b2ee8SDavid du Colombier margs   : arg			{ $$ = $1; }
955*de2caf28SDavid du Colombier 	| expr l_par arg r_par	{ if ($1->ntyp == ',')
956219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
957219b2ee8SDavid du Colombier 				  else
958219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
959219b2ee8SDavid du Colombier 				}
960219b2ee8SDavid du Colombier 	;
961219b2ee8SDavid du Colombier 
962219b2ee8SDavid du Colombier arg     : expr			{ if ($1->ntyp == ',')
963219b2ee8SDavid du Colombier 					$$ = $1;
964219b2ee8SDavid du Colombier 				  else
965219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, ZN);
966219b2ee8SDavid du Colombier 				}
967219b2ee8SDavid du Colombier 	| expr ',' arg		{ if ($1->ntyp == ',')
968219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
969219b2ee8SDavid du Colombier 				  else
970219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
971219b2ee8SDavid du Colombier 				}
972219b2ee8SDavid du Colombier 	;
973219b2ee8SDavid du Colombier 
9747dd7cddfSDavid du Colombier rarg	: varref		{ $$ = $1; trackvar($1, $1);
97500d97012SDavid du Colombier 				  trapwonly($1 /*, "rarg" */); }
976*de2caf28SDavid du Colombier 	| EVAL l_par expr r_par	{ $$ = nn(ZN,EVAL,$3,ZN);
97700d97012SDavid du Colombier 				  trapwonly($1 /*, "eval rarg" */); }
978219b2ee8SDavid du Colombier 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
979219b2ee8SDavid du Colombier 				  $$->ismtyp = $1->ismtyp;
980*de2caf28SDavid du Colombier 				  $$->sym = $1->sym;
981219b2ee8SDavid du Colombier 				  $$->val = $1->val;
982219b2ee8SDavid du Colombier 				}
983219b2ee8SDavid du Colombier 	| '-' CONST %prec UMIN	{ $$ = nn(ZN,CONST,ZN,ZN);
984219b2ee8SDavid du Colombier 				  $$->val = - ($2->val);
985219b2ee8SDavid du Colombier 				}
986219b2ee8SDavid du Colombier 	;
987219b2ee8SDavid du Colombier 
988219b2ee8SDavid du Colombier rargs	: rarg			{ if ($1->ntyp == ',')
989219b2ee8SDavid du Colombier 					$$ = $1;
990219b2ee8SDavid du Colombier 				  else
991219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, ZN);
992219b2ee8SDavid du Colombier 				}
993219b2ee8SDavid du Colombier 	| rarg ',' rargs	{ if ($1->ntyp == ',')
994219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
995219b2ee8SDavid du Colombier 				  else
996219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
997219b2ee8SDavid du Colombier 				}
998*de2caf28SDavid du Colombier 	| rarg l_par rargs r_par	{ if ($1->ntyp == ',')
999219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
1000219b2ee8SDavid du Colombier 				  else
1001219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
1002219b2ee8SDavid du Colombier 				}
1003*de2caf28SDavid du Colombier 	| l_par rargs r_par		{ $$ = $2; }
1004219b2ee8SDavid du Colombier 	;
1005219b2ee8SDavid du Colombier 
1006219b2ee8SDavid du Colombier nlst	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
1007219b2ee8SDavid du Colombier 				  $$ = nn(ZN, ',', $$, ZN); }
10087dd7cddfSDavid du Colombier 	| nlst NAME 		{ $$ = nn($2, NAME, ZN, ZN);
10097dd7cddfSDavid du Colombier 				  $$ = nn(ZN, ',', $$, $1);
1010219b2ee8SDavid du Colombier 				}
10117dd7cddfSDavid du Colombier 	| nlst ','		{ $$ = $1; /* commas optional */ }
1012219b2ee8SDavid du Colombier 	;
1013219b2ee8SDavid du Colombier %%
1014219b2ee8SDavid du Colombier 
101500d97012SDavid du Colombier #define binop(n, sop)	fprintf(fd, "("); recursive(fd, n->lft); \
101600d97012SDavid du Colombier 			fprintf(fd, ") %s (", sop); recursive(fd, n->rgt); \
101700d97012SDavid du Colombier 			fprintf(fd, ")");
101800d97012SDavid du Colombier #define unop(n, sop)	fprintf(fd, "%s (", sop); recursive(fd, n->lft); \
101900d97012SDavid du Colombier 			fprintf(fd, ")");
102000d97012SDavid du Colombier 
102100d97012SDavid du Colombier static void
102200d97012SDavid du Colombier recursive(FILE *fd, Lextok *n)
102300d97012SDavid du Colombier {
102400d97012SDavid du Colombier 	if (n)
102500d97012SDavid du Colombier 	switch (n->ntyp) {
102600d97012SDavid du Colombier 	case NEXT:
102700d97012SDavid du Colombier 		unop(n, "X");
102800d97012SDavid du Colombier 		break;
102900d97012SDavid du Colombier 	case ALWAYS:
103000d97012SDavid du Colombier 		unop(n, "[]");
103100d97012SDavid du Colombier 		break;
103200d97012SDavid du Colombier 	case EVENTUALLY:
103300d97012SDavid du Colombier 		unop(n, "<>");
103400d97012SDavid du Colombier 		break;
103500d97012SDavid du Colombier 	case '!':
103600d97012SDavid du Colombier 		unop(n, "!");
103700d97012SDavid du Colombier 		break;
103800d97012SDavid du Colombier 	case UNTIL:
103900d97012SDavid du Colombier 		binop(n, "U");
104000d97012SDavid du Colombier 		break;
104100d97012SDavid du Colombier 	case WEAK_UNTIL:
104200d97012SDavid du Colombier 		binop(n, "W");
104300d97012SDavid du Colombier 		break;
104400d97012SDavid du Colombier 	case RELEASE: /* see http://en.wikipedia.org/wiki/Linear_temporal_logic */
104500d97012SDavid du Colombier 		binop(n, "V");
104600d97012SDavid du Colombier 		break;
104700d97012SDavid du Colombier 	case OR:
104800d97012SDavid du Colombier 		binop(n, "||");
104900d97012SDavid du Colombier 		break;
105000d97012SDavid du Colombier 	case AND:
105100d97012SDavid du Colombier 		binop(n, "&&");
105200d97012SDavid du Colombier 		break;
105300d97012SDavid du Colombier 	case IMPLIES:
105400d97012SDavid du Colombier 		binop(n, "->");
105500d97012SDavid du Colombier 		break;
105600d97012SDavid du Colombier 	case EQUIV:
105700d97012SDavid du Colombier 		binop(n, "<->");
105800d97012SDavid du Colombier 		break;
1059*de2caf28SDavid du Colombier 	case C_EXPR:
1060*de2caf28SDavid du Colombier 		fprintf(fd, "c_expr { %s }", put_inline(fd, n->sym->name));
1061*de2caf28SDavid du Colombier 		break;
106200d97012SDavid du Colombier 	default:
106300d97012SDavid du Colombier 		comment(fd, n, 0);
106400d97012SDavid du Colombier 		break;
106500d97012SDavid du Colombier 	}
106600d97012SDavid du Colombier }
106700d97012SDavid du Colombier 
1068*de2caf28SDavid du Colombier #ifdef __MINGW32__
1069*de2caf28SDavid du Colombier extern ssize_t getline(char **, size_t *, FILE *); /* see main.c */
1070*de2caf28SDavid du Colombier #endif
107100d97012SDavid du Colombier 
107200d97012SDavid du Colombier static Lextok *
ltl_to_string(Lextok * n)107300d97012SDavid du Colombier ltl_to_string(Lextok *n)
107400d97012SDavid du Colombier {	Lextok *m = nn(ZN, 0, ZN, ZN);
1075*de2caf28SDavid du Colombier 	ssize_t retval;
1076*de2caf28SDavid du Colombier 	char *ltl_formula = NULL;
1077*de2caf28SDavid du Colombier 	FILE *tf = fopen(TMP_FILE1, "w+"); /* tmpfile() fails on Windows 7 */
107800d97012SDavid du Colombier 
107900d97012SDavid du Colombier 	/* convert the parsed ltl to a string
108000d97012SDavid du Colombier 	   by writing into a file, using existing functions,
108100d97012SDavid du Colombier 	   and then passing it to the existing interface for
108200d97012SDavid du Colombier 	   conversion into a never claim
108300d97012SDavid du Colombier 	  (this means parsing everything twice, which is
108400d97012SDavid du Colombier 	   a little redundant, but adds only miniscule overhead)
108500d97012SDavid du Colombier 	 */
108600d97012SDavid du Colombier 
108700d97012SDavid du Colombier 	if (!tf)
108800d97012SDavid du Colombier 	{	fatal("cannot create temporary file", (char *) 0);
108900d97012SDavid du Colombier 	}
1090*de2caf28SDavid du Colombier 	dont_simplify = 1;
109100d97012SDavid du Colombier 	recursive(tf, n);
1092*de2caf28SDavid du Colombier 	dont_simplify = 0;
109300d97012SDavid du Colombier 	(void) fseek(tf, 0L, SEEK_SET);
109400d97012SDavid du Colombier 
1095*de2caf28SDavid du Colombier 	size_t linebuffsize = 0;
1096*de2caf28SDavid du Colombier 	retval = getline(&ltl_formula, &linebuffsize, tf);
109700d97012SDavid du Colombier 	fclose(tf);
1098*de2caf28SDavid du Colombier 
1099*de2caf28SDavid du Colombier 	(void) unlink(TMP_FILE1);
110000d97012SDavid du Colombier 
110100d97012SDavid du Colombier 	if (!retval)
1102*de2caf28SDavid du Colombier 	{	printf("%ld\n", (long int) retval);
1103*de2caf28SDavid du Colombier 		fatal("could not translate ltl ltl_formula", 0);
110400d97012SDavid du Colombier 	}
110500d97012SDavid du Colombier 
1106*de2caf28SDavid du Colombier 	if (1) printf("ltl %s: %s\n", ltl_name, ltl_formula);
110700d97012SDavid du Colombier 
1108*de2caf28SDavid du Colombier 	m->sym = lookup(ltl_formula);
1109*de2caf28SDavid du Colombier #ifndef __MINGW32__
1110*de2caf28SDavid du Colombier 	free(ltl_formula);
1111*de2caf28SDavid du Colombier #endif
111200d97012SDavid du Colombier 	return m;
111300d97012SDavid du Colombier }
111400d97012SDavid du Colombier 
1115*de2caf28SDavid du Colombier int
is_temporal(int t)1116*de2caf28SDavid du Colombier is_temporal(int t)
1117*de2caf28SDavid du Colombier {
1118*de2caf28SDavid du Colombier 	return (t == EVENTUALLY || t == ALWAYS || t == UNTIL
1119*de2caf28SDavid du Colombier 	     || t == WEAK_UNTIL || t == RELEASE);
1120*de2caf28SDavid du Colombier }
1121*de2caf28SDavid du Colombier 
1122*de2caf28SDavid du Colombier int
is_boolean(int t)1123*de2caf28SDavid du Colombier is_boolean(int t)
1124*de2caf28SDavid du Colombier {
1125*de2caf28SDavid du Colombier 	return (t == AND || t == OR || t == IMPLIES || t == EQUIV);
1126*de2caf28SDavid du Colombier }
1127*de2caf28SDavid du Colombier 
1128*de2caf28SDavid du Colombier #if 0
1129*de2caf28SDavid du Colombier /* flags correct formula like: ltl { true U (true U true) } */
1130*de2caf28SDavid du Colombier void
1131*de2caf28SDavid du Colombier sanity_check(Lextok *t)	/* check proper embedding of ltl_expr */
1132*de2caf28SDavid du Colombier {
1133*de2caf28SDavid du Colombier 	if (!t) return;
1134*de2caf28SDavid du Colombier 	sanity_check(t->lft);
1135*de2caf28SDavid du Colombier 	sanity_check(t->rgt);
1136*de2caf28SDavid du Colombier 
1137*de2caf28SDavid du Colombier 	if (t->lft && t->rgt)
1138*de2caf28SDavid du Colombier 	{	if (!is_boolean(t->ntyp)
1139*de2caf28SDavid du Colombier 		&&  (is_temporal(t->lft->ntyp)
1140*de2caf28SDavid du Colombier 		||   is_temporal(t->rgt->ntyp)))
1141*de2caf28SDavid du Colombier 		{	printf("spin: attempt to apply '");
1142*de2caf28SDavid du Colombier 			explain(t->ntyp);
1143*de2caf28SDavid du Colombier 			printf("' to '");
1144*de2caf28SDavid du Colombier 			explain(t->lft->ntyp);
1145*de2caf28SDavid du Colombier 			printf("' and '");
1146*de2caf28SDavid du Colombier 			explain(t->rgt->ntyp);
1147*de2caf28SDavid du Colombier 			printf("'\n");
1148*de2caf28SDavid du Colombier 	/*		non_fatal("missing parentheses?", (char *)0); */
1149*de2caf28SDavid du Colombier 	}	}
1150*de2caf28SDavid du Colombier }
1151*de2caf28SDavid du Colombier #endif
1152*de2caf28SDavid du Colombier 
1153219b2ee8SDavid du Colombier void
yyerror(char * fmt,...)1154219b2ee8SDavid du Colombier yyerror(char *fmt, ...)
11557dd7cddfSDavid du Colombier {
11567dd7cddfSDavid du Colombier 	non_fatal(fmt, (char *) 0);
1157219b2ee8SDavid du Colombier }
1158