spin.y 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /***** spin: spin.y *****/
  2. /* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* Permission is given to distribute this code provided that this intro- */
  5. /* ductory message is not removed and no monies are exchanged. */
  6. /* No guarantee is expressed or implied by the distribution of this code. */
  7. /* Software written by Gerard J. Holzmann as part of the book: */
  8. /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */
  9. /* Prentice Hall, Englewood Cliffs, NJ, 07632. */
  10. /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */
  11. %{
  12. #include "spin.h"
  13. #include <stdarg.h>
  14. #define YYDEBUG 0
  15. #define Stop nn(ZN,'@',ZN,ZN)
  16. extern Symbol *context, *owner;
  17. extern int u_sync, u_async, dumptab;
  18. extern short has_sorted, has_random, has_enabled, has_pcvalue, has_np;
  19. extern void validref(Lextok *, Lextok *);
  20. extern char yytext[];
  21. int Mpars = 0; /* max nr of message parameters */
  22. int runsafe = 1; /* 1 if all run stmnts are in init */
  23. int Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
  24. char *claimproc = (char *) 0;
  25. char *eventmap = (char *) 0;
  26. static int Embedded = 0, inEventMap = 0, has_ini = 0;
  27. %}
  28. %token ASSERT PRINT
  29. %token RUN LEN ENABLED EVAL PC_VAL
  30. %token TYPEDEF MTYPE INLINE LABEL OF
  31. %token GOTO BREAK ELSE SEMI
  32. %token IF FI DO OD SEP
  33. %token ATOMIC NON_ATOMIC D_STEP UNLESS
  34. %token TIMEOUT NONPROGRESS
  35. %token ACTIVE PROCTYPE D_PROCTYPE
  36. %token HIDDEN SHOW ISLOCAL
  37. %token PRIORITY PROVIDED
  38. %token FULL EMPTY NFULL NEMPTY
  39. %token CONST TYPE XU /* val */
  40. %token NAME UNAME PNAME INAME /* sym */
  41. %token STRING CLAIM TRACE INIT /* sym */
  42. %right ASGN
  43. %left SND O_SND RCV R_RCV /* SND doubles as boolean negation */
  44. %left OR
  45. %left AND
  46. %left '|'
  47. %left '^'
  48. %left '&'
  49. %left EQ NE
  50. %left GT LT GE LE
  51. %left LSHIFT RSHIFT
  52. %left '+' '-'
  53. %left '*' '/' '%'
  54. %left INCR DECR
  55. %right '~' UMIN NEG
  56. %left DOT
  57. %%
  58. /** PROMELA Grammar Rules **/
  59. program : units { yytext[0] = '\0'; }
  60. ;
  61. units : unit
  62. | units unit
  63. ;
  64. unit : proc /* proctype { } */
  65. | init /* init { } */
  66. | claim /* never claim */
  67. | events /* event assertions */
  68. | one_decl /* variables, chans */
  69. | utype /* user defined types */
  70. | ns /* named sequence */
  71. | SEMI /* optional separator */
  72. | error
  73. ;
  74. proc : inst /* optional instantiator */
  75. proctype NAME {
  76. setptype($3, PROCTYPE, ZN);
  77. setpname($3);
  78. context = $3->sym;
  79. context->ini = $2; /* linenr and file */
  80. Expand_Ok++; /* expand struct names in decl */
  81. has_ini = 0;
  82. }
  83. '(' decl ')' { Expand_Ok--;
  84. if (has_ini)
  85. fatal("initializer in parameter list", (char *) 0);
  86. }
  87. Opt_priority
  88. Opt_enabler
  89. body { ProcList *rl;
  90. rl = ready($3->sym, $6, $11->sq, $2->val, $10);
  91. if ($1 != ZN && $1->val > 0)
  92. { int j;
  93. for (j = 0; j < $1->val; j++)
  94. runnable(rl, $9?$9->val:1, 1);
  95. announce(":root:");
  96. if (dumptab) $3->sym->ini = $1;
  97. }
  98. context = ZS;
  99. }
  100. ;
  101. proctype: PROCTYPE { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 0; }
  102. | D_PROCTYPE { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
  103. ;
  104. inst : /* empty */ { $$ = ZN; }
  105. | ACTIVE { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
  106. | ACTIVE '[' CONST ']' {
  107. $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
  108. }
  109. | ACTIVE '[' NAME ']' {
  110. $$ = nn(ZN,CONST,ZN,ZN);
  111. $$->val = 0;
  112. if (!$3->sym->type)
  113. non_fatal("undeclared variable %s", $3->sym->name);
  114. else if ($3->sym->ini->ntyp != CONST)
  115. non_fatal("constant initializer required for %s\n",
  116. $3->sym->name);
  117. else
  118. $$->val = $3->sym->ini->val;
  119. }
  120. ;
  121. init : INIT { context = $1->sym; }
  122. Opt_priority
  123. body { ProcList *rl;
  124. rl = ready(context, ZN, $4->sq, 0, ZN);
  125. runnable(rl, $3?$3->val:1, 1);
  126. announce(":root:");
  127. context = ZS;
  128. }
  129. ;
  130. claim : CLAIM { context = $1->sym;
  131. if (claimproc)
  132. non_fatal("claim %s redefined", claimproc);
  133. claimproc = $1->sym->name;
  134. }
  135. body { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
  136. context = ZS;
  137. }
  138. ;
  139. events : TRACE { context = $1->sym;
  140. if (eventmap)
  141. non_fatal("trace %s redefined", eventmap);
  142. eventmap = $1->sym->name;
  143. inEventMap++;
  144. }
  145. body { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
  146. context = ZS;
  147. inEventMap--;
  148. }
  149. ;
  150. utype : TYPEDEF NAME { if (context)
  151. fatal("typedef %s must be global",
  152. $2->sym->name);
  153. owner = $2->sym;
  154. }
  155. '{' decl_lst '}' { setuname($5); owner = ZS; }
  156. ;
  157. nm : NAME { $$ = $1; }
  158. | INAME { $$ = $1;
  159. if (IArgs)
  160. fatal("invalid use of '%s'", $1->sym->name);
  161. }
  162. ;
  163. ns : INLINE nm '(' { NamesNotAdded++; }
  164. args ')' { prep_inline($2->sym, $5); NamesNotAdded--; }
  165. ;
  166. body : '{' { open_seq(1); }
  167. sequence OS { add_seq(Stop); }
  168. '}' { $$->sq = close_seq(0); }
  169. ;
  170. sequence: step { if ($1) add_seq($1); }
  171. | sequence MS step { if ($3) add_seq($3); }
  172. ;
  173. step : one_decl { $$ = ZN; }
  174. | XU vref_lst { setxus($2, $1->val); $$ = ZN; }
  175. | stmnt { $$ = $1; }
  176. | stmnt UNLESS stmnt { $$ = do_unless($1, $3); }
  177. ;
  178. vis : /* empty */ { $$ = ZN; }
  179. | HIDDEN { $$ = $1; }
  180. | SHOW { $$ = $1; }
  181. | ISLOCAL { $$ = $1; }
  182. ;
  183. asgn: /* empty */
  184. | ASGN
  185. ;
  186. one_decl: vis TYPE var_list { setptype($3, $2->val, $1); $$ = $3; }
  187. | vis UNAME var_list { setutype($3, $2->sym, $1);
  188. $$ = expand($3, Expand_Ok);
  189. }
  190. | vis TYPE asgn '{' nlst '}' {
  191. if ($2->val != MTYPE)
  192. fatal("malformed declaration", 0);
  193. setmtype($5);
  194. if ($1)
  195. non_fatal("cannot %s mtype (ignored)",
  196. $1->sym->name);
  197. if (context != ZS)
  198. fatal("mtype declaration must be global", 0);
  199. }
  200. ;
  201. decl_lst: one_decl { $$ = nn(ZN, ',', $1, ZN); }
  202. | one_decl SEMI
  203. decl_lst { $$ = nn(ZN, ',', $1, $3); }
  204. ;
  205. decl : /* empty */ { $$ = ZN; }
  206. | decl_lst { $$ = $1; }
  207. ;
  208. vref_lst: varref { $$ = nn($1, XU, $1, ZN); }
  209. | varref ',' vref_lst { $$ = nn($1, XU, $1, $3); }
  210. ;
  211. var_list: ivar { $$ = nn($1, TYPE, ZN, ZN); }
  212. | ivar ',' var_list { $$ = nn($1, TYPE, ZN, $3); }
  213. ;
  214. ivar : vardcl { $$ = $1;
  215. $1->sym->ini = nn(ZN,CONST,ZN,ZN);
  216. $1->sym->ini->val = 0;
  217. }
  218. | vardcl ASGN expr { $1->sym->ini = $3; $$ = $1;
  219. trackvar($1,$3); has_ini = 1;
  220. }
  221. | vardcl ASGN ch_init { $1->sym->ini = $3;
  222. $$ = $1; has_ini = 1;
  223. }
  224. ;
  225. ch_init : '[' CONST ']' OF
  226. '{' typ_list '}' { if ($2->val) u_async++;
  227. else u_sync++;
  228. { int i = cnt_mpars($6);
  229. Mpars = max(Mpars, i);
  230. }
  231. $$ = nn(ZN, CHAN, ZN, $6);
  232. $$->val = $2->val;
  233. }
  234. ;
  235. vardcl : NAME { $1->sym->nel = 1; $$ = $1; }
  236. | NAME ':' CONST { $1->sym->nbits = $3->val;
  237. $1->sym->nel = 1; $$ = $1;
  238. }
  239. | NAME '[' CONST ']' { $1->sym->nel = $3->val; $$ = $1; }
  240. ;
  241. varref : cmpnd { $$ = mk_explicit($1, Expand_Ok, NAME); }
  242. ;
  243. pfld : NAME { $$ = nn($1, NAME, ZN, ZN); }
  244. | NAME { owner = ZS; }
  245. '[' expr ']' { $$ = nn($1, NAME, $4, ZN); }
  246. ;
  247. cmpnd : pfld { Embedded++;
  248. if ($1->sym->type == STRUCT)
  249. owner = $1->sym->Snm;
  250. }
  251. sfld { $$ = $1; $$->rgt = $3;
  252. if ($3 && $1->sym->type != STRUCT)
  253. $1->sym->type = STRUCT;
  254. Embedded--;
  255. if (!Embedded && !NamesNotAdded
  256. && !$1->sym->type)
  257. non_fatal("undeclared variable: %s",
  258. $1->sym->name);
  259. if ($3) validref($1, $3->lft);
  260. owner = ZS;
  261. }
  262. ;
  263. sfld : /* empty */ { $$ = ZN; }
  264. | '.' cmpnd %prec DOT { $$ = nn(ZN, '.', $2, ZN); }
  265. ;
  266. stmnt : Special { $$ = $1; }
  267. | Stmnt { $$ = $1;
  268. if (inEventMap)
  269. fatal("not an event", (char *)0);
  270. }
  271. ;
  272. Special : varref RCV { Expand_Ok++; }
  273. rargs { Expand_Ok--;
  274. $$ = nn($1, 'r', $1, $4);
  275. trackchanuse($4, ZN, 'R');
  276. }
  277. | varref SND { Expand_Ok++; }
  278. margs { Expand_Ok--;
  279. $$ = nn($1, 's', $1, $4);
  280. $$->val=0; trackchanuse($4, ZN, 'S');
  281. }
  282. | IF options FI { $$ = nn($1, IF, ZN, ZN);
  283. $$->sl = $2->sl;
  284. prune_opts($$);
  285. }
  286. | DO { pushbreak(); }
  287. options OD { $$ = nn($1, DO, ZN, ZN);
  288. $$->sl = $3->sl;
  289. prune_opts($$);
  290. }
  291. | BREAK { $$ = nn(ZN, GOTO, ZN, ZN);
  292. $$->sym = break_dest();
  293. }
  294. | GOTO NAME { $$ = nn($2, GOTO, ZN, ZN);
  295. if ($2->sym->type != 0
  296. && $2->sym->type != LABEL) {
  297. non_fatal("bad label-name %s",
  298. $2->sym->name);
  299. }
  300. $2->sym->type = LABEL;
  301. }
  302. | NAME ':' stmnt { $$ = nn($1, ':',$3, ZN);
  303. if ($1->sym->type != 0
  304. && $1->sym->type != LABEL) {
  305. non_fatal("bad label-name %s",
  306. $1->sym->name);
  307. }
  308. $1->sym->type = LABEL;
  309. }
  310. ;
  311. Stmnt : varref ASGN expr { $$ = nn($1, ASGN, $1, $3);
  312. trackvar($1, $3);
  313. nochan_manip($1, $3, 0);
  314. }
  315. | varref INCR { $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
  316. $$ = nn(ZN, '+', $1, $$);
  317. $$ = nn($1, ASGN, $1, $$);
  318. trackvar($1, $1);
  319. if ($1->sym->type == CHAN)
  320. fatal("arithmetic on chan", (char *)0);
  321. }
  322. | varref DECR { $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
  323. $$ = nn(ZN, '-', $1, $$);
  324. $$ = nn($1, ASGN, $1, $$);
  325. trackvar($1, $1);
  326. if ($1->sym->type == CHAN)
  327. fatal("arithmetic on chan id's", (char *)0);
  328. }
  329. | PRINT '(' STRING { realread = 0; }
  330. prargs ')' { $$ = nn($3, PRINT, $5, ZN); realread = 1; }
  331. | ASSERT full_expr { $$ = nn(ZN, ASSERT, $2, ZN); }
  332. | varref R_RCV { Expand_Ok++; }
  333. rargs { Expand_Ok--;
  334. $$ = nn($1, 'r', $1, $4);
  335. $$->val = has_random = 1;
  336. trackchanuse($4, ZN, 'R');
  337. }
  338. | varref RCV { Expand_Ok++; }
  339. LT rargs GT { Expand_Ok--;
  340. $$ = nn($1, 'r', $1, $5);
  341. $$->val = 2; /* fifo poll */
  342. trackchanuse($5, ZN, 'R');
  343. }
  344. | varref R_RCV { Expand_Ok++; }
  345. LT rargs GT { Expand_Ok--; /* rrcv poll */
  346. $$ = nn($1, 'r', $1, $5);
  347. $$->val = 3; has_random = 1;
  348. trackchanuse($5, ZN, 'R');
  349. }
  350. | varref O_SND { Expand_Ok++; }
  351. margs { Expand_Ok--;
  352. $$ = nn($1, 's', $1, $4);
  353. $$->val = has_sorted = 1;
  354. trackchanuse($4, ZN, 'S');
  355. }
  356. | full_expr { $$ = nn(ZN, 'c', $1, ZN); }
  357. | ELSE { $$ = nn(ZN,ELSE,ZN,ZN);
  358. }
  359. | ATOMIC '{' { open_seq(0); }
  360. sequence OS '}' { $$ = nn($1, ATOMIC, ZN, ZN);
  361. $$->sl = seqlist(close_seq(3), 0);
  362. make_atomic($$->sl->this, 0);
  363. }
  364. | D_STEP '{' { open_seq(0); rem_Seq(); }
  365. sequence OS '}' { $$ = nn($1, D_STEP, ZN, ZN);
  366. $$->sl = seqlist(close_seq(4), 0);
  367. make_atomic($$->sl->this, D_ATOM);
  368. unrem_Seq();
  369. }
  370. | '{' { open_seq(0); }
  371. sequence OS '}' { $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
  372. $$->sl = seqlist(close_seq(5), 0);
  373. }
  374. | INAME { IArgs++; }
  375. '(' args ')' { pickup_inline($1->sym, $4); IArgs--; }
  376. Stmnt { $$ = $7; }
  377. ;
  378. options : option { $$->sl = seqlist($1->sq, 0); }
  379. | option options { $$->sl = seqlist($1->sq, $2->sl); }
  380. ;
  381. option : SEP { open_seq(0); }
  382. sequence OS { $$ = nn(ZN,0,ZN,ZN);
  383. $$->sq = close_seq(6); }
  384. ;
  385. OS : /* empty */
  386. | SEMI { /* redundant semi at end of sequence */ }
  387. ;
  388. MS : SEMI { /* at least one semi-colon */ }
  389. | MS SEMI { /* but more are okay too */ }
  390. ;
  391. aname : NAME { $$ = $1; }
  392. | PNAME { $$ = $1; }
  393. ;
  394. expr : '(' expr ')' { $$ = $2; }
  395. | expr '+' expr { $$ = nn(ZN, '+', $1, $3); }
  396. | expr '-' expr { $$ = nn(ZN, '-', $1, $3); }
  397. | expr '*' expr { $$ = nn(ZN, '*', $1, $3); }
  398. | expr '/' expr { $$ = nn(ZN, '/', $1, $3); }
  399. | expr '%' expr { $$ = nn(ZN, '%', $1, $3); }
  400. | expr '&' expr { $$ = nn(ZN, '&', $1, $3); }
  401. | expr '^' expr { $$ = nn(ZN, '^', $1, $3); }
  402. | expr '|' expr { $$ = nn(ZN, '|', $1, $3); }
  403. | expr GT expr { $$ = nn(ZN, GT, $1, $3); }
  404. | expr LT expr { $$ = nn(ZN, LT, $1, $3); }
  405. | expr GE expr { $$ = nn(ZN, GE, $1, $3); }
  406. | expr LE expr { $$ = nn(ZN, LE, $1, $3); }
  407. | expr EQ expr { $$ = nn(ZN, EQ, $1, $3); }
  408. | expr NE expr { $$ = nn(ZN, NE, $1, $3); }
  409. | expr AND expr { $$ = nn(ZN, AND, $1, $3); }
  410. | expr OR expr { $$ = nn(ZN, OR, $1, $3); }
  411. | expr LSHIFT expr { $$ = nn(ZN, LSHIFT,$1, $3); }
  412. | expr RSHIFT expr { $$ = nn(ZN, RSHIFT,$1, $3); }
  413. | '~' expr { $$ = nn(ZN, '~', $2, ZN); }
  414. | '-' expr %prec UMIN { $$ = nn(ZN, UMIN, $2, ZN); }
  415. | SND expr %prec NEG { $$ = nn(ZN, '!', $2, ZN); }
  416. | '(' expr SEMI expr ':' expr ')' {
  417. $$ = nn(ZN, OR, $4, $6);
  418. $$ = nn(ZN, '?', $2, $$);
  419. }
  420. | RUN aname { Expand_Ok++;
  421. if (!context)
  422. fatal("used 'run' outside proctype",
  423. (char *) 0);
  424. if (strcmp(context->name, ":init:") != 0)
  425. runsafe = 0;
  426. }
  427. '(' args ')'
  428. Opt_priority { Expand_Ok--;
  429. $$ = nn($2, RUN, $5, ZN);
  430. $$->val = ($7) ? $7->val : 1;
  431. trackchanuse($5, $2, 'A'); trackrun($$);
  432. }
  433. | LEN '(' varref ')' { $$ = nn($3, LEN, $3, ZN); }
  434. | ENABLED '(' expr ')' { $$ = nn(ZN, ENABLED, $3, ZN);
  435. has_enabled++;
  436. }
  437. | varref RCV { Expand_Ok++; }
  438. '[' rargs ']' { Expand_Ok--;
  439. $$ = nn($1, 'R', $1, $5);
  440. }
  441. | varref R_RCV { Expand_Ok++; }
  442. '[' rargs ']' { Expand_Ok--;
  443. $$ = nn($1, 'R', $1, $5);
  444. $$->val = has_random = 1;
  445. }
  446. | varref { $$ = $1; trapwonly($1, "varref"); }
  447. | CONST { $$ = nn(ZN,CONST,ZN,ZN);
  448. $$->ismtyp = $1->ismtyp;
  449. $$->val = $1->val;
  450. }
  451. | TIMEOUT { $$ = nn(ZN,TIMEOUT, ZN, ZN); }
  452. | NONPROGRESS { $$ = nn(ZN,NONPROGRESS, ZN, ZN);
  453. has_np++;
  454. }
  455. | PC_VAL '(' expr ')' { $$ = nn(ZN, PC_VAL, $3, ZN);
  456. has_pcvalue++;
  457. }
  458. | PNAME '[' expr ']' '@'
  459. NAME { $$ = rem_lab($1->sym, $3, $6->sym); }
  460. ;
  461. Opt_priority: /* none */ { $$ = ZN; }
  462. | PRIORITY CONST { $$ = $2; }
  463. ;
  464. full_expr: expr { $$ = $1; }
  465. | Expr { $$ = $1; }
  466. ;
  467. Opt_enabler: /* none */ { $$ = ZN; }
  468. | PROVIDED '(' full_expr ')' { if (!proper_enabler($3))
  469. { non_fatal("invalid PROVIDED clause",
  470. (char *)0);
  471. $$ = ZN;
  472. } else
  473. $$ = $3;
  474. }
  475. | PROVIDED error { $$ = ZN;
  476. non_fatal("usage: provided ( ..expr.. )",
  477. (char *)0);
  478. }
  479. ;
  480. /* an Expr cannot be negated - to protect Probe expressions */
  481. Expr : Probe { $$ = $1; }
  482. | '(' Expr ')' { $$ = $2; }
  483. | Expr AND Expr { $$ = nn(ZN, AND, $1, $3); }
  484. | Expr AND expr { $$ = nn(ZN, AND, $1, $3); }
  485. | Expr OR Expr { $$ = nn(ZN, OR, $1, $3); }
  486. | Expr OR expr { $$ = nn(ZN, OR, $1, $3); }
  487. | expr AND Expr { $$ = nn(ZN, AND, $1, $3); }
  488. | expr OR Expr { $$ = nn(ZN, OR, $1, $3); }
  489. ;
  490. Probe : FULL '(' varref ')' { $$ = nn($3, FULL, $3, ZN); }
  491. | NFULL '(' varref ')' { $$ = nn($3, NFULL, $3, ZN); }
  492. | EMPTY '(' varref ')' { $$ = nn($3, EMPTY, $3, ZN); }
  493. | NEMPTY '(' varref ')' { $$ = nn($3,NEMPTY, $3, ZN); }
  494. ;
  495. basetype: TYPE { $$->sym = ZS;
  496. $$->val = $1->val;
  497. if ($$->val == UNSIGNED)
  498. fatal("unsigned cannot be used as mesg type", 0);
  499. }
  500. | UNAME { $$->sym = $1->sym;
  501. $$->val = STRUCT;
  502. }
  503. | error /* e.g., unsigned ':' const */
  504. ;
  505. typ_list: basetype { $$ = nn($1, $1->val, ZN, ZN); }
  506. | basetype ',' typ_list { $$ = nn($1, $1->val, ZN, $3); }
  507. ;
  508. args : /* empty */ { $$ = ZN; }
  509. | arg { $$ = $1; }
  510. ;
  511. prargs : /* empty */ { $$ = ZN; }
  512. | ',' arg { $$ = $2; }
  513. ;
  514. margs : arg { $$ = $1; }
  515. | expr '(' arg ')' { if ($1->ntyp == ',')
  516. $$ = tail_add($1, $3);
  517. else
  518. $$ = nn(ZN, ',', $1, $3);
  519. }
  520. ;
  521. arg : expr { if ($1->ntyp == ',')
  522. $$ = $1;
  523. else
  524. $$ = nn(ZN, ',', $1, ZN);
  525. }
  526. | expr ',' arg { if ($1->ntyp == ',')
  527. $$ = tail_add($1, $3);
  528. else
  529. $$ = nn(ZN, ',', $1, $3);
  530. }
  531. ;
  532. rarg : varref { $$ = $1; trackvar($1, $1);
  533. trapwonly($1, "rarg"); }
  534. | EVAL '(' expr ')' { $$ = nn(ZN,EVAL,$3,ZN);
  535. trapwonly($1, "eval rarg"); }
  536. | CONST { $$ = nn(ZN,CONST,ZN,ZN);
  537. $$->ismtyp = $1->ismtyp;
  538. $$->val = $1->val;
  539. }
  540. | '-' CONST %prec UMIN { $$ = nn(ZN,CONST,ZN,ZN);
  541. $$->val = - ($2->val);
  542. }
  543. ;
  544. rargs : rarg { if ($1->ntyp == ',')
  545. $$ = $1;
  546. else
  547. $$ = nn(ZN, ',', $1, ZN);
  548. }
  549. | rarg ',' rargs { if ($1->ntyp == ',')
  550. $$ = tail_add($1, $3);
  551. else
  552. $$ = nn(ZN, ',', $1, $3);
  553. }
  554. | rarg '(' rargs ')' { if ($1->ntyp == ',')
  555. $$ = tail_add($1, $3);
  556. else
  557. $$ = nn(ZN, ',', $1, $3);
  558. }
  559. | '(' rargs ')' { $$ = $2; }
  560. ;
  561. nlst : NAME { $$ = nn($1, NAME, ZN, ZN);
  562. $$ = nn(ZN, ',', $$, ZN); }
  563. | nlst NAME { $$ = nn($2, NAME, ZN, ZN);
  564. $$ = nn(ZN, ',', $$, $1);
  565. }
  566. | nlst ',' { $$ = $1; /* commas optional */ }
  567. ;
  568. %%
  569. void
  570. yyerror(char *fmt, ...)
  571. {
  572. non_fatal(fmt, (char *) 0);
  573. }