cc}p2.clu 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. % CC_P2 CLU
  2. %
  3. % CLU 3 compiler: parsing routines for statements
  4. BEGIN
  5. # include "clucmp/cc_syn.equate"
  6. # include "clucmp/cc_p.equate"
  7. END
  8. p_body = proc (e: env, kind: bodykind) returns (body);
  9. p_semi(e);
  10. env$new_level(e);
  11. equates: equatelist := p_equatelist(e);
  12. stmts: stmtlist := p_stmtlist(e, kind);
  13. env$pop_level(e);
  14. return({equates: equates,
  15. stmts: stmts});
  16. end p_body;
  17. p_stmtlist = proc (e: env, kind: bodykind) returns (stmtlist);
  18. stmts: stmtlist := stmtlist$create(1);
  19. while true do begin
  20. abs: stmtabs;
  21. l: int := e.lineno;
  22. k: token := e.peek_token;
  23. tagcase k in
  24. stmtkey: %(k: stmtkey):
  25. begin
  26. env$next_token(e);
  27. tagcase k in
  28. if_: abs := p_if(e);
  29. for_: abs := p_for(e);
  30. tagcase_: abs := p_tagcase(e);
  31. while_: abs := p_while(e);
  32. return_: abs := stmtabs$make_return_(p_pexprlist(e, true));
  33. yield_: abs := stmtabs$make_yield_(p_pexprlist(e, true));
  34. signal_: abs := p_signal(e);
  35. break_: abs := stmtabs$make_break_(nil);
  36. begin_: begin
  37. abs := stmtabs$make_body(p_body(e, misc_body));
  38. p_end(e, "END in BEGIN...END");
  39. end;
  40. end;
  41. end;
  42. ident:
  43. begin
  44. tk: token := env$peek(e, 2);
  45. tagcase tk in
  46. comma, assn, colon:
  47. abs := p_decl_or_assn(e);
  48. op: %(tk: infixop):
  49. tagcase tk in
  50. eq: begin
  51. tkn: token := env$peek(e, 3);
  52. tagcase tkn in
  53. defnkey: return(stmts);
  54. out: ;
  55. end;
  56. env$err(e, "equates as stmts - parsing anyway",
  57. serious);
  58. p_equatelist(e);
  59. abs := stmtabs$make_bad(nil);
  60. end;
  61. out: abs := p_expr_stmt(e);
  62. end;
  63. out: abs := p_expr_stmt(e);
  64. end;
  65. end;
  66. int_, char_, str, typekey, exprkey:
  67. abs := p_expr_stmt(e);
  68. op, not, l_paren:
  69. begin
  70. env$err(e, "operator or ( starts stmt - parsing as expr",
  71. minor);
  72. abs := p_expr_stmt(e);
  73. end;
  74. out: if p_find_a_stmt(e, kind)
  75. then abs := stmtabs$make_bad(nil);
  76. else return(stmts);
  77. end;
  78. stmtlist$addh(stmts, p_except(e, stmt$create(abs, l)));
  79. end;
  80. end p_stmtlist;
  81. p_if = proc (e: env) returns (stmtabs);
  82. arms: ifarmlist := ifarmlist$create(1);
  83. ifs: ifstmt := {arms: arms,
  84. else_: mbody$make_none(nil)};
  85. abs: stmtabs := stmtabs$make_if_(ifs);
  86. while true do begin
  87. x: expr := p_expr(e, min_prec);
  88. k: token := e.peek_token;
  89. tagcase k in
  90. then_: env$next_token(e);
  91. out: env$assume(e, "THEN in expr THEN body");
  92. end;
  93. bod: body := p_body(e, then_body);
  94. ifarmlist$addh(arms, {test: x,
  95. body: bod});
  96. k := e.peek_token;
  97. tagcase k in
  98. elseif_: env$next_token(e);
  99. else_: begin
  100. env$next_token(e);
  101. ifs.else_ := mbody$make_body(p_body(e, misc_body));
  102. p_end(e, "END in IF...END");
  103. return(abs);
  104. end;
  105. end_: begin
  106. env$next_token(e);
  107. return(abs);
  108. end;
  109. out: begin
  110. env$assume(e, "END in IF...END");
  111. return(abs);
  112. end;
  113. end;
  114. end;
  115. end p_if;
  116. p_for = proc (e: env) returns (stmtabs);
  117. env$new_level(e);
  118. vars: forvars;
  119. k: token := e.peek_token;
  120. tagcase k in
  121. in_: vars := forvars$make_old(idnlist$create(1));
  122. out: vars := p_idns_or_decls(e);
  123. end;
  124. k := e.peek_token;
  125. tagcase k in
  126. in_: env$next_token(e);
  127. out: env$assume(e, "IN in FOR...IN...END");
  128. end;
  129. call: invoke := p_make_invoke(e, p_expr(e, min_prec));
  130. bod: body := p_do(e);
  131. env$pop_level(e);
  132. return(stmtabs$make_for_({idns: vars,
  133. call: call,
  134. body: bod}));
  135. end p_for;
  136. p_do = proc (e: env) returns (body);
  137. k: token := e.peek_token;
  138. tagcase k in
  139. do_: env$next_token(e);
  140. out: env$assume(e, "DO in DO...END");
  141. end;
  142. bod: body := p_body(e, misc_body);
  143. p_end(e, "END in DO...END");
  144. return(bod);
  145. end p_do;
  146. p_idns_or_decls = proc (e: env) returns (forvars);
  147. l: int := e.lineno;
  148. idns: idnlist := p_idnlist(e);
  149. k: token := e.peek_token;
  150. tagcase k in
  151. colon: begin
  152. env$next_token(e);
  153. t: typespec := p_type(e);
  154. decls: decllist;
  155. tk: token := e.peek_token;
  156. tagcase tk in
  157. comma: begin
  158. env$next_token(e);
  159. decls := p_decllist(e);
  160. end;
  161. out: decls := decllist$create(1);
  162. end;
  163. decllist$addl(decls, {idns: idns,
  164. type_: t});
  165. decllist$set_low(decls, 1);
  166. return(forvars$make_new(decls));
  167. end;
  168. out: return(forvars$make_old(idns));
  169. end;
  170. end p_idns_or_decls;
  171. p_idnlist = proc (e: env) returns (idnlist);
  172. idns: idnlist := idnlist$create(1);
  173. while true do begin
  174. idnlist$addh(idns, p_idn(e));
  175. k: token := e.peek_token;
  176. tagcase k in
  177. comma: env$next_token(e);
  178. out: return(idns);
  179. end;
  180. end;
  181. end p_idnlist;
  182. p_idn = proc (e: env) returns (idn);
  183. k: token := e.peek_token;
  184. tagcase k in
  185. ident: %(k: ident):
  186. begin
  187. env$next_token(e);
  188. return(env$get_idn(e, k));
  189. end;
  190. out: begin
  191. env$assume(e, "idn");
  192. return(env$new_idn(e, "?idn?"));
  193. end;
  194. end;
  195. end p_idn;
  196. p_decllist = proc (e: env) returns (decllist);
  197. decls: decllist := decllist$create(1);
  198. while true do begin
  199. decllist$addh(decls, p_decl(e));
  200. k: token := e.peek_token;
  201. tagcase k in
  202. comma: env$next_token(e);
  203. out: return(decls);
  204. end;
  205. end;
  206. end p_decllist;
  207. p_decl = proc (e: env) returns (decl);
  208. idns: idnlist := p_idnlist(e);
  209. t: typespec;
  210. k: token := e.peek_token;
  211. tagcase k in
  212. colon: begin
  213. env$next_token(e);
  214. t := p_type(e);
  215. end;
  216. out: begin
  217. env$assume(e, ": type in decl");
  218. t := e.unknown_type;
  219. end;
  220. end;
  221. return({idns: idns,
  222. type_: t});
  223. end p_decl;
  224. p_tagcase = proc (e: env) returns (stmtabs);
  225. arms: tagarmlist := tagarmlist$create(1);
  226. obj: expr := p_expr(e, min_prec);
  227. tst: tagstmt := {obj: obj,
  228. arms: arms,
  229. others_: mbody$make_none(nil)};
  230. abs: stmtabs := stmtabs$make_tag_(tst);
  231. while true do begin
  232. k: token := e.peek_token;
  233. tagcase k in
  234. tag_: begin
  235. env$next_token(e);
  236. env$new_level(e);
  237. tags: namelist := p_namelist(e);
  238. var: mdecl := p_mdecl(e);
  239. bod: body := p_cbody(e, tag_body, ": in TAG...: body");
  240. tagarmlist$addh(arms, {tags: tags,
  241. var: var,
  242. body: bod});
  243. env$pop_level(e);
  244. end;
  245. others_: begin
  246. env$next_token(e);
  247. tst.others_ := p_cbody(e, misc_body, ": in OTHERS: body");
  248. p_end(e, "END in TAGCASE...END");
  249. return(abs);
  250. end;
  251. end_: begin
  252. env$next_token(e);
  253. return(abs);
  254. end;
  255. out: begin
  256. env$assume(e, "END in TAGCASE...END");
  257. return(abs);
  258. end;
  259. end;
  260. end;
  261. end p_tagcase;
  262. p_while = proc (e: env) returns (stmtabs);
  263. test: expr := p_expr(e, min_prec);
  264. bod: body := p_do(e);
  265. return(stmtabs$make_while_({test: test,
  266. body: bod}));
  267. end p_while;
  268. p_signal = proc (e: env) returns (stmtabs);
  269. n: name := p_name(e);
  270. args: exprlist := p_pexprlist(e, true);
  271. return(stmtabs$make_signal_({name: n,
  272. args: args}));
  273. end p_signal;
  274. p_decl_or_assn = proc (e: env) returns (stmtabs);
  275. vars: forvars := p_idns_or_decls(e);
  276. k: token := e.peek_token;
  277. tagcase k in
  278. assn: begin
  279. env$next_token(e);
  280. el: exprlist := p_exprlist(e, false);
  281. tagcase vars in
  282. old: %(vars: idnlist):
  283. return(stmtabs$make_assn({left: vars,
  284. right: el}));
  285. new: %(vars: decllist):
  286. begin
  287. x: expr;
  288. if exprlist$size(el) = 1
  289. then x := exprlist$bottom(el);
  290. else begin
  291. env$err(e, "only 1 expr allowed in declinit", minor);
  292. x := e.bad_expr;
  293. end;
  294. return(stmtabs$make_declinit({decls: vars,
  295. expr: x}));
  296. end;
  297. end;
  298. end;
  299. out: tagcase vars in
  300. old: %(vars: idnlist):
  301. begin
  302. env$assume(e, ": type in decl");
  303. return(stmtabs$make_decl({vars: vars,
  304. type_: e.unknown_type}));
  305. end;
  306. new: %(vars: decllist):
  307. if decllist$size(vars) = 1
  308. then return(stmtabs$make_decl(decllist$bottom(vars)));
  309. else begin
  310. env$assume(e, ":= invoke in declinit");
  311. return(stmtabs$make_declinit({decls: vars,
  312. expr: e.bad_expr}));
  313. end;
  314. end;
  315. end;
  316. end p_decl_or_assn;
  317. p_expr_stmt = proc (e: env) returns (stmtabs);
  318. x: expr := p_expr(e, min_prec);
  319. k: token := e.peek_token;
  320. tagcase k in
  321. assn: begin
  322. env$next_token(e);
  323. right: expr := p_expr(e, min_prec);
  324. return(stmtabs$make_sugarassn({left: x,
  325. right: right}));
  326. end;
  327. out: return(stmtabs$make_invoke(p_make_invoke(e, x)));
  328. end;
  329. end p_expr_stmt;
  330. p_make_invoke = proc (e: env, x: expr) returns (invoke);
  331. abs: exprabs := x.abs;
  332. tagcase abs in
  333. invoke: %(abs: invoke):
  334. return(abs);
  335. out: begin
  336. env$err(e, "preceding expr is not an invoke", minor);
  337. return({apply: e.bad_expr,
  338. args: exprlist$create(1),
  339. rename: renaming$make_none(nil)});
  340. end;
  341. end;
  342. end p_make_invoke;
  343. p_except = proc (e: env, st: stmt) returns (stmt);
  344. while true do begin
  345. p_semi(e);
  346. k: token := e.peek_token;
  347. tagcase k in
  348. except_: env$next_token(e);
  349. out: return(st);
  350. end;
  351. st := p_exceptarms(e, st);
  352. p_end(e, "END in EXCEPT...END");
  353. end;
  354. end p_except;
  355. p_exceptarms = proc (e: env, st: stmt) returns (stmtabs);
  356. arms: handlerlist := handlerlist$create(1);
  357. xs: exceptstmt := {stmt: st,
  358. arms: arms,
  359. others_: mothersarm$make_none(nil)};
  360. abs := stmtabs$make_except_(xs);
  361. while true do begin
  362. k: token := env$next_token(e);
  363. tagcase k in
  364. when_: begin
  365. env$next_token(e);
  366. env$new_level(e);
  367. names: namelist := p_namelist(e);
  368. vars: whendecl := p_whendecl(e);
  369. bod: body := p_cbody(e, when_body, ": in WHEN...: body");
  370. handlerlist$addh(arms, {names: names,
  371. vars: vars,
  372. body: bod});
  373. env$pop_level(e);
  374. end;
  375. others_: begin
  376. env$next_token(e);
  377. env$new_level(e);
  378. dec: mdecl := p_mdecl(e);
  379. bod: body := p_cbody(e, misc_body, ": in OTHERS...: body");
  380. xs.others_ := mothersarm$make_arm({decl: dec,
  381. body: bod});
  382. env$pop_level(e);
  383. end;
  384. out: return(abs);
  385. end;
  386. end;
  387. end p_exceptarms;
  388. p_mdecl = proc (e: env) returns (mdecl);
  389. k: token := e.peek_token;
  390. tagcase k in
  391. l_paren: env$next_token(e);
  392. out: return(mdecl$make_none(nil));
  393. end;
  394. dec: decl := p_decl(e);
  395. if idnlist$size(dec.idns) > 1
  396. then env$err(e, "more than one idn declared", minor);
  397. k := e.peek_token;
  398. tagcase k in
  399. r_paren: env$next_token(e);
  400. out: env$assume(e, ") in (idn: type)");
  401. end;
  402. return(mdecl$make_decl(dec));
  403. end p_mdecl;
  404. p_cbody = proc (e: env, kind: bodykind, assume: str) returns (body);
  405. k: token := e.peek_token;
  406. tagcase k in
  407. colon: env$next_token(e);
  408. out: env$assume(e, assume);
  409. end;
  410. return(p_body(e, kind));
  411. end p_cbody;
  412. p_whendecl = proc (e: env) returns (whendecl);
  413. k: token := e.peek_token;
  414. tagcase k in
  415. l_paren: env$next_token(e);
  416. out: return(whendecl$make_none(nil));
  417. end;
  418. dec: whendecl;
  419. k := e.peek_token;
  420. tagcase k in
  421. op: %(k: infixop):
  422. tagcase k in
  423. mul: begin
  424. env$next_token(e);
  425. dec := whendecl$make_star(nil);
  426. end;
  427. out: dec := whendecl$make_decls(p_decllist(e));
  428. end;
  429. out: dec := whendecl$make_decls(p_decllist(e));
  430. end;
  431. k := e.peek_token;
  432. tagcase k in
  433. r_paren: env$next_token(e);
  434. out: env$assume(e, ") in (decllist) or (*)");
  435. end;
  436. return(dec);
  437. end p_whendecl;
  438. p_end = proc (e: env, assume: str);
  439. k: token := e.peek_token;
  440. tagcase k in
  441. end_: env$next_token(e);
  442. out: env$assume(e, assume);
  443. end;
  444. end p_end;
  445. p_find_a_stmt = proc (e: env, kind: bodykind) returns (bool);
  446. flushed: bool := false;
  447. b: bool := true;
  448. found: bool := false;
  449. while b do begin
  450. k: token := e.peek_token;
  451. tagcase k in
  452. else_, elseif_:
  453. if kind = then_body then b := false;
  454. tag_: if kind = tag_body then b := false;
  455. when_: if kind = when_body then b := false;
  456. others_: if cor(kind = tag_body, kind = when_body)
  457. then b := false;
  458. end_, defnkey, returns_, yields_, where_, is_, has_, to_, eof:
  459. b := false;
  460. stmtkey, except_:
  461. begin
  462. found := true;
  463. b := false;
  464. end;
  465. semi: begin
  466. env$next_token(e);
  467. found := true;
  468. b := false;
  469. end;
  470. out: ;
  471. end;
  472. if b
  473. then begin
  474. if ~flushed
  475. then begin
  476. env$err(e, "looking for a stmt", serious);
  477. flushed := true;
  478. end;
  479. env$next_token(e);
  480. end;
  481. end;
  482. if flushed
  483. then env$err(e, "resuming parse at this point", none);
  484. return(found);
  485. end p_find_a_stmt;