rec 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. * Some grammar independent code.
  3. * This file is copied into Lpars.c.
  4. */
  5. unsigned int LLtcnt[LL_NTERMINALS];
  6. unsigned int LLscnt[LL_NSETS];
  7. int LLcsymb, LLsymb;
  8. static int LLlevel;
  9. #if LL_NON_CORR
  10. int LLstartsymb;
  11. static int fake_eof = 0;
  12. #endif
  13. #if LL_ANSI_C
  14. #define LL_VOIDCST (void)
  15. void LLmessage(int);
  16. #else
  17. #define LL_VOIDCST
  18. #endif
  19. #ifdef LL_USERHOOK
  20. #if LL_ANSI_C
  21. static int LLdoskip(int);
  22. static int LLuserhook(int, int*);
  23. #else
  24. static int LLdoskip();
  25. static int LLuserhook();
  26. #endif
  27. #endif
  28. #ifndef LL_FASTER
  29. #if LL_ANSI_C
  30. void LLscan(int t)
  31. #else
  32. LLscan(t)
  33. int t;
  34. #endif
  35. {
  36. /*
  37. * Check if the next symbol is equal to the parameter
  38. */
  39. #if LL_NON_CORR
  40. /* See if the error recovery has eaten an eof */
  41. if (fake_eof) {
  42. LLsymb = EOFILE;
  43. fake_eof = 0;
  44. }
  45. else {
  46. LLsymb = LL_LEXI();
  47. }
  48. if (LLsymb == t) {
  49. #else
  50. if ((LLsymb = LL_LEXI()) == t) {
  51. #endif
  52. #if LL_NON_CORR
  53. /* Check if a previous parser has 'crashed', in that
  54. * case continue with non-correcting parser
  55. */
  56. if (err_seen && !nc_done) {
  57. LLnc_recover();
  58. nc_done = 1;
  59. /* Remember that the error recovery has eaten an eof */
  60. fake_eof = 1;
  61. if (t != LLsymb) {
  62. LLerror(t);
  63. }
  64. else
  65. return;
  66. }
  67. #endif
  68. return;
  69. }
  70. /*
  71. * If we come here, an error has been detected
  72. */
  73. LLerror(t);
  74. }
  75. #endif
  76. #if LL_ANSI_C
  77. void LLread(void) {
  78. #else
  79. LLread() {
  80. #endif
  81. #if LL_NON_CORR
  82. /* Again, check if another parser has crashed,
  83. * in that case intercept and go to the
  84. * non-correcting parser
  85. */
  86. if (err_seen && !nc_done) {
  87. LLnc_recover();
  88. nc_done = 1;
  89. /* Pretend we read end of file */
  90. LLsymb = EOFILE;
  91. LLcsymb = LLindex[EOFILE];
  92. fake_eof = 0;
  93. return;
  94. }
  95. if (fake_eof) {
  96. LLsymb = EOFILE;
  97. LLcsymb = LLindex[EOFILE];
  98. fake_eof = 0;
  99. return;
  100. }
  101. #endif
  102. for (;;) {
  103. if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
  104. LLmessage(0);
  105. }
  106. /* NOTREACHED */
  107. }
  108. #if LL_ANSI_C
  109. void LLerror(int t)
  110. #else
  111. LLerror(t)
  112. int t;
  113. #endif
  114. {
  115. register int i;
  116. if (t == EOFILE && LLsymb <= 0) return;
  117. #ifdef LL_NEWMESS
  118. if (t == EOFILE) {
  119. #ifdef LL_USERHOOK
  120. static int lst[] = { EOFILE, 0 };
  121. LL_VOIDCST LLuserhook(EOFILE, lst);
  122. #endif /* LL_USERHOOK */
  123. if (LLsymb != EOFILE && LLsymb > 0) {
  124. LLmessage(-1);
  125. while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
  126. /* nothing */ ;
  127. }
  128. return;
  129. }
  130. #endif
  131. #if LL_NON_CORR
  132. if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
  133. LLmessage(0);
  134. LLnc_recover();
  135. nc_done = 1;
  136. LLsymb = EOFILE;
  137. }
  138. #endif
  139. if ((LLcsymb = LLindex[LLsymb]) < 0) {
  140. LLmessage(0);
  141. LLread();
  142. }
  143. i = LLindex[t];
  144. LLtcnt[i]++;
  145. #ifdef LL_USERHOOK
  146. LL_VOIDCST LLdoskip(t);
  147. #else
  148. LL_VOIDCST LLskip();
  149. #endif
  150. LLtcnt[i]--;
  151. if (LLsymb != t) {
  152. #if LL_NON_CORR
  153. /* A little kludge here; when using non-correcting recovery
  154. * it can happen that a program is correct but incomplete.
  155. * Here, we test this, and make sure the appropriate
  156. * message is generated
  157. */
  158. if (! nc_done) {
  159. int oldLLsymb;
  160. oldLLsymb = LLsymb;
  161. LLsymb = EOFILE;
  162. LLmessage(0);
  163. nc_done = 1;
  164. /* Not really, but to prevent more than 1 error message */
  165. LLsymb = oldLLsymb;
  166. }
  167. #endif
  168. LLmessage(t);
  169. }
  170. }
  171. #if LL_ANSI_C
  172. void LLsafeerror(int t)
  173. #else
  174. LLsafeerror(t)
  175. int t;
  176. #endif
  177. {
  178. if (t == EOFILE && LLsymb <= 0) return;
  179. #ifdef LL_NEWMESS
  180. if (t == EOFILE) {
  181. #ifdef LL_USERHOOK
  182. static int lst[] = { EOFILE, 0 };
  183. LL_VOIDCST LLuserhook(EOFILE, lst);
  184. #endif /* LL_USERHOOK */
  185. if (LLsymb != EOFILE && LLsymb > 0) {
  186. LLmessage(-1);
  187. while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
  188. /* nothing */ ;
  189. }
  190. return;
  191. }
  192. #endif
  193. #if LL_NON_CORR
  194. if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
  195. LLmessage(0);
  196. LLnc_recover();
  197. nc_done = 1;
  198. LLsymb = EOFILE;
  199. }
  200. /* A little kludge here; when using non-correcting recovery
  201. * it can happen that a program is correct but incomplete.
  202. * Here, we test this, and make sure the appropriate
  203. * message is generated
  204. */
  205. if (! nc_done) {
  206. int oldLLsymb;
  207. oldLLsymb = LLsymb;
  208. LLsymb = EOFILE;
  209. LLmessage(0);
  210. nc_done = 1;
  211. /* Not really, but to prevent more than 1 error message */
  212. LLsymb = oldLLsymb;
  213. }
  214. #endif
  215. LLmessage(t);
  216. }
  217. #ifndef LLNOFIRSTS
  218. #if LL_ANSI_C
  219. int LLfirst(int x, int d) {
  220. #else
  221. int LLfirst(x, d) {
  222. #endif
  223. register int i;
  224. return (i = LLindex[x]) >= 0 &&
  225. (LLsets[d + (i >> 3)] & (1 << (i & 07)));
  226. }
  227. #endif
  228. #if LL_ANSI_C
  229. int LLnext(int n)
  230. #else
  231. int LLnext(n)
  232. int n;
  233. #endif
  234. {
  235. /* returns: 0 if the current symbol is'nt skipped, and it
  236. is'nt a member of "n",
  237. 1 if we have a new symbol, but it is'nt a member,
  238. 2 if the current symbol is a member,
  239. and 3 if we have a new symbol and it is a member.
  240. So, the low order bit indicates wether we have a new symbol,
  241. and the next bit indicates wether it is a member of "n".
  242. */
  243. int retval = 0;
  244. if (LLskip()) retval = 1;
  245. if (n <= 0 && LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07))) {
  246. retval |= 2;
  247. }
  248. else if (n > 0 && LLcsymb == LLindex[n]) retval |= 2;
  249. return retval;
  250. }
  251. #if LL_ANSI_C
  252. int LLskip(void) {
  253. #else
  254. int LLskip() {
  255. #endif
  256. /* returns 0 if the current symbol is'nt skipped, and
  257. 1 if it is, t.i., we have a new symbol
  258. */
  259. #ifdef LL_USERHOOK
  260. return LLdoskip(0);
  261. }
  262. #if LL_ANSI_C
  263. extern void LL_USERHOOK(int, int *);
  264. static int LLuserhook(int e, int *list)
  265. #else
  266. static int LLuserhook(e, list)
  267. int e;
  268. int *list;
  269. #endif
  270. {
  271. int old = LLsymb;
  272. LL_USERHOOK(e, list);
  273. LLread();
  274. return LLsymb != old;
  275. }
  276. #if LL_ANSI_C
  277. static void LLmklist(register int *list)
  278. #else
  279. static LLmklist(list)
  280. register int *list;
  281. #endif
  282. {
  283. char Xset[LL_SSIZE];
  284. register char *p;
  285. register int i;
  286. for (p = &Xset[0]; p < &Xset[LL_SSIZE]; ) *p++ = 0;
  287. for (i = 0; i < LL_NTERMINALS; i++) {
  288. if (LLtcnt[i] != 0) Xset[i >> 3] |= (1 << (i & 07));
  289. }
  290. for (i = LL_NSETS - 1; i >= 0; i--) if (LLscnt[i] != 0) {
  291. register char *q = &LLsets[LL_SSIZE * i];
  292. p = &Xset[0];
  293. while (p < &Xset[LL_SSIZE]) *p++ |= *q++;
  294. }
  295. for (i = 0; i < LL_NTERMINALS; i++) {
  296. if (Xset[i >> 3] & (1 << (i & 07))) {
  297. *list++ = LLtok[i];
  298. }
  299. }
  300. *list = 0;
  301. }
  302. #if LL_ANSI_C
  303. static int LLdoskip(int e)
  304. #else
  305. static int LLdoskip(e)
  306. int e;
  307. #endif
  308. {
  309. int LLx;
  310. int list[LL_NTERMINALS+1];
  311. #endif /* LL_USERHOOK */
  312. register int i;
  313. int retval;
  314. int LLi, LLb;
  315. retval = 0;
  316. #ifdef LL_USERHOOK
  317. LLmklist(list);
  318. LLx = LLuserhook(e, list);
  319. if (LLx) retval = 1;
  320. #endif /* LL_USERHOOK */
  321. for (;;) {
  322. if (LLtcnt[LLcsymb] != 0) {
  323. #ifdef LL_USERHOOK
  324. if (!e || !LLx || LLcsymb == LLindex[e])
  325. #endif
  326. return retval;
  327. }
  328. LLi = LLcsymb >> 3;
  329. LLb = 1 << (LLcsymb & 07);
  330. for (i = LL_NSETS - 1; i >= 0; i--) {
  331. if (LLscnt[i] != 0) {
  332. if (LLsets[LL_SSIZE*i+LLi] & LLb) {
  333. #ifdef LL_USERHOOK
  334. if (!e || !LLx || LLcsymb == LLindex[e])
  335. #endif
  336. return retval;
  337. }
  338. }
  339. }
  340. #ifdef LL_USERHOOK
  341. if (LLx) {
  342. LLx = LLuserhook(e, list);
  343. continue;
  344. }
  345. #endif /* LL_USERHOOK */
  346. #if LL_NON_CORR
  347. if ((!nc_done) && (LLsymb > 0)) {
  348. LLmessage(0);
  349. LLnc_recover();
  350. nc_done = 1;
  351. fake_eof = 1;
  352. }
  353. else {
  354. LLmessage(0);
  355. }
  356. #else
  357. LLmessage(0);
  358. #endif
  359. retval = 1;
  360. LLread();
  361. }
  362. /* NOTREACHED */
  363. }
  364. #if LL_ANSI_C
  365. void LLnewlevel(unsigned int *LLsinfo) {
  366. #else
  367. LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
  368. #endif
  369. register int i;
  370. if (LLlevel++) {
  371. LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb;
  372. LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb;
  373. for (i = LL_NTERMINALS - 1; i >= 0; i--) {
  374. LLsinfo[i] = LLtcnt[i];
  375. LLtcnt[i] = 0;
  376. }
  377. for (i = LL_NSETS - 1; i >= 0; i--) {
  378. LLsinfo[LL_NTERMINALS+i] = LLscnt[i];
  379. LLscnt[i] = 0;
  380. }
  381. }
  382. LLtincr(0);
  383. }
  384. #if LL_ANSI_C
  385. void LLoldlevel(unsigned int *LLsinfo) {
  386. #else
  387. LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
  388. #endif
  389. register int i;
  390. LLtdecr(0);
  391. #ifdef LL_DEBUG
  392. for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
  393. for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
  394. #endif
  395. if (--LLlevel) {
  396. for (i = LL_NSETS - 1; i >= 0; i--) {
  397. LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
  398. }
  399. for (i = LL_NTERMINALS - 1; i >= 0; i--) {
  400. LLtcnt[i] = LLsinfo[i];
  401. }
  402. LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
  403. LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
  404. }
  405. }