/usr.bin/yacc/reader.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1924 lines · 1701 code · 186 blank · 37 comment · 474 complexity · 6b4a20320a9583d372b80dab8ea55ec2 MD5 · raw file

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