lburg.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <stdarg.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include "lburg.h"
  9. static char rcsid[] = "lburg.c - faked rcsid";
  10. static char *prefix = "";
  11. static int Tflag = 0;
  12. static int ntnumber = 0;
  13. static Nonterm start = 0;
  14. static Term terms;
  15. static Nonterm nts;
  16. static Rule rules;
  17. static int nrules;
  18. static struct block {
  19. struct block *link;
  20. } *memlist; /* list of allocated blocks */
  21. static char *stringf(char *fmt, ...);
  22. static void print(char *fmt, ...);
  23. static void ckreach(Nonterm p);
  24. static void emitclosure(Nonterm nts);
  25. static void emitcost(Tree t, char *v);
  26. static void emitdefs(Nonterm nts, int ntnumber);
  27. static void emitheader(void);
  28. static void emitkids(Rule rules, int nrules);
  29. static void emitnts(Rule rules, int nrules);
  30. static void emitrecalc(char *pre, Term root, Term kid);
  31. static void emitrecord(char *pre, Rule r, char *c, int cost);
  32. static void emitrule(Nonterm nts);
  33. static void emitlabel(Term terms, Nonterm start, int ntnumber);
  34. static void emitstring(Rule rules);
  35. static void emitstruct(Nonterm nts, int ntnumber);
  36. static void emittest(Tree t, char *v, char *suffix);
  37. int main(int argc, char *argv[]) {
  38. int c, i;
  39. Nonterm p;
  40. for (i = 1; i < argc; i++)
  41. if (strcmp(argv[i], "-T") == 0)
  42. Tflag = 1;
  43. else if (strncmp(argv[i], "-p", 2) == 0 && argv[i][2])
  44. prefix = &argv[i][2];
  45. else if (strncmp(argv[i], "-p", 2) == 0 && i + 1 < argc)
  46. prefix = argv[++i];
  47. else if (*argv[i] == '-' && argv[i][1]) {
  48. yyerror("usage: %s [-T | -p prefix]... [ [ input ] output ] \n",
  49. argv[0]);
  50. exit(1);
  51. } else if (infp == NULL) {
  52. if (strcmp(argv[i], "-") == 0)
  53. infp = stdin;
  54. else if ((infp = fopen(argv[i], "r")) == NULL) {
  55. yyerror("%s: can't read `%s'\n", argv[0], argv[i]);
  56. exit(1);
  57. }
  58. } else if (outfp == NULL) {
  59. if (strcmp(argv[i], "-") == 0)
  60. outfp = stdout;
  61. if ((outfp = fopen(argv[i], "w")) == NULL) {
  62. yyerror("%s: can't write `%s'\n", argv[0], argv[i]);
  63. exit(1);
  64. }
  65. }
  66. if (infp == NULL)
  67. infp = stdin;
  68. if (outfp == NULL)
  69. outfp = stdout;
  70. yyparse();
  71. if (start)
  72. ckreach(start);
  73. for (p = nts; p; p = p->link) {
  74. if (p->rules == NULL)
  75. yyerror("undefined nonterminal `%s'\n", p->name);
  76. if (!p->reached)
  77. yyerror("can't reach nonterminal `%s'\n", p->name);
  78. }
  79. emitheader();
  80. emitdefs(nts, ntnumber);
  81. emitstruct(nts, ntnumber);
  82. emitnts(rules, nrules);
  83. emitstring(rules);
  84. emitrule(nts);
  85. emitclosure(nts);
  86. if (start)
  87. emitlabel(terms, start, ntnumber);
  88. emitkids(rules, nrules);
  89. if (!feof(infp))
  90. while ((c = getc(infp)) != EOF)
  91. putc(c, outfp);
  92. while (memlist) { /* for purify */
  93. struct block *q = memlist->link;
  94. free(memlist);
  95. memlist = q;
  96. }
  97. return errcnt > 0;
  98. }
  99. /* alloc - allocate nbytes or issue fatal error */
  100. void *alloc(int nbytes) {
  101. struct block *p = calloc(1, sizeof *p + nbytes);
  102. if (p == NULL) {
  103. yyerror("out of memory\n");
  104. exit(1);
  105. }
  106. p->link = memlist;
  107. memlist = p;
  108. return p + 1;
  109. }
  110. /* stringf - format and save a string */
  111. static char *stringf(char *fmt, ...) {
  112. va_list ap;
  113. char buf[512];
  114. va_start(ap, fmt);
  115. vsprintf(buf, fmt, ap);
  116. va_end(ap);
  117. return strcpy(alloc(strlen(buf) + 1), buf);
  118. }
  119. struct entry {
  120. union {
  121. char *name;
  122. struct term t;
  123. struct nonterm nt;
  124. } sym;
  125. struct entry *link;
  126. } *table[211];
  127. #define HASHSIZE (sizeof table/sizeof table[0])
  128. /* hash - return hash number for str */
  129. static unsigned hash(char *str) {
  130. unsigned h = 0;
  131. while (*str)
  132. h = (h<<1) + *str++;
  133. return h;
  134. }
  135. /* lookup - lookup symbol name */
  136. static void *lookup(char *name) {
  137. struct entry *p = table[hash(name)%HASHSIZE];
  138. for ( ; p; p = p->link)
  139. if (strcmp(name, p->sym.name) == 0)
  140. return &p->sym;
  141. return 0;
  142. }
  143. /* install - install symbol name */
  144. static void *install(char *name) {
  145. struct entry *p = alloc(sizeof *p);
  146. int i = hash(name)%HASHSIZE;
  147. p->sym.name = name;
  148. p->link = table[i];
  149. table[i] = p;
  150. return &p->sym;
  151. }
  152. /* nonterm - create a new terminal id, if necessary */
  153. Nonterm nonterm(char *id) {
  154. Nonterm p = lookup(id), *q = &nts;
  155. if (p && p->kind == NONTERM)
  156. return p;
  157. if (p && p->kind == TERM)
  158. yyerror("`%s' is a terminal\n", id);
  159. p = install(id);
  160. p->kind = NONTERM;
  161. p->number = ++ntnumber;
  162. if (p->number == 1)
  163. start = p;
  164. while (*q && (*q)->number < p->number)
  165. q = &(*q)->link;
  166. assert(*q == 0 || (*q)->number != p->number);
  167. p->link = *q;
  168. *q = p;
  169. return p;
  170. }
  171. /* term - create a new terminal id with external symbol number esn */
  172. Term term(char *id, int esn) {
  173. Term p = lookup(id), *q = &terms;
  174. if (p)
  175. yyerror("redefinition of terminal `%s'\n", id);
  176. else
  177. p = install(id);
  178. p->kind = TERM;
  179. p->esn = esn;
  180. p->arity = -1;
  181. while (*q && (*q)->esn < p->esn)
  182. q = &(*q)->link;
  183. if (*q && (*q)->esn == p->esn)
  184. yyerror("duplicate external symbol number `%s=%d'\n",
  185. p->name, p->esn);
  186. p->link = *q;
  187. *q = p;
  188. return p;
  189. }
  190. /* tree - create & initialize a tree node with the given fields */
  191. Tree tree(char *id, Tree left, Tree right) {
  192. Tree t = alloc(sizeof *t);
  193. Term p = lookup(id);
  194. int arity = 0;
  195. if (left && right)
  196. arity = 2;
  197. else if (left)
  198. arity = 1;
  199. if (p == NULL && arity > 0) {
  200. yyerror("undefined terminal `%s'\n", id);
  201. p = term(id, -1);
  202. } else if (p == NULL && arity == 0)
  203. p = (Term)nonterm(id);
  204. else if (p && p->kind == NONTERM && arity > 0) {
  205. yyerror("`%s' is a nonterminal\n", id);
  206. p = term(id, -1);
  207. }
  208. if (p->kind == TERM && p->arity == -1)
  209. p->arity = arity;
  210. if (p->kind == TERM && arity != p->arity)
  211. yyerror("inconsistent arity for terminal `%s'\n", id);
  212. t->op = p;
  213. t->nterms = p->kind == TERM;
  214. if ((t->left = left) != NULL)
  215. t->nterms += left->nterms;
  216. if ((t->right = right) != NULL)
  217. t->nterms += right->nterms;
  218. return t;
  219. }
  220. /* rule - create & initialize a rule with the given fields */
  221. Rule rule(char *id, Tree pattern, char *template, char *code) {
  222. Rule r = alloc(sizeof *r), *q;
  223. Term p = pattern->op;
  224. char *end;
  225. r->lhs = nonterm(id);
  226. r->packed = ++r->lhs->lhscount;
  227. for (q = &r->lhs->rules; *q; q = &(*q)->decode)
  228. ;
  229. *q = r;
  230. r->pattern = pattern;
  231. r->ern = ++nrules;
  232. r->template = template;
  233. r->code = code;
  234. r->cost = strtol(code, &end, 10);
  235. if (*end) {
  236. r->cost = -1;
  237. r->code = stringf("(%s)", code);
  238. }
  239. if (p->kind == TERM) {
  240. for (q = &p->rules; *q; q = &(*q)->next)
  241. ;
  242. *q = r;
  243. } else if (pattern->left == NULL && pattern->right == NULL) {
  244. Nonterm p = pattern->op;
  245. r->chain = p->chain;
  246. p->chain = r;
  247. if (r->cost == -1)
  248. yyerror("illegal nonconstant cost `%s'\n", code);
  249. }
  250. for (q = &rules; *q; q = &(*q)->link)
  251. ;
  252. r->link = *q;
  253. *q = r;
  254. return r;
  255. }
  256. /* print - formatted output */
  257. static void print(char *fmt, ...) {
  258. va_list ap;
  259. va_start(ap, fmt);
  260. for ( ; *fmt; fmt++)
  261. if (*fmt == '%')
  262. switch (*++fmt) {
  263. case 'd': fprintf(outfp, "%d", va_arg(ap, int)); break;
  264. case 's': fputs(va_arg(ap, char *), outfp); break;
  265. case 'P': fprintf(outfp, "%s_", prefix); break;
  266. case 'T': {
  267. Tree t = va_arg(ap, Tree);
  268. print("%S", t->op);
  269. if (t->left && t->right)
  270. print("(%T,%T)", t->left, t->right);
  271. else if (t->left)
  272. print("(%T)", t->left);
  273. break;
  274. }
  275. case 'R': {
  276. Rule r = va_arg(ap, Rule);
  277. print("%S: %T", r->lhs, r->pattern);
  278. break;
  279. }
  280. case 'S': fputs(va_arg(ap, Term)->name, outfp); break;
  281. case '1': case '2': case '3': case '4': case '5': {
  282. int n = *fmt - '0';
  283. while (n-- > 0)
  284. putc('\t', outfp);
  285. break;
  286. }
  287. default: putc(*fmt, outfp); break;
  288. }
  289. else
  290. putc(*fmt, outfp);
  291. va_end(ap);
  292. }
  293. /* reach - mark all nonterminals in tree t as reachable */
  294. static void reach(Tree t) {
  295. Nonterm p = t->op;
  296. if (p->kind == NONTERM)
  297. if (!p->reached)
  298. ckreach(p);
  299. if (t->left)
  300. reach(t->left);
  301. if (t->right)
  302. reach(t->right);
  303. }
  304. /* ckreach - mark all nonterminals reachable from p */
  305. static void ckreach(Nonterm p) {
  306. Rule r;
  307. p->reached = 1;
  308. for (r = p->rules; r; r = r->decode)
  309. reach(r->pattern);
  310. }
  311. /* emitcase - emit one case in function state */
  312. static void emitcase(Term p, int ntnumber) {
  313. Rule r;
  314. print("%1case %d: /* %S */\n", p->esn, p);
  315. switch (p->arity) {
  316. case 0: case -1:
  317. break;
  318. case 1:
  319. print("%2%Plabel(LEFT_CHILD(a));\n");
  320. break;
  321. case 2:
  322. print("%2%Plabel(LEFT_CHILD(a));\n");
  323. print("%2%Plabel(RIGHT_CHILD(a));\n");
  324. break;
  325. default: assert(0);
  326. }
  327. for (r = p->rules; r; r = r->next) {
  328. char *indent = "\t\t\0";
  329. switch (p->arity) {
  330. case 0: case -1:
  331. print("%2/* %R */\n", r);
  332. if (r->cost == -1) {
  333. print("%2c = %s;\n", r->code);
  334. emitrecord("\t\t", r, "c", 0);
  335. } else
  336. emitrecord("\t\t", r, r->code, 0);
  337. break;
  338. case 1:
  339. if (r->pattern->nterms > 1) {
  340. print("%2if (%1/* %R */\n", r);
  341. emittest(r->pattern->left, "LEFT_CHILD(a)", " ");
  342. print("%2) {\n");
  343. indent = "\t\t\t";
  344. } else
  345. print("%2/* %R */\n", r);
  346. if (r->pattern->nterms == 2 && r->pattern->left
  347. && r->pattern->right == NULL)
  348. emitrecalc(indent, r->pattern->op, r->pattern->left->op);
  349. print("%sc = ", indent);
  350. emitcost(r->pattern->left, "LEFT_CHILD(a)");
  351. print("%s;\n", r->code);
  352. emitrecord(indent, r, "c", 0);
  353. if (indent[2])
  354. print("%2}\n");
  355. break;
  356. case 2:
  357. if (r->pattern->nterms > 1) {
  358. print("%2if (%1/* %R */\n", r);
  359. emittest(r->pattern->left, "LEFT_CHILD(a)",
  360. r->pattern->right->nterms ? " && " : " ");
  361. emittest(r->pattern->right, "RIGHT_CHILD(a)", " ");
  362. print("%2) {\n");
  363. indent = "\t\t\t";
  364. } else
  365. print("%2/* %R */\n", r);
  366. print("%sc = ", indent);
  367. emitcost(r->pattern->left, "LEFT_CHILD(a)");
  368. emitcost(r->pattern->right, "RIGHT_CHILD(a)");
  369. print("%s;\n", r->code);
  370. emitrecord(indent, r, "c", 0);
  371. if (indent[2])
  372. print("%2}\n");
  373. break;
  374. default: assert(0);
  375. }
  376. }
  377. print("%2break;\n");
  378. }
  379. /* emitclosure - emit the closure functions */
  380. static void emitclosure(Nonterm nts) {
  381. Nonterm p;
  382. for (p = nts; p; p = p->link)
  383. if (p->chain)
  384. print("static void %Pclosure_%S(NODEPTR_TYPE, int);\n", p);
  385. print("\n");
  386. for (p = nts; p; p = p->link)
  387. if (p->chain) {
  388. Rule r;
  389. print("static void %Pclosure_%S(NODEPTR_TYPE a, int c) {\n"
  390. "%1struct %Pstate *p = STATE_LABEL(a);\n", p);
  391. for (r = p->chain; r; r = r->chain)
  392. emitrecord("\t", r, "c", r->cost);
  393. print("}\n\n");
  394. }
  395. }
  396. /* emitcost - emit cost computation for tree t */
  397. static void emitcost(Tree t, char *v) {
  398. Nonterm p = t->op;
  399. if (p->kind == TERM) {
  400. if (t->left)
  401. emitcost(t->left, stringf("LEFT_CHILD(%s)", v));
  402. if (t->right)
  403. emitcost(t->right, stringf("RIGHT_CHILD(%s)", v));
  404. } else
  405. print("((struct %Pstate *)(%s->x.state))->cost[%P%S_NT] + ", v, p);
  406. }
  407. /* emitdefs - emit nonterminal defines and data structures */
  408. static void emitdefs(Nonterm nts, int ntnumber) {
  409. Nonterm p;
  410. for (p = nts; p; p = p->link)
  411. print("#define %P%S_NT %d\n", p, p->number);
  412. print("\n");
  413. print("static char *%Pntname[] = {\n%10,\n");
  414. for (p = nts; p; p = p->link)
  415. print("%1\"%S\",\n", p);
  416. print("%10\n};\n\n");
  417. }
  418. /* emitheader - emit initial definitions */
  419. static void emitheader(void) {
  420. time_t timer = time(NULL);
  421. print("/*\ngenerated at %sby %s\n*/\n", ctime(&timer), rcsid);
  422. print("static void %Pkids(NODEPTR_TYPE, int, NODEPTR_TYPE[]);\n");
  423. print("static void %Plabel(NODEPTR_TYPE);\n");
  424. print("static int %Prule(void*, int);\n\n");
  425. }
  426. /* computekids - compute paths to kids in tree t */
  427. static char *computekids(Tree t, char *v, char *bp, int *ip) {
  428. Term p = t->op;
  429. if (p->kind == NONTERM) {
  430. sprintf(bp, "\t\tkids[%d] = %s;\n", (*ip)++, v);
  431. bp += strlen(bp);
  432. } else if (p->arity > 0) {
  433. bp = computekids(t->left, stringf("LEFT_CHILD(%s)", v), bp, ip);
  434. if (p->arity == 2)
  435. bp = computekids(t->right, stringf("RIGHT_CHILD(%s)", v), bp, ip);
  436. }
  437. return bp;
  438. }
  439. /* emitkids - emit _kids */
  440. static void emitkids(Rule rules, int nrules) {
  441. int i;
  442. Rule r, *rc = alloc((nrules + 1 + 1)*sizeof *rc);
  443. char **str = alloc((nrules + 1 + 1)*sizeof *str);
  444. for (i = 0, r = rules; r; r = r->link) {
  445. int j = 0;
  446. char buf[1024], *bp = buf;
  447. *computekids(r->pattern, "p", bp, &j) = 0;
  448. for (j = 0; str[j] && strcmp(str[j], buf); j++)
  449. ;
  450. if (str[j] == NULL)
  451. str[j] = strcpy(alloc(strlen(buf) + 1), buf);
  452. r->kids = rc[j];
  453. rc[j] = r;
  454. }
  455. print("static void %Pkids(NODEPTR_TYPE p, int eruleno, NODEPTR_TYPE kids[]) {\n"
  456. "%1if (!p)\n%2fatal(\"%Pkids\", \"Null tree\\n\", 0);\n"
  457. "%1if (!kids)\n%2fatal(\"%Pkids\", \"Null kids\\n\", 0);\n"
  458. "%1switch (eruleno) {\n");
  459. for (i = 0; (r = rc[i]) != NULL; i++) {
  460. for ( ; r; r = r->kids)
  461. print("%1case %d: /* %R */\n", r->ern, r);
  462. print("%s%2break;\n", str[i]);
  463. }
  464. print("%1default:\n%2fatal(\"%Pkids\", \"Bad rule number %%d\\n\", eruleno);\n%1}\n}\n\n");
  465. }
  466. /* emitlabel - emit label function */
  467. static void emitlabel(Term terms, Nonterm start, int ntnumber) {
  468. int i;
  469. Term p;
  470. print("static void %Plabel(NODEPTR_TYPE a) {\n%1int c;\n"
  471. "%1struct %Pstate *p;\n\n"
  472. "%1if (!a)\n%2fatal(\"%Plabel\", \"Null tree\\n\", 0);\n");
  473. print("%1STATE_LABEL(a) = p = allocate(sizeof *p, FUNC);\n"
  474. "%1p->rule._stmt = 0;\n");
  475. for (i = 1; i <= ntnumber; i++)
  476. print("%1p->cost[%d] =\n", i);
  477. print("%20x7fff;\n%1switch (OP_LABEL(a)) {\n");
  478. for (p = terms; p; p = p->link)
  479. emitcase(p, ntnumber);
  480. print("%1default:\n"
  481. "%2fatal(\"%Plabel\", \"Bad terminal %%d\\n\", OP_LABEL(a));\n%1}\n}\n\n");
  482. }
  483. /* computents - fill in bp with _nts vector for tree t */
  484. static char *computents(Tree t, char *bp) {
  485. if (t) {
  486. Nonterm p = t->op;
  487. if (p->kind == NONTERM) {
  488. sprintf(bp, "%s_%s_NT, ", prefix, p->name);
  489. bp += strlen(bp);
  490. } else
  491. bp = computents(t->right, computents(t->left, bp));
  492. }
  493. return bp;
  494. }
  495. /* emitnts - emit _nts ragged array */
  496. static void emitnts(Rule rules, int nrules) {
  497. Rule r;
  498. int i, j, *nts = alloc((nrules + 1)*sizeof *nts);
  499. char **str = alloc((nrules + 1)*sizeof *str);
  500. for (i = 0, r = rules; r; r = r->link) {
  501. char buf[1024];
  502. *computents(r->pattern, buf) = 0;
  503. for (j = 0; str[j] && strcmp(str[j], buf); j++)
  504. ;
  505. if (str[j] == NULL) {
  506. print("static short %Pnts_%d[] = { %s0 };\n", j, buf);
  507. str[j] = strcpy(alloc(strlen(buf) + 1), buf);
  508. }
  509. nts[i++] = j;
  510. }
  511. print("\nstatic short *%Pnts[] = {\n");
  512. for (i = j = 0, r = rules; r; r = r->link) {
  513. for ( ; j < r->ern; j++)
  514. print("%10,%1/* %d */\n", j);
  515. print("%1%Pnts_%d,%1/* %d */\n", nts[i++], j++);
  516. }
  517. print("};\n\n");
  518. }
  519. /* emitrecalc - emit code that tests for recalculation of INDIR?(VREGP) */
  520. static void emitrecalc(char *pre, Term root, Term kid) {
  521. if (root->kind == TERM && strncmp(root->name, "INDIR", 5) == 0
  522. && kid->kind == TERM && strcmp(kid->name, "VREGP" ) == 0) {
  523. Nonterm p;
  524. print("%sif (mayrecalc(a)) {\n", pre);
  525. print("%s%1struct %Pstate *q = a->syms[RX]->u.t.cse->x.state;\n", pre);
  526. for (p = nts; p; p = p->link) {
  527. print("%s%1if (q->cost[%P%S_NT] == 0) {\n", pre, p);
  528. print("%s%2p->cost[%P%S_NT] = 0;\n", pre, p);
  529. print("%s%2p->rule.%P%S = q->rule.%P%S;\n", pre, p, p);
  530. print("%s%1}\n", pre);
  531. }
  532. print("%s}\n", pre);
  533. }
  534. }
  535. /* emitrecord - emit code that tests for a winning match of rule r */
  536. static void emitrecord(char *pre, Rule r, char *c, int cost) {
  537. if (Tflag)
  538. print("%s%Ptrace(a, %d, %s + %d, p->cost[%P%S_NT]);\n",
  539. pre, r->ern, c, cost, r->lhs);
  540. print("%sif (", pre);
  541. print("%s + %d < p->cost[%P%S_NT]) {\n"
  542. "%s%1p->cost[%P%S_NT] = %s + %d;\n%s%1p->rule.%P%S = %d;\n",
  543. c, cost, r->lhs, pre, r->lhs, c, cost, pre, r->lhs,
  544. r->packed);
  545. if (r->lhs->chain)
  546. print("%s%1%Pclosure_%S(a, %s + %d);\n", pre, r->lhs, c, cost);
  547. print("%s}\n", pre);
  548. }
  549. /* emitrule - emit decoding vectors and _rule */
  550. static void emitrule(Nonterm nts) {
  551. Nonterm p;
  552. for (p = nts; p; p = p->link) {
  553. Rule r;
  554. print("static short %Pdecode_%S[] = {\n%10,\n", p);
  555. for (r = p->rules; r; r = r->decode)
  556. print("%1%d,\n", r->ern);
  557. print("};\n\n");
  558. }
  559. print("static int %Prule(void *state, int goalnt) {\n"
  560. "%1if (goalnt < 1 || goalnt > %d)\n%2fatal(\"%Prule\", \"Bad goal nonterminal %%d\\n\", goalnt);\n"
  561. "%1if (!state)\n%2return 0;\n%1switch (goalnt) {\n", ntnumber);
  562. for (p = nts; p; p = p->link)
  563. print("%1case %P%S_NT:"
  564. "%1return %Pdecode_%S[((struct %Pstate *)state)->rule.%P%S];\n", p, p, p);
  565. print("%1default:\n%2fatal(\"%Prule\", \"Bad goal nonterminal %%d\\n\", goalnt);\n%2return 0;\n%1}\n}\n\n");
  566. }
  567. /* emitstring - emit arrays of templates, instruction flags, and rules */
  568. static void emitstring(Rule rules) {
  569. Rule r;
  570. print("static char *%Ptemplates[] = {\n");
  571. print("/* 0 */%10,\n");
  572. for (r = rules; r; r = r->link)
  573. print("/* %d */%1\"%s\",%1/* %R */\n", r->ern, r->template, r);
  574. print("};\n");
  575. print("\nstatic char %Pisinstruction[] = {\n");
  576. print("/* 0 */%10,\n");
  577. for (r = rules; r; r = r->link) {
  578. int len = strlen(r->template);
  579. print("/* %d */%1%d,%1/* %s */\n", r->ern,
  580. len >= 2 && r->template[len-2] == '\\' && r->template[len-1] == 'n',
  581. r->template);
  582. }
  583. print("};\n");
  584. print("\nstatic char *%Pstring[] = {\n");
  585. print("/* 0 */%10,\n");
  586. for (r = rules; r; r = r->link)
  587. print("/* %d */%1\"%R\",\n", r->ern, r);
  588. print("};\n\n");
  589. }
  590. /* emitstruct - emit the definition of the state structure */
  591. static void emitstruct(Nonterm nts, int ntnumber) {
  592. print("struct %Pstate {\n%1short cost[%d];\n%1struct {\n", ntnumber + 1);
  593. for ( ; nts; nts = nts->link) {
  594. int n = 1, m = nts->lhscount;
  595. while ((m >>= 1) != 0)
  596. n++;
  597. print("%2unsigned int %P%S:%d;\n", nts, n);
  598. }
  599. print("%1} rule;\n};\n\n");
  600. }
  601. /* emittest - emit clause for testing a match */
  602. static void emittest(Tree t, char *v, char *suffix) {
  603. Term p = t->op;
  604. if (p->kind == TERM) {
  605. print("%3%s->op == %d%s/* %S */\n", v, p->esn,
  606. t->nterms > 1 ? " && " : suffix, p);
  607. if (t->left)
  608. emittest(t->left, stringf("LEFT_CHILD(%s)", v),
  609. t->right && t->right->nterms ? " && " : suffix);
  610. if (t->right)
  611. emittest(t->right, stringf("RIGHT_CHILD(%s)", v), suffix);
  612. }
  613. }