tokens.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /* LLgen generated code from source tokens.g */
  2. #include "Lpars.h"
  3. #define LL_LEXI scanner
  4. #define LLNOFIRSTS
  5. #if __STDC__ || __cplusplus
  6. #define LL_ANSI_C 1
  7. #endif
  8. #define LL_LEXI scanner
  9. /* $Id$ */
  10. #ifdef LL_DEBUG
  11. #include <assert.h>
  12. #include <stdio.h>
  13. #define LL_assert(x) assert(x)
  14. #else
  15. #define LL_assert(x) /* nothing */
  16. #endif
  17. extern int LLsymb;
  18. #define LL_SAFE(x) /* Nothing */
  19. #define LL_SSCANDONE(x) if (LLsymb != x) LLsafeerror(x)
  20. #define LL_SCANDONE(x) if (LLsymb != x) LLerror(x)
  21. #define LL_NOSCANDONE(x) LLscan(x)
  22. #ifdef LL_FASTER
  23. #define LLscan(x) if ((LLsymb = LL_LEXI()) != x) LLerror(x)
  24. #endif
  25. extern unsigned int LLscnt[];
  26. extern unsigned int LLtcnt[];
  27. extern int LLcsymb;
  28. #if LL_NON_CORR
  29. extern int LLstartsymb;
  30. #endif
  31. #define LLsdecr(d) {LL_assert(LLscnt[d] > 0); LLscnt[d]--;}
  32. #define LLtdecr(d) {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
  33. #define LLsincr(d) LLscnt[d]++
  34. #define LLtincr(d) LLtcnt[d]++
  35. #if LL_ANSI_C
  36. extern int LL_LEXI(void);
  37. extern void LLread(void);
  38. extern int LLskip(void);
  39. extern int LLnext(int);
  40. extern void LLerror(int);
  41. extern void LLsafeerror(int);
  42. extern void LLnewlevel(unsigned int *);
  43. extern void LLoldlevel(unsigned int *);
  44. #ifndef LL_FASTER
  45. extern void LLscan(int);
  46. #endif
  47. #ifndef LLNOFIRSTS
  48. extern int LLfirst(int, int);
  49. #endif
  50. #if LL_NON_CORR
  51. extern void LLnc_recover(void);
  52. #endif
  53. #else /* not LL_ANSI_C */
  54. extern LLread();
  55. extern int LLskip();
  56. extern int LLnext();
  57. extern LLerror();
  58. extern LLsafeerror();
  59. extern LLnewlevel();
  60. extern LLoldlevel();
  61. #ifndef LL_FASTER
  62. extern LLscan();
  63. #endif
  64. #ifndef LLNOFIRSTS
  65. extern int LLfirst();
  66. #endif
  67. #if LL_NON_CORR
  68. extern LLnc_recover();
  69. #endif
  70. #endif /* not LL_ANSI_C */
  71. # line 20 "tokens.g"
  72. # include "types.h"
  73. # include "io.h"
  74. # include "extern.h"
  75. # include "assert.h"
  76. # include "cclass.h"
  77. # ifndef NORCSID
  78. static string rcsidc = "$Id$";
  79. # endif
  80. /* Here are defined : */
  81. extern int scanner();
  82. extern LLmessage();
  83. extern int input();
  84. extern unput();
  85. extern skipcomment();
  86. # ifdef LINE_DIRECTIVE
  87. STATIC linedirective();
  88. # endif
  89. STATIC string cpy();
  90. STATIC string vallookup();
  91. STATIC copyact();
  92. static int nparams;
  93. # line 75 "tokens.g"
  94. /*
  95. * Structure for a keyword
  96. */
  97. typedef struct keyword {
  98. string w_word;
  99. int w_value;
  100. } t_keyw, *p_keyw;
  101. /*
  102. * The list of keywords, the most often used keywords come first.
  103. * Linear search is used, as there are not many keywords
  104. */
  105. static t_keyw resword[] = {
  106. { "token", C_TOKEN },
  107. { "avoid", C_AVOID },
  108. { "prefer", C_PREFER },
  109. { "persistent", C_PERSISTENT },
  110. { "default", C_DEFAULT },
  111. { "if", C_IF },
  112. { "while", C_WHILE },
  113. { "first", C_FIRST },
  114. { "start", C_START },
  115. { "lexical", C_LEXICAL },
  116. { "onerror", C_ONERROR },
  117. { "prefix", C_PREFIX },
  118. #ifdef NON_CORRECTING
  119. { "substart", C_SUBSTART },
  120. { "erroneous", C_ERRONEOUS },
  121. { "illegal", C_ILLEGAL },
  122. #endif
  123. { 0, 0 }
  124. };
  125. static t_token savedtok; /* to save lextoken in case of an insertion */
  126. # ifdef LINE_DIRECTIVE
  127. static int nostartline; /* = 0 if at the start of a line */
  128. # endif
  129. STATIC
  130. copyact(ch1,ch2,flag,level) char ch1,ch2; {
  131. /*
  132. * Copy an action to file f. Opening bracket is ch1, closing bracket
  133. * is ch2.
  134. * If flag & 1, copy opening and closing parameters too.
  135. * If flag & 2, don't allow ','.
  136. */
  137. static int text_seen = 0;
  138. register FILE *f;
  139. register ch; /* Current char */
  140. register match; /* used to read strings */
  141. int saved = linecount;
  142. /* save linecount */
  143. int sav_strip = strip_grammar;
  144. f = fact;
  145. if (ch1 == '{' || flag != 1) strip_grammar = 0;
  146. if (!level) {
  147. text_seen = 0;
  148. nparams = 0; /* count comma's */
  149. putc('\0',f);
  150. fprintf(f,"# line %d \"%s\"\n", linecount,f_input);
  151. }
  152. if (level || (flag & 1)) putc(ch1,f);
  153. for (;;) {
  154. ch = input();
  155. if (ch == ch2) {
  156. if (!level) {
  157. if (text_seen) nparams++;
  158. }
  159. if (level || (flag & 1)) putc(ch,f);
  160. if (strip_grammar != sav_strip) {
  161. if (ch1 == '{' || flag != 1) putchar(ch);
  162. }
  163. strip_grammar = sav_strip;
  164. return;
  165. }
  166. switch(ch) {
  167. case ')':
  168. case '}':
  169. case ']':
  170. error(linecount,"Parentheses mismatch");
  171. break;
  172. case '(':
  173. text_seen = 1;
  174. copyact('(',')',flag,level+1);
  175. continue;
  176. case '{':
  177. text_seen = 1;
  178. copyact('{','}',flag,level+1);
  179. continue;
  180. case '[':
  181. text_seen = 1;
  182. copyact('[',']',flag,level+1);
  183. continue;
  184. case '/':
  185. ch = input();
  186. unput(ch);
  187. if (ch == '*') {
  188. putc('/', f);
  189. skipcomment(1);
  190. continue;
  191. }
  192. ch = '/';
  193. text_seen = 1;
  194. break;
  195. case ';':
  196. case ',':
  197. if (! level && text_seen) {
  198. text_seen = 0;
  199. nparams++;
  200. if (ch == ',' && (flag & 2)) {
  201. warning(linecount, "Parameters may not be separated with a ','");
  202. ch = ';';
  203. }
  204. }
  205. break;
  206. case '\'':
  207. case '"' :
  208. /*
  209. * watch out for brackets in strings, they do not
  210. * count !
  211. */
  212. text_seen = 1;
  213. match = ch;
  214. putc(ch,f);
  215. while((ch = input())) {
  216. if (ch == match) break;
  217. if (ch == '\\') {
  218. putc(ch,f);
  219. ch = input();
  220. }
  221. if (ch == '\n') {
  222. error(linecount,"Newline in string");
  223. unput(match);
  224. }
  225. putc(ch,f);
  226. }
  227. if (ch == match) break;
  228. /* Fall through */
  229. case EOF :
  230. if (!level) error(saved,"Action does not terminate");
  231. strip_grammar = sav_strip;
  232. return;
  233. default:
  234. if (c_class[ch] != ISSPA) text_seen = 1;
  235. }
  236. putc(ch,f);
  237. }
  238. }
  239. scanner() {
  240. /*
  241. * Lexical analyser, what else
  242. */
  243. register int ch; /* Current char */
  244. register char *p = ltext;
  245. int reserved = 0; /* reserved word? */
  246. char *max = &ltext[LTEXTSZ - 1];
  247. static int nextexpr;
  248. int expect_expr = nextexpr;
  249. long off;
  250. nextexpr = 0;
  251. if (savedtok.t_tokno) {
  252. /* A token has been inserted.
  253. * Now deliver the last lextoken again
  254. */
  255. lextoken = savedtok;
  256. savedtok.t_tokno = 0;
  257. return lextoken.t_tokno;
  258. }
  259. for (;;) {
  260. ch = input();
  261. if (ch == EOF) return ch;
  262. # ifdef LINE_DIRECTIVE
  263. if (ch == '#' && !nostartline) {
  264. linedirective();
  265. continue;
  266. }
  267. # endif
  268. switch(c_class[ch]) {
  269. case ISACT :
  270. if (ch == '{') {
  271. copyact('{', '}', in_production, 0);
  272. return C_ACTION;
  273. }
  274. assert(ch == '(');
  275. if (expect_expr) {
  276. copyact('(', ')', 1, 0);
  277. return C_EXPR;
  278. }
  279. off = ftell(fact);
  280. copyact('(', ')', in_production != 0 ? 0 : 2, 0);
  281. if (nparams == 0) fseek(fact, off, 0);
  282. lextoken.t_num = nparams;
  283. return C_PARAMS;
  284. case ISLIT :
  285. for (;;) {
  286. ch = input();
  287. if (ch == '\n' || ch == EOF) {
  288. error(linecount,"Missing '");
  289. break;
  290. }
  291. if (ch == '\'') break;
  292. if (ch == '\\') {
  293. *p++ = ch;
  294. ch = input();
  295. }
  296. *p++ = ch;
  297. if (p > max) p--;
  298. }
  299. *p = '\0';
  300. lextoken.t_string = ltext;
  301. return C_LITERAL;
  302. case ISCOM :
  303. skipcomment(0);
  304. /* Fall through */
  305. case ISSPA :
  306. continue;
  307. case ISDIG : {
  308. register i = 0;
  309. do {
  310. i = 10 * i + (ch - '0');
  311. ch= input();
  312. } while (c_class[ch] == ISDIG);
  313. lextoken.t_num = i;
  314. unput(ch);
  315. return C_NUMBER; }
  316. default:
  317. return ch;
  318. case ISKEY :
  319. reserved = 1;
  320. ch = input();
  321. /* Fall through */
  322. case ISLET :
  323. do {
  324. if (reserved && ch >= 'A' && ch <= 'Z') {
  325. ch += 'a' - 'A';
  326. }
  327. *p++ = ch;
  328. if (p > max) p--;
  329. ch = input();
  330. } while (c_class[ch] == ISDIG || c_class[ch] == ISLET);
  331. unput(ch);
  332. *p = '\0';
  333. if (reserved) { /*
  334. * Now search for the keyword
  335. */
  336. register p_keyw w;
  337. w = resword;
  338. while (w->w_word) {
  339. if (! strcmp(ltext,w->w_word)) {
  340. /*
  341. * Return token number.
  342. */
  343. if (w->w_value == C_IF ||
  344. w->w_value == C_WHILE) {
  345. nextexpr = 1;
  346. }
  347. return w->w_value;
  348. }
  349. w++;
  350. }
  351. error(linecount,"Illegal reserved word");
  352. }
  353. lextoken.t_string = ltext;
  354. return C_IDENT;
  355. }
  356. }
  357. }
  358. static int backupc; /* for unput() */
  359. static int nonline; /* = 1 if last char read was a newline */
  360. input() {
  361. /*
  362. * Low level input routine, used by all other input routines
  363. */
  364. register c;
  365. if (c = backupc) {
  366. /* Last char was "unput()". Deliver it again
  367. */
  368. backupc = 0;
  369. return c;
  370. }
  371. if ((c = getc(finput)) == EOF) {
  372. nonline = 0;
  373. return c;
  374. }
  375. # ifdef LINE_DIRECTIVE
  376. nostartline = 1;
  377. # endif
  378. if (!nonline) {
  379. linecount++;
  380. # ifdef LINE_DIRECTIVE
  381. nostartline = 0;
  382. # endif
  383. nonline = 1;
  384. }
  385. if (c == '\n') nonline = 0;
  386. if (strip_grammar) putchar(c);
  387. return c;
  388. }
  389. unput(c) {
  390. /*
  391. * "unread" c
  392. */
  393. backupc = c;
  394. }
  395. skipcomment(flag) {
  396. /*
  397. * Skip comment. If flag != 0, the comment is inside a fragment
  398. * of C-code, so keep it.
  399. */
  400. register int ch;
  401. int saved; /* line count on which comment starts */
  402. saved = linecount;
  403. if (input() != '*') error(linecount,"Illegal comment");
  404. if (flag) putc('*', fact);
  405. do {
  406. ch = input();
  407. if (flag) putc(ch, fact);
  408. while (ch == '*') {
  409. ch = input();
  410. if (flag) putc(ch, fact);
  411. if (ch == '/') return;
  412. }
  413. } while (ch != EOF);
  414. error(saved,"Comment does not terminate");
  415. }
  416. # ifdef LINE_DIRECTIVE
  417. STATIC
  418. linedirective() {
  419. /*
  420. * Read a line directive
  421. */
  422. register int ch;
  423. register int i;
  424. string s_error = "Illegal line directive";
  425. string store();
  426. register string c;
  427. do { /*
  428. * Skip to next digit
  429. * Do not skip newlines
  430. */
  431. ch = input();
  432. } while (ch != '\n' && c_class[ch] != ISDIG);
  433. if (ch == '\n') {
  434. error(linecount,s_error);
  435. return;
  436. }
  437. i = 0;
  438. do {
  439. i = i*10 + (ch - '0');
  440. ch = input();
  441. } while (c_class[ch] == ISDIG);
  442. while (ch != '\n' && ch != '"') ch = input();
  443. if (ch == '"') {
  444. c = ltext;
  445. do {
  446. *c++ = ch = input();
  447. } while (ch != '"' && ch != '\n');
  448. if (ch == '\n') {
  449. error(linecount,s_error);
  450. return;
  451. }
  452. *--c = '\0';
  453. do {
  454. ch = input();
  455. } while (ch != '\n');
  456. /*
  457. * Remember the file name
  458. */
  459. if (strcmp(f_input,ltext)) f_input = store(ltext);
  460. }
  461. linecount = i;
  462. }
  463. # endif
  464. STATIC string
  465. vallookup(s) {
  466. /*
  467. * Look up the keyword that has token number s
  468. */
  469. register p_keyw p = resword;
  470. while (p->w_value) {
  471. if (p->w_value == s) return p->w_word;
  472. p++;
  473. }
  474. return 0;
  475. }
  476. STATIC string
  477. cpy(s,p,inserted) register string p; {
  478. /*
  479. * Create a piece of error message for token s and put it at p.
  480. * inserted = 0 if the token s was deleted (in which case we have
  481. * attributes), else it was inserted
  482. */
  483. register string t = 0;
  484. switch(s) {
  485. case C_IDENT :
  486. if (!inserted) t = lextoken.t_string;
  487. else t = "identifier";
  488. break;
  489. case C_NUMBER :
  490. t = "number";
  491. break;
  492. case C_LITERAL :
  493. if (!inserted) {
  494. *p++ = '\'';
  495. t = lextoken.t_string;
  496. break;
  497. }
  498. t = "literal";
  499. break;
  500. case C_ACTION:
  501. t = "C action";
  502. break;
  503. case C_PARAMS:
  504. t = "C parameter section";
  505. break;
  506. case C_EXPR:
  507. t = "C expression";
  508. break;
  509. case EOFILE :
  510. t = "end-of-file";
  511. break;
  512. }
  513. if (!t && (t = vallookup(s))) {
  514. *p++ = '%';
  515. }
  516. if (t) { /*
  517. * We have a string for the token. Copy it
  518. */
  519. while (*t) *p++ = *t++;
  520. if (s == C_LITERAL && !inserted) {
  521. *p++ = '\'';
  522. }
  523. return p;
  524. }
  525. /*
  526. * The token is a literal
  527. */
  528. *p++ = '\'';
  529. if (s >= 040 && s <= 0176) *p++ = s;
  530. else {
  531. *p++ = '\\';
  532. switch(s) {
  533. case '\b' : *p++ = 'b'; break;
  534. case '\f' : *p++ = 'f'; break;
  535. case '\n' : *p++ = 'n'; break;
  536. case '\r' : *p++ = 'r'; break;
  537. case '\t' : *p++ = 't'; break;
  538. default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07);
  539. *p++='0'+(s&07);
  540. }
  541. }
  542. *p++ = '\'';
  543. return p;
  544. }
  545. string strcpy();
  546. LLmessage(d) {
  547. /*
  548. * d is either 0, in which case the current token has been deleted,
  549. * or non-zero, in which case it represents a token that is inserted
  550. * before the current token
  551. */
  552. register string s,t;
  553. char buf[128];
  554. nerrors++;
  555. s = buf;
  556. if (d < 0) {
  557. strcpy(buf, "end-of-file expected");
  558. }
  559. else if (d == 0) {
  560. #ifdef LLNONCORR
  561. t = " unexpected";
  562. #else
  563. t = " deleted";
  564. #endif
  565. s = cpy(LLsymb,s,0);
  566. do *s++ = *t; while (*t++);
  567. } else {
  568. s = cpy(d,s,1);
  569. t = " inserted in front of ";
  570. do *s++ = *t++; while (*t);
  571. s = cpy(LLsymb,s,0);
  572. *s = '\0';
  573. }
  574. if (d > 0) { /*
  575. * Save the current token and make up some
  576. * attributes for the inserted token
  577. */
  578. savedtok = lextoken;
  579. savedtok.t_tokno = LLsymb;
  580. if (d == C_IDENT) lextoken.t_string = "dummy_identifier";
  581. else if (d == C_LITERAL) lextoken.t_string = "dummy_literal";
  582. else if (d == C_NUMBER) lextoken.t_num = 1;
  583. }
  584. #ifdef LLNONCORR
  585. else
  586. #endif
  587. error(linecount, "%s", buf);
  588. /* Don't change this line to
  589. * error(linecount, buf).
  590. * The string in "buf" might contain '%' ...
  591. */
  592. #ifdef LLNONCORR
  593. in_production = 1;
  594. /* To prevent warnings from copyact */
  595. #endif
  596. }