PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mosmlyac/reader.c

https://github.com/bluegnu/mosml
C | 1850 lines | 1628 code | 201 blank | 21 comment | 483 complexity | 0f4f18bbe03edfd93ce978b80f99392e MD5 | raw file
Possible License(s): GPL-2.0
  1. #ifdef ANSI
  2. #include <string.h>
  3. #endif
  4. #include "defs.h"
  5. /* The line size must be a positive integer. One hundred was chosen */
  6. /* because few lines in Yacc input grammars exceed 100 characters. */
  7. /* Note that if a line exceeds LINESIZE characters, the line buffer */
  8. /* will be expanded to accomodate it. */
  9. #define LINESIZE 100
  10. char *cache;
  11. int cinc, cache_size;
  12. int ntags, tagmax;
  13. char **tag_table;
  14. char saw_eof, unionized;
  15. char *cptr, *line;
  16. int linesize;
  17. bucket *goal;
  18. int prec;
  19. int gensym;
  20. char last_was_action;
  21. int maxitems;
  22. bucket **pitem;
  23. int maxrules;
  24. bucket **plhs;
  25. int name_pool_size;
  26. char *name_pool;
  27. bucket** sortedtokens;
  28. int ntruetokens;
  29. char line_format[] = "(* Line %d, file %s *)\n";
  30. void start_rule(register bucket *bp, int s_lineno);
  31. void cachec(int c)
  32. {
  33. assert(cinc >= 0);
  34. if (cinc >= cache_size)
  35. {
  36. cache_size += 256;
  37. cache = REALLOC(cache, cache_size);
  38. if (cache == 0) no_space();
  39. }
  40. cache[cinc] = c;
  41. ++cinc;
  42. }
  43. void get_line(void)
  44. {
  45. register FILE *f = input_file;
  46. register int c;
  47. register int i;
  48. if (saw_eof || (c = getc(f)) == EOF)
  49. {
  50. if (line) { FREE(line); line = 0; }
  51. cptr = 0;
  52. saw_eof = 1;
  53. return;
  54. }
  55. if (line == 0 || linesize != (LINESIZE + 1))
  56. {
  57. if (line) FREE(line);
  58. linesize = LINESIZE + 1;
  59. line = MALLOC(linesize);
  60. if (line == 0) no_space();
  61. }
  62. i = 0;
  63. ++lineno;
  64. for (;;)
  65. {
  66. line[i] = c;
  67. if (c == '\n') { cptr = line; return; }
  68. if (++i >= linesize)
  69. {
  70. linesize += LINESIZE;
  71. line = REALLOC(line, linesize);
  72. if (line == 0) no_space();
  73. }
  74. c = getc(f);
  75. if (c == EOF)
  76. {
  77. line[i] = '\n';
  78. saw_eof = 1;
  79. cptr = line;
  80. return;
  81. }
  82. }
  83. }
  84. char *dup_line(void)
  85. {
  86. register char *p, *s, *t;
  87. if (line == 0) return (0);
  88. s = line;
  89. while (*s != '\n') ++s;
  90. p = MALLOC(s - line + 1);
  91. if (p == 0) no_space();
  92. s = line;
  93. t = p;
  94. while ((*t++ = *s++) != '\n') continue;
  95. return (p);
  96. }
  97. void skip_comment(void)
  98. {
  99. register char *s;
  100. int st_lineno = lineno;
  101. char *st_line = dup_line();
  102. char *st_cptr = st_line + (cptr - line);
  103. s = cptr + 2;
  104. for (;;)
  105. {
  106. if (*s == '*' && s[1] == '/')
  107. {
  108. cptr = s + 2;
  109. FREE(st_line);
  110. return;
  111. }
  112. if (*s == '\n')
  113. {
  114. get_line();
  115. if (line == 0)
  116. unterminated_comment(st_lineno, st_line, st_cptr);
  117. s = cptr;
  118. }
  119. else
  120. ++s;
  121. }
  122. }
  123. int nextc(void)
  124. {
  125. register char *s;
  126. if (line == 0)
  127. {
  128. get_line();
  129. if (line == 0)
  130. return (EOF);
  131. }
  132. s = cptr;
  133. for (;;)
  134. {
  135. switch (*s)
  136. {
  137. case '\n':
  138. get_line();
  139. if (line == 0) return (EOF);
  140. s = cptr;
  141. break;
  142. case ' ':
  143. case '\t':
  144. case '\f':
  145. case '\r':
  146. case '\v':
  147. case ',':
  148. case ';':
  149. ++s;
  150. break;
  151. case '\\':
  152. cptr = s;
  153. return ('%');
  154. case '/':
  155. if (s[1] == '*')
  156. {
  157. cptr = s;
  158. skip_comment();
  159. s = cptr;
  160. break;
  161. }
  162. else if (s[1] == '/')
  163. {
  164. get_line();
  165. if (line == 0) return (EOF);
  166. s = cptr;
  167. break;
  168. }
  169. /* fall through */
  170. default:
  171. cptr = s;
  172. return (*s);
  173. }
  174. }
  175. }
  176. int keyword(void)
  177. {
  178. register int c;
  179. char *t_cptr = cptr;
  180. c = *++cptr;
  181. if (isalpha(c))
  182. {
  183. cinc = 0;
  184. for (;;)
  185. {
  186. if (isalpha(c))
  187. {
  188. if (isupper(c)) c = tolower(c);
  189. cachec(c);
  190. }
  191. else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  192. cachec(c);
  193. else
  194. break;
  195. c = *++cptr;
  196. }
  197. cachec(NUL);
  198. if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  199. return (TOKEN);
  200. if (strcmp(cache, "type") == 0)
  201. return (TYPE);
  202. if (strcmp(cache, "left") == 0)
  203. return (LEFT);
  204. if (strcmp(cache, "right") == 0)
  205. return (RIGHT);
  206. if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  207. return (NONASSOC);
  208. if (strcmp(cache, "start") == 0)
  209. return (START);
  210. if (strcmp(cache, "union") == 0)
  211. return (UNION);
  212. if (strcmp(cache, "ident") == 0)
  213. return (IDENT);
  214. }
  215. else
  216. {
  217. ++cptr;
  218. if (c == '{')
  219. return (TEXT);
  220. if (c == '%' || c == '\\')
  221. return (MARK);
  222. if (c == '<')
  223. return (LEFT);
  224. if (c == '>')
  225. return (RIGHT);
  226. if (c == '0')
  227. return (TOKEN);
  228. if (c == '2')
  229. return (NONASSOC);
  230. }
  231. syntax_error(lineno, line, t_cptr);
  232. /*NOTREACHED*/
  233. }
  234. void copy_ident(void)
  235. {
  236. register int c;
  237. register FILE *f = output_file;
  238. c = nextc();
  239. if (c == EOF) unexpected_EOF();
  240. if (c != '"') syntax_error(lineno, line, cptr);
  241. ++outline;
  242. fprintf(f, "#ident \"");
  243. for (;;)
  244. {
  245. c = *++cptr;
  246. if (c == '\n')
  247. {
  248. fprintf(f, "\"\n");
  249. return;
  250. }
  251. putc(c, f);
  252. if (c == '"')
  253. {
  254. putc('\n', f);
  255. ++cptr;
  256. return;
  257. }
  258. }
  259. }
  260. void copy_text(void)
  261. {
  262. register int c;
  263. int quote;
  264. register FILE *f = text_file;
  265. int need_newline = 0;
  266. int t_lineno = lineno;
  267. char *t_line = dup_line();
  268. char *t_cptr = t_line + (cptr - line - 2);
  269. if (*cptr == '\n')
  270. {
  271. get_line();
  272. if (line == 0)
  273. unterminated_text(t_lineno, t_line, t_cptr);
  274. }
  275. loop:
  276. c = *cptr++;
  277. switch (c)
  278. {
  279. case '\n':
  280. /* next_line: */
  281. putc('\n', f);
  282. need_newline = 0;
  283. get_line();
  284. if (line) goto loop;
  285. unterminated_text(t_lineno, t_line, t_cptr);
  286. case '`':
  287. case '"':
  288. {
  289. int s_lineno = lineno;
  290. char *s_line = dup_line();
  291. char *s_cptr = s_line + (cptr - line - 1);
  292. quote = c;
  293. putc(c, f);
  294. for (;;)
  295. {
  296. c = *cptr++;
  297. putc(c, f);
  298. if (c == quote)
  299. {
  300. need_newline = 1;
  301. FREE(s_line);
  302. goto loop;
  303. }
  304. if (c == '\n')
  305. unterminated_string(s_lineno, s_line, s_cptr);
  306. if (c == '\\')
  307. {
  308. c = *cptr++;
  309. putc(c, f);
  310. if (c == '\n')
  311. {
  312. get_line();
  313. if (line == 0)
  314. unterminated_string(s_lineno, s_line, s_cptr);
  315. }
  316. }
  317. }
  318. }
  319. case '(':
  320. putc(c, f);
  321. need_newline = 1;
  322. c = *cptr;
  323. if (c == '*')
  324. {
  325. int c_lineno = lineno;
  326. char *c_line = dup_line();
  327. char *c_cptr = c_line + (cptr - line - 1);
  328. putc('*', f);
  329. ++cptr;
  330. for (;;)
  331. {
  332. c = *cptr++;
  333. putc(c, f);
  334. if (c == '*' && *cptr == ')')
  335. {
  336. putc(')', f);
  337. ++cptr;
  338. FREE(c_line);
  339. goto loop;
  340. }
  341. if (c == '\n')
  342. {
  343. get_line();
  344. if (line == 0)
  345. unterminated_comment(c_lineno, c_line, c_cptr);
  346. }
  347. }
  348. }
  349. need_newline = 1;
  350. goto loop;
  351. case '%':
  352. case '\\':
  353. if (*cptr == '}')
  354. {
  355. if (need_newline) putc('\n', f);
  356. ++cptr;
  357. FREE(t_line);
  358. return;
  359. }
  360. /* fall through */
  361. default:
  362. putc(c, f);
  363. need_newline = 1;
  364. goto loop;
  365. }
  366. }
  367. void copy_union(void)
  368. {
  369. register int c;
  370. int quote;
  371. int depth;
  372. int u_lineno = lineno;
  373. char *u_line = dup_line();
  374. char *u_cptr = u_line + (cptr - line - 6);
  375. if (unionized) over_unionized(cptr - 6);
  376. unionized = 1;
  377. if (!lflag)
  378. fprintf(text_file, line_format, lineno, input_file_name);
  379. fprintf(text_file, "typedef union");
  380. if (dflag) fprintf(union_file, "typedef union");
  381. depth = 1;
  382. cptr++;
  383. loop:
  384. c = *cptr++;
  385. putc(c, text_file);
  386. if (dflag) putc(c, union_file);
  387. switch (c)
  388. {
  389. case '\n':
  390. /* next_line: */
  391. get_line();
  392. if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  393. goto loop;
  394. case '{':
  395. ++depth;
  396. goto loop;
  397. case '}':
  398. --depth;
  399. if (c == '}' && depth == 0) {
  400. fprintf(text_file, " YYSTYPE;\n");
  401. FREE(u_line);
  402. return;
  403. }
  404. goto loop;
  405. case '\'':
  406. case '"':
  407. {
  408. int s_lineno = lineno;
  409. char *s_line = dup_line();
  410. char *s_cptr = s_line + (cptr - line - 1);
  411. quote = c;
  412. for (;;)
  413. {
  414. c = *cptr++;
  415. putc(c, text_file);
  416. if (dflag) putc(c, union_file);
  417. if (c == quote)
  418. {
  419. FREE(s_line);
  420. goto loop;
  421. }
  422. if (c == '\n')
  423. unterminated_string(s_lineno, s_line, s_cptr);
  424. if (c == '\\')
  425. {
  426. c = *cptr++;
  427. putc(c, text_file);
  428. if (dflag) putc(c, union_file);
  429. if (c == '\n')
  430. {
  431. get_line();
  432. if (line == 0)
  433. unterminated_string(s_lineno, s_line, s_cptr);
  434. }
  435. }
  436. }
  437. }
  438. case '(':
  439. c = *cptr;
  440. if (c == '*')
  441. {
  442. int c_lineno = lineno;
  443. char *c_line = dup_line();
  444. char *c_cptr = c_line + (cptr - line - 1);
  445. putc('*', text_file);
  446. if (dflag) putc('*', union_file);
  447. ++cptr;
  448. for (;;)
  449. {
  450. c = *cptr++;
  451. putc(c, text_file);
  452. if (dflag) putc(c, union_file);
  453. if (c == '*' && *cptr == ')')
  454. {
  455. putc(')', text_file);
  456. if (dflag) putc(')', union_file);
  457. ++cptr;
  458. FREE(c_line);
  459. goto loop;
  460. }
  461. if (c == '\n')
  462. {
  463. get_line();
  464. if (line == 0)
  465. unterminated_comment(c_lineno, c_line, c_cptr);
  466. }
  467. }
  468. }
  469. goto loop;
  470. default:
  471. goto loop;
  472. }
  473. }
  474. int hexval(int c)
  475. {
  476. if (c >= '0' && c <= '9')
  477. return (c - '0');
  478. if (c >= 'A' && c <= 'F')
  479. return (c - 'A' + 10);
  480. if (c >= 'a' && c <= 'f')
  481. return (c - 'a' + 10);
  482. return (-1);
  483. }
  484. bucket *get_literal(void)
  485. {
  486. register int c, quote;
  487. register int i;
  488. register int n;
  489. register char *s;
  490. register bucket *bp;
  491. int s_lineno = lineno;
  492. char *s_line = dup_line();
  493. char *s_cptr = s_line + (cptr - line);
  494. quote = *cptr++;
  495. cinc = 0;
  496. for (;;)
  497. {
  498. c = *cptr++;
  499. if (c == quote) break;
  500. if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  501. if (c == '\\')
  502. {
  503. char *c_cptr = cptr - 1;
  504. c = *cptr++;
  505. switch (c)
  506. {
  507. case '\n':
  508. get_line();
  509. if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  510. continue;
  511. case '0': case '1': case '2': case '3':
  512. case '4': case '5': case '6': case '7':
  513. n = c - '0';
  514. c = *cptr;
  515. if (IS_OCTAL(c))
  516. {
  517. n = (n << 3) + (c - '0');
  518. c = *++cptr;
  519. if (IS_OCTAL(c))
  520. {
  521. n = (n << 3) + (c - '0');
  522. ++cptr;
  523. }
  524. }
  525. if (n > MAXCHAR) illegal_character(c_cptr);
  526. c = n;
  527. break;
  528. case 'x':
  529. c = *cptr++;
  530. n = hexval(c);
  531. if (n < 0 || n >= 16)
  532. illegal_character(c_cptr);
  533. for (;;)
  534. {
  535. c = *cptr;
  536. i = hexval(c);
  537. if (i < 0 || i >= 16) break;
  538. ++cptr;
  539. n = (n << 4) + i;
  540. if (n > MAXCHAR) illegal_character(c_cptr);
  541. }
  542. c = n;
  543. break;
  544. case 'a': c = 7; break;
  545. case 'b': c = '\b'; break;
  546. case 'f': c = '\f'; break;
  547. case 'n': c = '\n'; break;
  548. case 'r': c = '\r'; break;
  549. case 't': c = '\t'; break;
  550. case 'v': c = '\v'; break;
  551. }
  552. }
  553. cachec(c);
  554. }
  555. FREE(s_line);
  556. n = cinc;
  557. s = MALLOC(n);
  558. if (s == 0) no_space();
  559. for (i = 0; i < n; ++i)
  560. s[i] = cache[i];
  561. cinc = 0;
  562. if (n == 1)
  563. cachec('\'');
  564. else
  565. cachec('"');
  566. for (i = 0; i < n; ++i)
  567. {
  568. c = ((unsigned char *)s)[i];
  569. if (c == '\\' || c == cache[0])
  570. {
  571. cachec('\\');
  572. cachec(c);
  573. }
  574. else if (isprint(c))
  575. cachec(c);
  576. else
  577. {
  578. cachec('\\');
  579. switch (c)
  580. {
  581. case 7: cachec('a'); break;
  582. case '\b': cachec('b'); break;
  583. case '\f': cachec('f'); break;
  584. case '\n': cachec('n'); break;
  585. case '\r': cachec('r'); break;
  586. case '\t': cachec('t'); break;
  587. case '\v': cachec('v'); break;
  588. default:
  589. cachec(((c >> 6) & 7) + '0');
  590. cachec(((c >> 3) & 7) + '0');
  591. cachec((c & 7) + '0');
  592. break;
  593. }
  594. }
  595. }
  596. if (n == 1)
  597. cachec('\'');
  598. else
  599. cachec('"');
  600. cachec(NUL);
  601. bp = lookup(cache);
  602. bp->class = TERM;
  603. if (n == 1 && bp->value == UNDEFINED)
  604. bp->value = *(unsigned char *)s;
  605. FREE(s);
  606. return (bp);
  607. }
  608. int is_reserved(char *name)
  609. {
  610. char *s;
  611. if (strcmp(name, ".") == 0 ||
  612. strcmp(name, "$accept") == 0 ||
  613. strcmp(name, "$end") == 0)
  614. return (1);
  615. if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  616. {
  617. s = name + 3;
  618. while (isdigit(*s)) ++s;
  619. if (*s == NUL) return (1);
  620. }
  621. return (0);
  622. }
  623. bucket *get_name(void)
  624. {
  625. register int c;
  626. cinc = 0;
  627. for (c = *cptr; IS_IDENT(c); c = *++cptr)
  628. cachec(c);
  629. cachec(NUL);
  630. if (is_reserved(cache)) used_reserved(cache);
  631. return (lookup(cache));
  632. }
  633. int get_number(void)
  634. {
  635. register int c;
  636. register int n;
  637. n = 0;
  638. for (c = *cptr; isdigit(c); c = *++cptr)
  639. n = 10*n + (c - '0');
  640. return (n);
  641. }
  642. char *get_tag(void)
  643. {
  644. register int c;
  645. register int i;
  646. register char *s;
  647. int t_lineno = lineno;
  648. char *t_line = dup_line();
  649. char *t_cptr = t_line + (cptr - line);
  650. cinc = 0;
  651. {int last = ' '; /* The character preceding the current one (c) */
  652. while (1) {
  653. c = *++cptr;
  654. if (c == '\n')
  655. {last = c; c = nextc(); }
  656. if (c == EOF) unexpected_EOF();
  657. /* Do not take `->' to signify the end of a type specification: */
  658. if ((c == '>') && (last != '-')) break;
  659. cachec(c); last = c;
  660. } }
  661. ++cptr;
  662. cachec(NUL);
  663. for (i = 0; i < ntags; ++i)
  664. {
  665. if (strcmp(cache, tag_table[i]) == 0)
  666. return (tag_table[i]);
  667. }
  668. if (ntags >= tagmax)
  669. {
  670. tagmax += 16;
  671. tag_table = (char **)
  672. (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  673. : MALLOC(tagmax*sizeof(char *)));
  674. if (tag_table == 0) no_space();
  675. }
  676. s = MALLOC(cinc);
  677. if (s == 0) no_space();
  678. strcpy(s, cache);
  679. tag_table[ntags] = s;
  680. ++ntags;
  681. FREE(t_line);
  682. return (s);
  683. }
  684. void declare_tokens(int assoc)
  685. {
  686. register int c;
  687. register bucket *bp;
  688. int value;
  689. char *tag = 0;
  690. if (assoc != TOKEN) ++prec;
  691. c = nextc();
  692. if (c == EOF) unexpected_EOF();
  693. if (c == '<')
  694. {
  695. tag = get_tag();
  696. c = nextc();
  697. if (c == EOF) unexpected_EOF();
  698. }
  699. for (;;)
  700. {
  701. if (isalpha(c) || c == '_' || c == '.' || c == '$')
  702. bp = get_name();
  703. else if (c == '\'' || c == '"')
  704. bp = get_literal();
  705. else
  706. return;
  707. if (bp == goal) tokenized_start(bp->name);
  708. bp->class = TERM;
  709. if (tag)
  710. {
  711. if (bp->tag && tag != bp->tag)
  712. retyped_warning(bp->name);
  713. bp->tag = tag;
  714. }
  715. if (assoc == TOKEN)
  716. {
  717. bp->true_token = 1;
  718. }
  719. else
  720. {
  721. if (bp->prec && prec != bp->prec)
  722. reprec_warning(bp->name);
  723. bp->assoc = assoc;
  724. bp->prec = prec;
  725. }
  726. c = nextc();
  727. if (c == EOF) unexpected_EOF();
  728. value = UNDEFINED;
  729. /* It makes no sense in mosmlyac to explicit specify the tag
  730. number of a token or symbol (sestoft 2000-04-28):
  731. if (isdigit(c))
  732. {
  733. value = get_number();
  734. if (bp->value != UNDEFINED && value != bp->value)
  735. revalued_warning(bp->name);
  736. bp->value = value;
  737. c = nextc();
  738. if (c == EOF) unexpected_EOF();
  739. }
  740. */
  741. }
  742. }
  743. void declare_types(void)
  744. {
  745. register int c;
  746. register bucket *bp;
  747. char *tag;
  748. c = nextc();
  749. if (c == EOF) unexpected_EOF();
  750. if (c != '<') syntax_error(lineno, line, cptr);
  751. tag = get_tag();
  752. for (;;)
  753. {
  754. c = nextc();
  755. if (isalpha(c) || c == '_' || c == '.' || c == '$')
  756. bp = get_name();
  757. else if (c == '\'' || c == '"')
  758. bp = get_literal();
  759. else
  760. return;
  761. if (bp->tag && tag != bp->tag)
  762. retyped_warning(bp->name);
  763. bp->tag = tag;
  764. }
  765. }
  766. void declare_start(void)
  767. {
  768. register int c;
  769. register bucket *bp;
  770. static int entry_counter = 0;
  771. c = nextc();
  772. if (c == EOF) unexpected_EOF();
  773. if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  774. syntax_error(lineno, line, cptr);
  775. bp = get_name();
  776. if (bp->class == TERM)
  777. terminal_start(bp->name);
  778. bp->entry = ++entry_counter;
  779. if (entry_counter == 256)
  780. too_many_entries();
  781. }
  782. void read_declarations(void)
  783. {
  784. register int c, k;
  785. cache_size = 256;
  786. cache = MALLOC(cache_size);
  787. if (cache == 0) no_space();
  788. for (;;)
  789. {
  790. c = nextc();
  791. if (c == EOF) unexpected_EOF();
  792. if (c != '%') syntax_error(lineno, line, cptr);
  793. switch (k = keyword())
  794. {
  795. case MARK:
  796. return;
  797. case IDENT:
  798. copy_ident();
  799. break;
  800. case TEXT:
  801. copy_text();
  802. break;
  803. case UNION:
  804. copy_union();
  805. break;
  806. case TOKEN:
  807. case LEFT:
  808. case RIGHT:
  809. case NONASSOC:
  810. declare_tokens(k);
  811. break;
  812. case TYPE:
  813. declare_types();
  814. break;
  815. case START:
  816. declare_start();
  817. break;
  818. }
  819. }
  820. }
  821. /* Order tokens lexicographically by modifying next-pointers, first_symbol */
  822. int tokcompare(const void* bpp1, const void* bpp2)
  823. { return strcmp((*((bucket**)bpp1))->name, (*((bucket**)bpp2))->name); }
  824. void sort_tokens() {
  825. int i;
  826. bucket *bp;
  827. /* Count tokens */
  828. ntruetokens = 0;
  829. for (bp = first_symbol; bp; bp = bp->next)
  830. if (bp->class == TERM && bp->true_token)
  831. ++ntruetokens;
  832. sortedtokens = (bucket **) MALLOC(ntruetokens*sizeof(bucket *));
  833. if (sortedtokens == 0) no_space();
  834. i = 0;
  835. for (bp = first_symbol; bp; bp = bp->next)
  836. if (bp->class == TERM && bp->true_token)
  837. sortedtokens[i++] = bp;
  838. assert(i == ntruetokens);
  839. /* Sort sortedtokens[0..ntruetokens-1] in alphabetical order: */
  840. qsort(sortedtokens, ntruetokens, sizeof(bucket*), tokcompare);
  841. /* Assign explicit token values based on the alphabetical ordering: */
  842. /* (... and pray that later code does not screw up these values) */
  843. for (i=0; i<ntruetokens; i++)
  844. sortedtokens[i]->value = i+257;
  845. }
  846. void output_token_type(FILE *output_file)
  847. {
  848. bucket * bp;
  849. int n, tyno;
  850. int i;
  851. bucket **sorted;
  852. fprintf(output_file, "local\n");
  853. /* Make type abbreviations for types that may be products or records: */
  854. tyno = 1;
  855. for (i = 0; i<ntruetokens; i++) {
  856. bp = sortedtokens[i];
  857. if (bp->tag && (strchr(bp->tag, '*') || strchr(bp->tag, '{')))
  858. {
  859. fprintf(output_file, "type t__%d__ = %s\n", tyno, bp->tag);
  860. tyno++;
  861. }
  862. }
  863. fprintf(output_file, "in\n");
  864. /* Output the token datatype, using the type abbreviations: */
  865. fprintf(output_file, "datatype token =\n");
  866. n = 0; tyno = 1;
  867. for (i = 0; i<ntruetokens; i++) {
  868. bp = sortedtokens[i];
  869. if (bp->class == TERM && bp->true_token) {
  870. fprintf(output_file, " %c %s", n == 0 ? ' ' : '|', bp->name);
  871. if (bp->tag) {
  872. /* If it may be a product or record,
  873. there is an abbreviation t__nn__ for it: */
  874. if (strchr(bp->tag, '*') || strchr(bp->tag, '{')) {
  875. fprintf(output_file, " of t__%d__", tyno);
  876. tyno++;
  877. } else {
  878. fprintf(output_file, " of %s", bp->tag); }
  879. }
  880. fprintf(output_file, "\n");
  881. n++;
  882. }
  883. }
  884. fprintf(output_file, "end;\n\n");
  885. }
  886. void initialize_grammar(void)
  887. {
  888. nitems = 4;
  889. maxitems = 300;
  890. pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  891. if (pitem == 0) no_space();
  892. pitem[0] = 0;
  893. pitem[1] = 0;
  894. pitem[2] = 0;
  895. pitem[3] = 0;
  896. nrules = 3;
  897. maxrules = 100;
  898. plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  899. if (plhs == 0) no_space();
  900. plhs[0] = 0;
  901. plhs[1] = 0;
  902. plhs[2] = 0;
  903. rprec = (short *) MALLOC(maxrules*sizeof(short));
  904. if (rprec == 0) no_space();
  905. rprec[0] = 0;
  906. rprec[1] = 0;
  907. rprec[2] = 0;
  908. rassoc = (char *) MALLOC(maxrules*sizeof(char));
  909. if (rassoc == 0) no_space();
  910. rassoc[0] = TOKEN;
  911. rassoc[1] = TOKEN;
  912. rassoc[2] = TOKEN;
  913. }
  914. void expand_items(void)
  915. {
  916. maxitems += 300;
  917. pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  918. if (pitem == 0) no_space();
  919. }
  920. void expand_rules(void)
  921. {
  922. maxrules += 100;
  923. plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  924. if (plhs == 0) no_space();
  925. rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  926. if (rprec == 0) no_space();
  927. rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  928. if (rassoc == 0) no_space();
  929. }
  930. void advance_to_start(void)
  931. {
  932. register int c;
  933. register bucket *bp;
  934. char *s_cptr;
  935. int s_lineno;
  936. for (;;)
  937. {
  938. c = nextc();
  939. if (c != '%') break;
  940. s_cptr = cptr;
  941. switch (keyword())
  942. {
  943. case MARK:
  944. no_grammar();
  945. case TEXT:
  946. copy_text();
  947. break;
  948. case START:
  949. declare_start();
  950. break;
  951. default:
  952. syntax_error(lineno, line, s_cptr);
  953. }
  954. }
  955. c = nextc();
  956. if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  957. syntax_error(lineno, line, cptr);
  958. bp = get_name();
  959. if (goal == 0)
  960. {
  961. if (bp->class == TERM)
  962. terminal_start(bp->name);
  963. goal = bp;
  964. }
  965. s_lineno = lineno;
  966. c = nextc();
  967. if (c == EOF) unexpected_EOF();
  968. if (c != ':') syntax_error(lineno, line, cptr);
  969. start_rule(bp, s_lineno);
  970. ++cptr;
  971. }
  972. void start_rule(register bucket *bp, int s_lineno)
  973. {
  974. if (bp->class == TERM)
  975. terminal_lhs(s_lineno);
  976. bp->class = NONTERM;
  977. if (nrules >= maxrules)
  978. expand_rules();
  979. plhs[nrules] = bp;
  980. rprec[nrules] = UNDEFINED;
  981. rassoc[nrules] = TOKEN;
  982. }
  983. void end_rule(void)
  984. {
  985. register int i;
  986. if (!last_was_action && plhs[nrules]->tag)
  987. {
  988. for (i = nitems - 1; pitem[i]; --i) continue;
  989. if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
  990. default_action_warning();
  991. }
  992. last_was_action = 0;
  993. if (nitems >= maxitems) expand_items();
  994. pitem[nitems] = 0;
  995. ++nitems;
  996. ++nrules;
  997. }
  998. void insert_empty_rule(void)
  999. {
  1000. register bucket *bp, **bpp;
  1001. assert(cache);
  1002. sprintf(cache, "$$%d", ++gensym);
  1003. bp = make_bucket(cache);
  1004. last_symbol->next = bp;
  1005. last_symbol = bp;
  1006. bp->tag = plhs[nrules]->tag;
  1007. bp->class = NONTERM;
  1008. if ((nitems += 2) > maxitems)
  1009. expand_items();
  1010. bpp = pitem + nitems - 1;
  1011. *bpp-- = bp;
  1012. while (bpp[0] = bpp[-1]) --bpp;
  1013. if (++nrules >= maxrules)
  1014. expand_rules();
  1015. plhs[nrules] = plhs[nrules-1];
  1016. plhs[nrules-1] = bp;
  1017. rprec[nrules] = rprec[nrules-1];
  1018. rprec[nrules-1] = 0;
  1019. rassoc[nrules] = rassoc[nrules-1];
  1020. rassoc[nrules-1] = TOKEN;
  1021. }
  1022. void add_symbol(void)
  1023. {
  1024. register int c;
  1025. register bucket *bp;
  1026. int s_lineno = lineno;
  1027. c = *cptr;
  1028. if (c == '\'' || c == '"')
  1029. bp = get_literal();
  1030. else
  1031. bp = get_name();
  1032. c = nextc();
  1033. if (c == ':')
  1034. {
  1035. end_rule();
  1036. start_rule(bp, s_lineno);
  1037. ++cptr;
  1038. return;
  1039. }
  1040. if (last_was_action)
  1041. insert_empty_rule();
  1042. last_was_action = 0;
  1043. if (++nitems > maxitems)
  1044. expand_items();
  1045. pitem[nitems-1] = bp;
  1046. }
  1047. void copy_action(void)
  1048. {
  1049. register int c;
  1050. register int i, n;
  1051. int depth;
  1052. int quote;
  1053. bucket *item;
  1054. char *tagres;
  1055. register FILE *f = action_file;
  1056. int a_lineno = lineno;
  1057. char *a_line = dup_line();
  1058. char *a_cptr = a_line + (cptr - line);
  1059. if (last_was_action)
  1060. insert_empty_rule();
  1061. last_was_action = 1;
  1062. fprintf(f, "(* Rule %d, file %s, line %d *)\n",
  1063. nrules-2, input_file_name, lineno);
  1064. n = 0;
  1065. for (i = nitems - 1; pitem[i]; --i) ++n;
  1066. /* Let-bind all $'s early in the semantic action, outside any function
  1067. closure:
  1068. let val d__1__ = peekVal (n-1)
  1069. val d__2__ = peekVal (n-2)
  1070. ...
  1071. val d__n__ = peekVal 0
  1072. in ... semantic action ...
  1073. end
  1074. */
  1075. fprintf(f, "val _ = update_ yyact %d\n(fn () => repr(let\n", nrules-2);
  1076. for (i = 1; i <= n; i++)
  1077. { item = pitem[nitems + i - n - 1];
  1078. if (item->tag)
  1079. fprintf(f, "val d__%d__ = peekVal %d : %s\n", i, n - i, item->tag);
  1080. }
  1081. fprintf(f, "in\n(");
  1082. depth = 1;
  1083. cptr++;
  1084. loop:
  1085. c = *cptr;
  1086. if (c == '$')
  1087. {
  1088. if (isdigit(cptr[1]))
  1089. {
  1090. ++cptr;
  1091. i = get_number();
  1092. if (i <= 0 || i > n)
  1093. unknown_rhs(i);
  1094. item = pitem[nitems + i - n - 1];
  1095. if (item->tag) {
  1096. fprintf(f, "(d__%d__)", i);
  1097. } else {
  1098. if (item->class == TERM)
  1099. { illegal_token_ref(i, item->name); }
  1100. else
  1101. { missing_type(item->name); }
  1102. /* This trick, which works in Caml Light and Edinburgh ML,
  1103. * cannot be used in Standard ML to improve type security:
  1104. * if (sflag)
  1105. * fprintf(f, "(peekVal %d)", n - i);
  1106. * else
  1107. * fprintf(f, "(peekVal %d : '%s)", n - i, item->name);
  1108. */
  1109. }
  1110. goto loop;
  1111. }
  1112. }
  1113. if (isalpha(c) || c == '_' || c == '$')
  1114. {
  1115. do
  1116. {
  1117. putc(c, f);
  1118. c = *++cptr;
  1119. } while (isalnum(c) || c == '_' || c == '$');
  1120. goto loop;
  1121. }
  1122. if (c == '}' && depth == 1) {
  1123. cptr++;
  1124. tagres = plhs[nrules]->tag;
  1125. if (tagres)
  1126. { fprintf(f, ") end : %s))\n", tagres); }
  1127. else
  1128. { missing_type(plhs[nrules]->name); }
  1129. /* Same problem as above: don't insert type ascriptions:
  1130. * if (sflag)
  1131. * fprintf(f, ")))\n");
  1132. * else
  1133. * fprintf(f, ") : '%s))\n", plhs[nrules]->name);
  1134. */
  1135. /* if (sflag) */
  1136. fprintf(f, ";\n");
  1137. return;
  1138. }
  1139. putc(c, f);
  1140. ++cptr;
  1141. switch (c)
  1142. {
  1143. case '\n':
  1144. /* next_line: */
  1145. get_line();
  1146. if (line) goto loop;
  1147. unterminated_action(a_lineno, a_line, a_cptr);
  1148. case '{':
  1149. ++depth;
  1150. goto loop;
  1151. case '}':
  1152. --depth;
  1153. goto loop;
  1154. case '`':
  1155. case '"':
  1156. {
  1157. int s_lineno = lineno;
  1158. char *s_line = dup_line();
  1159. char *s_cptr = s_line + (cptr - line - 1);
  1160. quote = c;
  1161. for (;;)
  1162. {
  1163. c = *cptr++;
  1164. putc(c, f);
  1165. if (c == quote)
  1166. {
  1167. FREE(s_line);
  1168. goto loop;
  1169. }
  1170. if (c == '\n')
  1171. unterminated_string(s_lineno, s_line, s_cptr);
  1172. if (c == '\\')
  1173. {
  1174. c = *cptr++;
  1175. putc(c, f);
  1176. if (c == '\n')
  1177. {
  1178. get_line();
  1179. if (line == 0)
  1180. unterminated_string(s_lineno, s_line, s_cptr);
  1181. }
  1182. }
  1183. }
  1184. }
  1185. case '(':
  1186. c = *cptr;
  1187. if (c == '*')
  1188. {
  1189. int c_lineno = lineno;
  1190. char *c_line = dup_line();
  1191. char *c_cptr = c_line + (cptr - line - 1);
  1192. putc('*', f);
  1193. ++cptr;
  1194. for (;;)
  1195. {
  1196. c = *cptr++;
  1197. putc(c, f);
  1198. if (c == '*' && *cptr == ')')
  1199. {
  1200. putc(')', f);
  1201. ++cptr;
  1202. FREE(c_line);
  1203. goto loop;
  1204. }
  1205. if (c == '\n')
  1206. {
  1207. get_line();
  1208. if (line == 0)
  1209. unterminated_comment(c_lineno, c_line, c_cptr);
  1210. }
  1211. }
  1212. }
  1213. goto loop;
  1214. default:
  1215. goto loop;
  1216. }
  1217. }
  1218. int mark_symbol(void)
  1219. {
  1220. register int c;
  1221. register bucket *bp;
  1222. c = cptr[1];
  1223. if (c == '%' || c == '\\')
  1224. {
  1225. cptr += 2;
  1226. return (1);
  1227. }
  1228. if (c == '=')
  1229. cptr += 2;
  1230. else if ((c == 'p' || c == 'P') &&
  1231. ((c = cptr[2]) == 'r' || c == 'R') &&
  1232. ((c = cptr[3]) == 'e' || c == 'E') &&
  1233. ((c = cptr[4]) == 'c' || c == 'C') &&
  1234. ((c = cptr[5], !IS_IDENT(c))))
  1235. cptr += 5;
  1236. else
  1237. syntax_error(lineno, line, cptr);
  1238. c = nextc();
  1239. if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1240. bp = get_name();
  1241. else if (c == '\'' || c == '"')
  1242. bp = get_literal();
  1243. else
  1244. {
  1245. syntax_error(lineno, line, cptr);
  1246. /*NOTREACHED*/
  1247. }
  1248. if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1249. prec_redeclared();
  1250. rprec[nrules] = bp->prec;
  1251. rassoc[nrules] = bp->assoc;
  1252. return (0);
  1253. }
  1254. void read_grammar(void)
  1255. {
  1256. register int c;
  1257. initialize_grammar();
  1258. advance_to_start();
  1259. for (;;)
  1260. {
  1261. c = nextc();
  1262. if (c == EOF) break;
  1263. if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1264. c == '"')
  1265. add_symbol();
  1266. else if (c == '{' || c == '=')
  1267. copy_action();
  1268. else if (c == '|')
  1269. {
  1270. end_rule();
  1271. start_rule(plhs[nrules-1], 0);
  1272. ++cptr;
  1273. }
  1274. else if (c == '%')
  1275. {
  1276. if (mark_symbol()) break;
  1277. }
  1278. else
  1279. syntax_error(lineno, line, cptr);
  1280. }
  1281. end_rule();
  1282. }
  1283. void free_tags(void)
  1284. {
  1285. register int i;
  1286. if (tag_table == 0) return;
  1287. for (i = 0; i < ntags; ++i)
  1288. {
  1289. assert(tag_table[i]);
  1290. FREE(tag_table[i]);
  1291. }
  1292. FREE(tag_table);
  1293. }
  1294. void pack_names(void)
  1295. {
  1296. register bucket *bp;
  1297. register char *p, *s, *t;
  1298. name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
  1299. for (bp = first_symbol; bp; bp = bp->next)
  1300. name_pool_size += strlen(bp->name) + 1;
  1301. name_pool = MALLOC(name_pool_size);
  1302. if (name_pool == 0) no_space();
  1303. strcpy(name_pool, "$accept");
  1304. strcpy(name_pool+8, "$end");
  1305. t = name_pool + 13;
  1306. for (bp = first_symbol; bp; bp = bp->next)
  1307. {
  1308. p = t;
  1309. s = bp->name;
  1310. while (*t++ = *s++) continue;
  1311. FREE(bp->name);
  1312. bp->name = p;
  1313. }
  1314. }
  1315. void check_symbols(void)
  1316. {
  1317. register bucket *bp;
  1318. if (goal->class == UNKNOWN)
  1319. undefined_goal(goal->name);
  1320. for (bp = first_symbol; bp; bp = bp->next)
  1321. {
  1322. if (bp->class == UNKNOWN)
  1323. {
  1324. undefined_symbol_warning(bp->name);
  1325. bp->class = TERM;
  1326. }
  1327. }
  1328. }
  1329. void pack_symbols(void)
  1330. {
  1331. register bucket *bp;
  1332. register bucket **v;
  1333. register int i, j, k, n, itrue;
  1334. nsyms = 2;
  1335. ntokens = 1;
  1336. for (bp = first_symbol; bp; bp = bp->next)
  1337. {
  1338. ++nsyms;
  1339. if (bp->class == TERM) ++ntokens;
  1340. }
  1341. start_symbol = ntokens;
  1342. nvars = nsyms - ntokens;
  1343. symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1344. if (symbol_name == 0) no_space();
  1345. symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1346. if (symbol_value == 0) no_space();
  1347. symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1348. if (symbol_prec == 0) no_space();
  1349. symbol_assoc = MALLOC(nsyms);
  1350. if (symbol_assoc == 0) no_space();
  1351. symbol_tag = (char **) MALLOC(nsyms*sizeof(char *));
  1352. if (symbol_tag == 0) no_space();
  1353. symbol_true_token = (char *) MALLOC(nsyms*sizeof(char));
  1354. if (symbol_true_token == 0) no_space();
  1355. v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1356. if (v == 0) no_space();
  1357. v[0] = 0;
  1358. v[start_symbol] = 0;
  1359. i = 1;
  1360. itrue = 0;
  1361. j = start_symbol + 1;
  1362. for (bp = first_symbol; bp; bp = bp->next)
  1363. {
  1364. if (bp->class == TERM) {
  1365. if (bp->true_token)
  1366. v[i] = sortedtokens[itrue++];
  1367. else
  1368. v[i] = bp;
  1369. i++;
  1370. } else
  1371. v[j++] = bp;
  1372. }
  1373. assert(i == ntokens && j == nsyms);
  1374. for (i = 1; i < ntokens; ++i)
  1375. v[i]->index = i;
  1376. goal->index = start_symbol + 1;
  1377. k = start_symbol + 2;
  1378. while (++i < nsyms)
  1379. if (v[i] != goal)
  1380. {
  1381. v[i]->index = k;
  1382. ++k;
  1383. }
  1384. goal->value = 0;
  1385. k = 1;
  1386. for (i = start_symbol + 1; i < nsyms; ++i)
  1387. {
  1388. if (v[i] != goal)
  1389. {
  1390. v[i]->value = k;
  1391. ++k;
  1392. }
  1393. }
  1394. k = 0;
  1395. /* This (assigns and) sorts the symbol_value fields for tokens
  1396. by insertion sort */
  1397. /* It appears to be pretty useless (or dangerous) in the context
  1398. of mosmlyac */
  1399. for (i = 1; i < ntokens; ++i)
  1400. {
  1401. n = v[i]->value;
  1402. if (n > 256)
  1403. {
  1404. for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1405. symbol_value[j] = symbol_value[j-1];
  1406. symbol_value[j] = n;
  1407. }
  1408. }
  1409. if (v[1]->value == UNDEFINED)
  1410. v[1]->value = 256;
  1411. j = 0;
  1412. n = 257;
  1413. for (i = 2; i < ntokens; ++i)
  1414. {
  1415. if (v[i]->value == UNDEFINED)
  1416. {
  1417. while (j < k && n == symbol_value[j])
  1418. {
  1419. while (++j < k && n == symbol_value[j]) continue;
  1420. ++n;
  1421. }
  1422. v[i]->value = n;
  1423. ++n;
  1424. }
  1425. }
  1426. symbol_name[0] = name_pool + 8;
  1427. symbol_value[0] = 0;
  1428. symbol_prec[0] = 0;
  1429. symbol_assoc[0] = TOKEN;
  1430. symbol_tag[0] = "";
  1431. symbol_true_token[0] = 0;
  1432. for (i = 1; i < ntokens; ++i)
  1433. {
  1434. symbol_name[i] = v[i]->name;
  1435. symbol_value[i] = v[i]->value;
  1436. symbol_prec[i] = v[i]->prec;
  1437. symbol_assoc[i] = v[i]->assoc;
  1438. symbol_tag[i] = v[i]->tag;
  1439. symbol_true_token[i] = v[i]->true_token;
  1440. }
  1441. symbol_name[start_symbol] = name_pool;
  1442. symbol_value[start_symbol] = -1;
  1443. symbol_prec[start_symbol] = 0;
  1444. symbol_assoc[start_symbol] = TOKEN;
  1445. symbol_tag[start_symbol] = "";
  1446. symbol_true_token[start_symbol] = 0;
  1447. for (++i; i < nsyms; ++i)
  1448. {
  1449. k = v[i]->index;
  1450. symbol_name[k] = v[i]->name;
  1451. symbol_value[k] = v[i]->value;
  1452. symbol_prec[k] = v[i]->prec;
  1453. symbol_assoc[k] = v[i]->assoc;
  1454. symbol_tag[i] = v[i]->tag;
  1455. symbol_true_token[i] = v[i]->true_token;
  1456. }
  1457. FREE(v);
  1458. }
  1459. void make_goal(void)
  1460. {
  1461. static char name[7] = "'\\xxx'";
  1462. bucket * bp;
  1463. bucket * bc;
  1464. goal = lookup("%entry%");
  1465. ntotalrules = nrules - 2;
  1466. for(bp = first_symbol; bp != 0; bp = bp->next) {
  1467. if (bp->entry) {
  1468. start_rule(goal, 0);
  1469. if (nitems + 2> maxitems)
  1470. expand_items();
  1471. name[2] = '0' + ((bp->entry >> 6) & 7);
  1472. name[3] = '0' + ((bp->entry >> 3) & 7);
  1473. name[4] = '0' + (bp->entry & 7);
  1474. bc = lookup(name);
  1475. bc->class = TERM;
  1476. bc->value = (unsigned char) bp->entry;
  1477. pitem[nitems++] = bc;
  1478. pitem[nitems++] = bp;
  1479. fprintf(entry_file,
  1480. "fun %s lexer lexbuf = yyparse yytables %d lexer lexbuf;\n",
  1481. bp->name, bp->entry);
  1482. if (bp->tag == NULL)
  1483. missing_type(bp->name);
  1484. fprintf(interface_file,
  1485. "val %s :\n (Lexing.lexbuf -> token) -> Lexing.lexbuf -> %s;\n",
  1486. bp->name,
  1487. bp->tag);
  1488. fprintf(action_file,
  1489. "(* Entry %s *)\n", bp->name);
  1490. fprintf(action_file,
  1491. "val _ = update_ yyact %d (fn () => raise yyexit (peekVal 0));\n",
  1492. ntotalrules);
  1493. ntotalrules++;
  1494. last_was_action = 1;
  1495. end_rule();
  1496. }
  1497. }
  1498. }
  1499. void pack_grammar(void)
  1500. {
  1501. register int i, j;
  1502. int assoc, prec;
  1503. ritem = (short *) MALLOC(nitems*sizeof(short));
  1504. if (ritem == 0) no_space();
  1505. rlhs = (short *) MALLOC(nrules*sizeof(short));
  1506. if (rlhs == 0) no_space();
  1507. rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1508. if (rrhs == 0) no_space();
  1509. rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1510. if (rprec == 0) no_space();
  1511. rassoc = REALLOC(rassoc, nrules);
  1512. if (rassoc == 0) no_space();
  1513. ritem[0] = -1;
  1514. ritem[1] = goal->index;
  1515. ritem[2] = 0;
  1516. ritem[3] = -2;
  1517. rlhs[0] = 0;
  1518. rlhs[1] = 0;
  1519. rlhs[2] = start_symbol;
  1520. rrhs[0] = 0;
  1521. rrhs[1] = 0;
  1522. rrhs[2] = 1;
  1523. j = 4;
  1524. for (i = 3; i < nrules; ++i)
  1525. {
  1526. rlhs[i] = plhs[i]->index;
  1527. rrhs[i] = j;
  1528. assoc = TOKEN;
  1529. prec = 0;
  1530. while (pitem[j])
  1531. {
  1532. ritem[j] = pitem[j]->index;
  1533. if (pitem[j]->class == TERM)
  1534. {
  1535. prec = pitem[j]->prec;
  1536. assoc = pitem[j]->assoc;
  1537. }
  1538. ++j;
  1539. }
  1540. ritem[j] = -i;
  1541. ++j;
  1542. if (rprec[i] == UNDEFINED)
  1543. {
  1544. rprec[i] = prec;
  1545. rassoc[i] = assoc;
  1546. }
  1547. }
  1548. rrhs[i] = j;
  1549. FREE(plhs);
  1550. FREE(pitem);
  1551. }
  1552. void print_grammar(void)
  1553. {
  1554. register int i, j, k;
  1555. int spacing;
  1556. register FILE *f = verbose_file;
  1557. if (!vflag) return;
  1558. k = 1;
  1559. for (i = 2; i < nrules; ++i)
  1560. {
  1561. if (rlhs[i] != rlhs[i-1])
  1562. {
  1563. if (i != 2) fprintf(f, "\n");
  1564. fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
  1565. spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1566. }
  1567. else
  1568. {
  1569. fprintf(f, "%4d ", i - 2);
  1570. j = spacing;
  1571. while (--j >= 0) putc(' ', f);
  1572. putc('|', f);
  1573. }
  1574. while (ritem[k] >= 0)
  1575. {
  1576. fprintf(f, " %s", symbol_name[ritem[k]]);
  1577. ++k;
  1578. }
  1579. ++k;
  1580. putc('\n', f);
  1581. }
  1582. }
  1583. void reader(void)
  1584. {
  1585. create_symbol_table();
  1586. read_declarations();
  1587. sort_tokens();
  1588. output_token_type(interface_file);
  1589. output_token_type(code_file);
  1590. read_grammar();
  1591. make_goal();
  1592. free_symbol_table();
  1593. free_tags();
  1594. pack_names();
  1595. check_symbols();
  1596. pack_symbols();
  1597. pack_grammar();
  1598. free_symbols();
  1599. print_grammar();
  1600. }