cc}p1.clu 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. % CC_P1 CLU
  2. %
  3. % CLU 3 compiler: parsing routines for modules
  4. BEGIN
  5. # include "clucmp/cc_syn.equate"
  6. # include "clucmp/cc_p.equate"
  7. END
  8. parse = proc (e: env) returns (definition) signals (eof);
  9. k: token := e.peek_token;
  10. tagcase k in
  11. sharp: begin
  12. env$next_token(e);
  13. return(p_directive(e));
  14. end;
  15. out: return(p_definition(e));
  16. end;
  17. except eof: signal eof; end;
  18. end parse;
  19. p_definition = proc (e: env) returns (definition) signals (eof);
  20. not_oper = false;
  21. if bool$not(p_find_a_defn(e, not_oper))
  22. then signal eof;
  23. def: definition;
  24. k: token := env$peek(e, 3);
  25. tagcase k in
  26. defnkey: %(k: defnkey):
  27. begin
  28. id: idn := p_idn(e);
  29. env$next_token(e);
  30. env$next_token(e);
  31. env$new_level(e);
  32. tagcase k in
  33. proc_: def := definition$make_proc_(p_proc(e, id));
  34. iter_: def := definition$make_iter_(p_iter(e, id));
  35. cluster_: def := definition$make_clu(p_cluster(e, id));
  36. end;
  37. env$pop_level(e);
  38. p_semi(e);
  39. return(def);
  40. end;
  41. out: def := definition$make_equates(p_equatelist(e));
  42. end;
  43. return(def);
  44. end p_definition;
  45. p_directive = proc (e: env) returns (definition) signals (eof);
  46. ok: bool := false;
  47. k: token := e.peek_token;
  48. tagcase k in
  49. ident: %(k: ident):
  50. begin
  51. env$next_token(e);
  52. if "include" = k.str
  53. then ok := true;
  54. else env$err(e, "unrecognized directive", serious);
  55. end;
  56. out: env$err(e, "missing directive after #", serious);
  57. end;
  58. k := e.peek_token;
  59. tagcase k in
  60. str: %(k: strid):
  61. begin
  62. env$next_token(e);
  63. fs: str := strid$get_str(k);
  64. if cand(ok, file$exists(fs))
  65. then begin
  66. inf: file := file$open_read(fs);
  67. e1: env := env$new_env(e, inf);
  68. def: definition := definition$make_equates(p_equatelist(e1));
  69. tk: token := e1.peek_token;
  70. tagcase tk in
  71. eof: ;
  72. out: env$err(e1, "more than equates in include file", minor);
  73. end;
  74. file$close(inf);
  75. e.err := e1.err;
  76. return(def);
  77. end;
  78. if ok
  79. then env$err(e, "cannot open include file", serious);
  80. end;
  81. out: env$err(e, "missing file name string after # include", serious);
  82. end;
  83. return(p_definition(e));
  84. except eof: signal eof; end;
  85. end p_directive;
  86. p_proc = proc (e: env, id: idn) returns (applyspec);
  87. parms: decllist := p_parms(e);
  88. args: decllist := p_args(e);
  89. vals: typelist := p_returns(e);
  90. sigs: exceptionlist := p_signals(e);
  91. wher: restrictlist := p_where(e);
  92. bod: body := p_body(e, misc_body);
  93. p_defn_end(e, id, "PROC...END idn");
  94. return({idn: id,
  95. parms: parms,
  96. args: args,
  97. vals: vals,
  98. sigs: sigs,
  99. where_: wher,
  100. body: bod});
  101. end p_proc;
  102. p_iter = proc (e: env, id: idn) returns (applyspec);
  103. parms: decllist := p_parms(e);
  104. args: decllist := p_args(e);
  105. vals: typelist := p_yields(e);
  106. sigs: exceptionlist := p_signals(e);
  107. wher: restrictlist := p_where(e);
  108. bod: body := p_body(e, misc_body);
  109. p_defn_end(e, id, "ITER...END idn");
  110. return({idn: id,
  111. parms: parms,
  112. args: args,
  113. vals: vals,
  114. sigs: sigs,
  115. where_: wher,
  116. body: bod});
  117. end p_iter;
  118. p_cluster = proc (e: env, id: idn) returns (cluspec);
  119. parms: decllist := p_parms(e);
  120. ops: idnlist;
  121. k: token := e.peek_token;
  122. tagcase k in
  123. is_: begin
  124. env$next_token(e);
  125. ops := p_idnlist(e);
  126. end;
  127. out: begin
  128. env$assume(e, "IS idnlist in CLUSTER...END");
  129. ops := idnlist$create(1);
  130. end;
  131. end;
  132. wher: restrictlist := p_where(e);
  133. p_semi(e);
  134. equates: equatelist := p_equatelist(e);
  135. bod: operdefnlist := p_operdefnlist(e);
  136. p_defn_end(e, id, "CLUSTER...END idn");
  137. return({idn: id,
  138. parms: parms,
  139. ops: ops,
  140. where_: wher,
  141. equates: equates,
  142. body: bod});
  143. end p_cluster;
  144. p_equatelist = proc (e: env) returns (equatelist);
  145. equates: equatelist := equatelist$create(1);
  146. while true do begin
  147. id: idn;
  148. line: int := e.lineno;
  149. k: token := e.peek_token;
  150. tagcase k in
  151. ident: %(k: ident):
  152. id := env$get_idn(e, k);
  153. typekey: %(k: typekey):
  154. tagcase k in
  155. rep_: id := env$new_idn(e, "REP");
  156. out: return(equates);
  157. end;
  158. out: return(equates);
  159. end;
  160. k := env$peek(e, 2);
  161. tagcase k in
  162. op: %(k: infixop):
  163. tagcase k in
  164. eq: ;
  165. out: return(equates);
  166. end;
  167. out: return(equates);
  168. end;
  169. k := env$peek(e, 3);
  170. tagcase k in
  171. defnkey: return(equates);
  172. out: ;
  173. end;
  174. env$next_token(e);
  175. env$next_token(e);
  176. val: equateval;
  177. tagcase k in
  178. l_bkt: begin
  179. env$next_token(e);
  180. val := equateval$make_rename(p_renamelist(e));
  181. end;
  182. l_curly: begin
  183. env$next_token(e);
  184. val := equateval$make_typeset(p_typeset(e));
  185. end;
  186. out: val := equateval$make_const(p_const(e));
  187. end;
  188. equatelist$addh(equates, equate$create(id, val, line));
  189. p_semi(e);
  190. end;
  191. end p_equatelist;
  192. p_operdefnlist = proc (e: env) returns (operdefnlist);
  193. want_oper = true;
  194. opers: operdefnlist := operdefnlist$create(1);
  195. while p_find_a_defn(e, want_oper) do begin
  196. k: token := env$peek(e, 3);
  197. tagcase k in
  198. defnkey: %(k: defnkey):
  199. begin
  200. tagcase k in
  201. cluster_: return(opers);
  202. out: ;
  203. end;
  204. op: operdefn;
  205. id: idn := p_idn(e);
  206. env$next_token(e);
  207. env$next_token(e);
  208. env$new_level(e);
  209. tagcase k in
  210. proc_: op := operdefn$make_proc_(p_proc(e, id));
  211. iter_: op := operdefn$make_iter_(p_iter(e, id));
  212. end;
  213. env$pop_level(e);
  214. p_semi(e);
  215. operdefnlist$addh(opers, op);
  216. end;
  217. out: begin
  218. env$err(e, "equates as operdefns - parsing anyway", serious);
  219. p_equatelist(e);
  220. end;
  221. end;
  222. end;
  223. return(opers);
  224. end p_operdefnlist;
  225. p_parms = proc (e: env) returns (decllist);
  226. k: token := e.peek_token;
  227. tagcase k in
  228. l_bkt: env$next_token(e);
  229. out: return(decllist$create(1));
  230. end;
  231. parms: decllist := p_decllist(e);
  232. k := e.peek_token;
  233. tagcase k in
  234. r_bkt: env$next_token(e);
  235. out: env$assume(e, "] in [parmlist]");
  236. end;
  237. return(parms);
  238. end p_parms;
  239. p_args = proc (e: env) returns (decllist);
  240. k: token := e.peek_token;
  241. tagcase k in
  242. l_paren: env$next_token(e);
  243. out: return(decllist$create(1));
  244. end;
  245. k := e.peek_token;
  246. tagcase k in
  247. r_paren: begin
  248. env$next_token(e);
  249. return(decllist$create(1));
  250. end;
  251. out: ;
  252. end;
  253. args: decllist := p_decllist(e);
  254. k := e.peek_token;
  255. tagcase k in
  256. r_paren: env$next_token(e);
  257. out: env$assume(e, ") in (arglist)");
  258. end;
  259. return(args);
  260. end p_args;
  261. p_where = proc (e: env) returns (restrictlist);
  262. wher: restrictlist := restrictlist$create(1);
  263. k: token := e.peek_token;
  264. tagcase k in
  265. where_: env$next_token(e);
  266. out: return(wher);
  267. end;
  268. while true do begin
  269. id: idn := p_idn(e);
  270. kind: restrictkind := p_restrictkind(e);
  271. restrictlist$addh(wher, {idn: id,
  272. kind: kind});
  273. k := e.peek_token;
  274. tagcase k in
  275. comma: env$next_token(e);
  276. out: return(wher);
  277. end;
  278. end;
  279. end p_where;
  280. p_restrictkind = proc (e: env) returns (restrictkind);
  281. k: token := e.peek_token;
  282. tagcase k in
  283. in_: begin
  284. env$next_token(e);
  285. tk: token := e.peek_token;
  286. tagcase tk in
  287. ident: %(tk: ident):
  288. begin
  289. env$next_token(e);
  290. return(restrictkind$make_idn(env$get_idn(e, tk)));
  291. end;
  292. l_curly: begin
  293. env$next_token(e);
  294. return(restrictkind$make_set(p_typeset(e)));
  295. end;
  296. out: begin
  297. env$assume(e, "typeset in IN typeset");
  298. return(restrictkind$make_idn(env$new_idn(e, "?typeset?")));
  299. end;
  300. end;
  301. end;
  302. has_: begin
  303. env$next_token(e);
  304. return(restrictkind$make_has_(p_operdecllist(e)));
  305. end;
  306. out: begin
  307. env$assume(e, "IN typeset or HAS operdecllist in restrict");
  308. return(restrictkind$make_has_(operdecllist$create(1)));
  309. end;
  310. end;
  311. end p_restrictkind;
  312. p_typeset = proc (e: env) returns (typeset);
  313. env$new_level(e);
  314. id: idn := p_idn(e);
  315. id2: idn;
  316. k: token := e.peek_token;
  317. tagcase k in
  318. op: %(k: infixop):
  319. tagcase k in
  320. or: begin
  321. env$next_token(e);
  322. id2 := p_idn(e);
  323. end;
  324. out: begin
  325. env$assume(e, "| idn in {idn | idn ...}");
  326. id2 := id;
  327. end;
  328. end;
  329. out: begin
  330. env$assume(e, "| in {idn | ...}");
  331. id2 := id;
  332. end;
  333. end;
  334. if ~str$equal(id.str, id2.str)
  335. then env$assume(e, "idns do not match in {idn | idn ...}");
  336. ops: operdecllist;
  337. k := e.peek_token;
  338. tagcase k in
  339. has_: begin
  340. env$next_token(e);
  341. ops := p_operdecllist(e);
  342. end;
  343. out: begin
  344. env$assume(e, "HAS operdecllist in typeset");
  345. ops := operdecllist$create(1);
  346. end;
  347. end;
  348. equates: equatelist := p_equatelist(e);
  349. set: typeset := {idn: id,
  350. ops: ops,
  351. equates: equates};
  352. k := e.peek_token;
  353. tagcase k in
  354. r_curly: env$next_token(e);
  355. out: env$assume(e, "} in {idn | ...}");
  356. end;
  357. env$pop_level(e);
  358. return(set);
  359. end p_typeset;
  360. p_semi = proc (e: env);
  361. i: int := 0;
  362. while token$is_semi(e.peek_token) do begin
  363. env$next_token(e);
  364. i := i + 1;
  365. end;
  366. if i > 1
  367. then env$err(e, "more than one ; in a row", minor);
  368. end p_semi;
  369. p_defn_end = proc (e: env, id: idn, mod: str);
  370. k: token := e.peek_token;
  371. tagcase k in
  372. end_: env$next_token(e);
  373. out: begin
  374. env$assume(e, "END idn in " || mod);
  375. return;
  376. end;
  377. end;
  378. k := e.peek_token;
  379. tagcase k in
  380. ident: %(k: ident):
  381. if str$equal(k.str, id.str)
  382. then begin
  383. env$next_token(e);
  384. return;
  385. end;
  386. out: begin
  387. env$assume(e, "idn in " || mod);
  388. return;
  389. end;
  390. end;
  391. tagcase k in
  392. semi,
  393. ident: begin
  394. env$next_token(e);
  395. env$err(e, "idns do not match in idn = " || mod, minor);
  396. end;
  397. out: env$assume(e, "idn in " || mod);
  398. end;
  399. end p_defn_end;
  400. p_find_a_defn = proc (e: env, want_oper: bool) returns (bool);
  401. flushed: bool := false;
  402. b: bool := true;
  403. found: bool := false;
  404. while b do begin
  405. k: token := e.peek_token;
  406. tagcase k in
  407. ident: begin
  408. tk: token := env$peek(e, 2);
  409. tagcase tk in
  410. op: %(tk: infixop):
  411. tagcase tk in
  412. eq: begin
  413. found := true;
  414. b := false;
  415. end;
  416. out: ;
  417. end;
  418. out: ;
  419. end;
  420. end;
  421. end_: if want_oper
  422. then b := false;
  423. eof: b := false;
  424. out: ;
  425. end;
  426. if b
  427. then begin
  428. if ~flushed
  429. then begin
  430. if want_oper
  431. then env$err(e, "looking for an operdefn", serious);
  432. else env$err(e, "looking for a definition", serious);
  433. flushed := true;
  434. end;
  435. env$next_token(e);
  436. end;
  437. end;
  438. if flushed
  439. then env$err(e, "resuming parse at this point", none);
  440. return(found);
  441. end p_find_a_defn;