r2l.y 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644
  1. /*
  2. * This is a "yacc" specification of the syntax of RLISP. It is used
  3. * to provide a (symbolic-mode) RLISP to Lisp translator that can be
  4. * made freely available without reference to anybody apart from
  5. * myself! The Lisp dialect generated is Standard Lisp and in all reality
  6. * I intend it to be for use with CSL (my own Lisp). I am putting in
  7. * a switch that causes generation of something a bit more like Common
  8. * Lisp but please do not expect this to be fully sorted out and
  9. * suitable for use with full Common Lisp: again it is tuned to my own
  10. * private purposes...
  11. *
  12. * I will think about making this work with Bison as wall as Yacc but
  13. * maybe I prefer the licence terms associated with Yacc. But it is quite
  14. * certain that if you receive this code and can make it work with Bison
  15. * you can use it internally: the only issues are to do with distribution,
  16. * and if you are careful to use a sufficiently modern release of Bison
  17. * its skeleton code may be distributed without bad license consequences.
  18. *
  19. * Usage:
  20. * r2l -common -rights -Dname=val source1.red ... sourcen.red dest.lsp
  21. */
  22. /*
  23. * This code may be used and modified, and redistributed in binary
  24. * or source form, subject to the "CCL Public License", which should
  25. * accompany it. This license is a variant on the BSD license, and thus
  26. * permits use of code derived from this in either open and commercial
  27. * projects: but it does require that updates to this code be made
  28. * available back to the originators of the package.
  29. * Before merging other code in with this or linking this code
  30. * with other packages or libraries please check that the license terms
  31. * of the other material are compatible with those of this.
  32. */
  33. %{
  34. /*
  35. * This is a "yacc" specification of the syntax of RLISP. It is used
  36. * to provide a (symbolic-mode) RLISP to Lisp translator that can be
  37. * made freely available without reference to anybody apart from
  38. * myself! The Lisp dialect generated is Standard Lisp and in all reality
  39. * I intend it to be for use with CSL (my own Lisp). I am putting in
  40. * a switch that causes generation of something a bit more like Common
  41. * Lisp but please do not expect this to be fully sorted out and
  42. * suitable for use with full Common Lisp: again it is tuned to my own
  43. * private purposes...
  44. *
  45. * I will think about making this work with Bison as wall as Yacc but
  46. * maybe I prefer the licence terms associated with Yacc. But it is quite
  47. * certain that if you receive this code and can make it work with Bison
  48. * you can use it internally: the only issues are to do with distribution,
  49. * and if you are careful to use a sufficiently modern release of Bison
  50. * its skeleton code may be distributed without bad license consequences.
  51. *
  52. * Usage:
  53. * r2l -common -rights -Dname=val source1.red ... sourcen.red dest.lsp
  54. */
  55. /*
  56. * This code may be used and modified, and redistributed in binary
  57. * or source form, subject to the "CCL Public License", which should
  58. * accompany it. This license is a variant on the BSD license, and thus
  59. * permits use of code derived from this in either open and commercial
  60. * projects: but it does require that updates to this code be made
  61. * available back to the originators of the package.
  62. * Before merging other code in with this or linking this code
  63. * with other packages or libraries please check that the license terms
  64. * of the other material are compatible with those of this.
  65. */
  66. /* Signature: 0b607589 21-Apr-2002 */
  67. #include <stdio.h>
  68. #include <string.h>
  69. #include <ctype.h>
  70. #include <stdlib.h>
  71. int *heap;
  72. int heapfringe = 0;
  73. int yyparse();
  74. FILE *inputfile, *outputfile;
  75. FILE *filestack[30];
  76. int filestackp = 0;
  77. char *defined_names[20];
  78. int n_defined_names;
  79. int common;
  80. static char *rights_message[] =
  81. {
  82. "",
  83. " This code may be used and modified, and redistributed in binary",
  84. " or source form, subject to the \"CCL Public License\", which should",
  85. " accompany it. This license is a variant on the BSD license, and thus",
  86. " permits use of code derived from this in either open and commercial",
  87. " projects: but it does require that updates to this code be made",
  88. " available back to the originators of the package.",
  89. " Before merging other code in with this or linking this code",
  90. " with other packages or libraries please check that the license terms",
  91. " of the other material are compatible with those of this.",
  92. "",
  93. NULL
  94. };
  95. int main(int argc, char *argv[])
  96. {
  97. int rights = 0;
  98. inputfile = NULL;
  99. outputfile = NULL;
  100. common = 0;
  101. /*
  102. * If the very first arg is "-common" pick that off.
  103. */
  104. if (argc > 1 &&
  105. strcmp(argv[1], "-common") == 0)
  106. { common = 1;
  107. printf("Common Lisp mode activated\n");
  108. argv++;
  109. argc--;
  110. }
  111. /*
  112. * If the next arg is "-rights" then pick that off.
  113. */
  114. if (argc > 1 &&
  115. strcmp(argv[1], "-rights") == 0)
  116. { rights = 1;
  117. printf("Will insert re-distribution rights notice\n");
  118. argv++;
  119. argc--;
  120. }
  121. /*
  122. * Pick off initial command-line things of the form "-D..." and store the
  123. * "..." bit.
  124. */
  125. n_defined_names = 0;
  126. while (argc > 1 &&
  127. argv[1][0] == '-' &&
  128. argv[1][1] == 'D')
  129. { if (n_defined_names < 20)
  130. defined_names[n_defined_names++] = &argv[1][2];
  131. argv++;
  132. argc--;
  133. }
  134. /*
  135. * If > 1 arg then final arg is destination. If only one arg then arg is
  136. * a source!
  137. */
  138. if (argc > 2)
  139. { if (strcmp(argv[--argc], "-") == 0) outputfile = stdout;
  140. else outputfile = fopen(argv[argc], "w");
  141. }
  142. if (outputfile == NULL) outputfile = stdout;
  143. if (common)
  144. fprintf(outputfile, "\n;; RLISP to LISP converter. A C Norman 2002\n");
  145. else fprintf(outputfile, "\n%% RLISP to LISP converter. A C Norman 2002\n");
  146. fprintf(outputfile, "\n\n");
  147. if (rights)
  148. { char **p = rights_message;
  149. char *m;
  150. while ((m = *p++) != NULL)
  151. { fprintf(outputfile, "%s%s\n", (common ? ";;" : "%"), m);
  152. }
  153. fprintf(outputfile, "\n\n");
  154. }
  155. heap = (int *)malloc(2000000); /* Rather arbitrary size! */
  156. if (argc == 1) filestack[filestackp++] = stdin;
  157. else while (--argc != 0)
  158. { if ((inputfile = fopen(argv[argc], "r")) == NULL)
  159. printf("File %s not readable\n", argv[argc]);
  160. else filestack[filestackp++] = inputfile;
  161. }
  162. inputfile = filestack[--filestackp];
  163. yyparse();
  164. fclose(outputfile);
  165. printf("Finished...\n");
  166. return 0;
  167. }
  168. char *lookup_name(char *s)
  169. {
  170. int i, n = strlen(s);
  171. for (i=0; i<n_defined_names; i++)
  172. { char *w = defined_names[i]; /* name or name=value */
  173. if (strncmp(s, w, n) == 0 &&
  174. w[n] == 0 ||
  175. w[n] == '=') return (w[n]==0 ? "" : &w[n+1]);
  176. }
  177. return NULL;
  178. }
  179. char linebuffer[128];
  180. int linep = 0;
  181. int ch = '\n';
  182. int linecount = 1;
  183. int nextch()
  184. {
  185. if (ch == -1) return ch; /* end of file sticks */
  186. for (;;)
  187. { ch = getc(inputfile);
  188. if (ch == -1 && filestackp != 0)
  189. { inputfile = filestack[--filestackp];
  190. continue;
  191. }
  192. else break;
  193. }
  194. if (ch == '\n') linecount++;
  195. linebuffer[127 & linep++] = ch;
  196. return ch;
  197. }
  198. void yyerror(char *m)
  199. {
  200. int q = 0;
  201. fprintf(stderr, "\nSyntax error (%s) around line %d\n", m, linecount);
  202. if (linep >= 128) q = linep-128;
  203. while (q != linep) fprintf(stderr, "%c", linebuffer[127 & q++]);
  204. fprintf(stderr, "$$$");
  205. while ((q = nextch()) != -1 && q != '\n') fprintf(stderr, "%c", q);
  206. fprintf(stderr, "\n");
  207. fflush(stderr);
  208. exit(0);
  209. }
  210. typedef struct keyword_code
  211. {
  212. char *name;
  213. int code;
  214. } keyword_code;
  215. static keyword_code operators[];
  216. int find_symbol(char *s)
  217. {
  218. char *r = (char *)&heap[heapfringe];
  219. int len = strlen(s);
  220. strcpy(r, s);
  221. heapfringe += (len+4)/4;
  222. return (int)(r+1);
  223. }
  224. static int gennum = 1000;
  225. int genlabel()
  226. {
  227. char name[32];
  228. sprintf(name, "lab%d", gennum++);
  229. return find_symbol(name);
  230. }
  231. int genvar()
  232. {
  233. char name[32];
  234. sprintf(name, "var%d", gennum++);
  235. return find_symbol(name);
  236. }
  237. static int yylex();
  238. #define C_nil ((int)0)
  239. #define qcar(x) (((int *)(x))[0])
  240. #define qcdr(x) (((int *)(x))[1])
  241. int cons(int a, int b)
  242. {
  243. int *r = &heap[heapfringe];
  244. heapfringe += 2;
  245. qcar(r) = a;
  246. qcdr(r) = b;
  247. return (int)r;
  248. }
  249. int ncons(int a)
  250. {
  251. int *r = &heap[heapfringe];
  252. heapfringe += 2;
  253. qcar(r) = a;
  254. qcdr(r) = C_nil;
  255. return (int)r;
  256. }
  257. int list1(int a)
  258. {
  259. return cons(a, C_nil);
  260. }
  261. int list2(int a, int b)
  262. {
  263. return cons(a, cons(b, C_nil));
  264. }
  265. int list3(int a, int b, int c)
  266. {
  267. return cons(a, cons(b, cons(c, C_nil)));
  268. }
  269. int list4(int a, int b, int c, int d)
  270. {
  271. return cons(a, cons(b, cons(c, cons(d, C_nil))));
  272. }
  273. int list5(int a, int b, int c, int d, int e)
  274. {
  275. return cons(a, cons(b, cons(c, cons(d, cons(e, C_nil)))));
  276. }
  277. int list6(int a, int b, int c, int d, int e, int f)
  278. {
  279. return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, C_nil))))));
  280. }
  281. int list7(int a, int b, int c, int d, int e, int f, int g)
  282. {
  283. return cons(a, cons(b, cons(c, cons(d,
  284. cons(e, cons(f, cons(g, C_nil)))))));
  285. }
  286. int list8(int a, int b, int c, int d, int e, int f, int g, int h)
  287. {
  288. return cons(a, cons(b, cons(c, cons(d,
  289. cons(e, cons(f, cons(g, cons(h, C_nil))))))));
  290. }
  291. int list9(int a, int b, int c, int d, int e, int f, int g, int h, int i)
  292. {
  293. return cons(a, cons(b, cons(c, cons(d,
  294. cons(e, cons(f, cons(g, cons(h, cons(i, C_nil)))))))));
  295. }
  296. int append(int a, int b)
  297. {
  298. if (a == C_nil || ((a & 1) != 0)) return b;
  299. else return cons(qcar(a), append(qcdr(a), b));
  300. }
  301. #define atom(x) ((int)(x)==0 || (((int)(x)) & 1) != 0)
  302. int otlpos = 0;
  303. int checkspace(int n)
  304. {
  305. if (otlpos + n < 78)
  306. { otlpos += n;
  307. return 1;
  308. }
  309. fprintf(outputfile, "\n");
  310. otlpos = n;
  311. return 0;
  312. }
  313. static char common_name[256];
  314. char *tocommon(char *s)
  315. {
  316. int easy = 1, c;
  317. int p = 0, q = 0;
  318. if (s[0] == '"') return s; /* a string */
  319. if (isdigit(s[0])) return s; /* a number */
  320. while ((c = s[p++]) != 0)
  321. { if (c == '!') c = s[p++];
  322. common_name[q++] = c;
  323. if (c == ':') common_name[q++] = c; /* double up ':' */
  324. else if (!isalpha(c) && !isdigit(c) && c != '-' &&
  325. c != '_' && c != '*' && c != '&' && c != '$') easy = 0;
  326. }
  327. common_name[q] = 0;
  328. if (!easy)
  329. { common_name[q+1] = '|';
  330. common_name[q+2] = 0;
  331. while (q != 0)
  332. { common_name[q] = common_name[q-1];
  333. q--;
  334. }
  335. common_name[0] = '|';
  336. }
  337. return common_name;
  338. }
  339. void print(int a)
  340. {
  341. if (a == C_nil)
  342. { checkspace(3);
  343. fprintf(outputfile, "nil");
  344. return;
  345. }
  346. else if (atom(a))
  347. { char *s = ((char *)a) - 1;
  348. if (common) s = tocommon(s);
  349. checkspace(strlen(s));
  350. fprintf(outputfile, "%s", s);
  351. return;
  352. }
  353. checkspace(1);
  354. fprintf(outputfile, "(");
  355. print(qcar(a));
  356. a = qcdr(a);
  357. while (!atom(a))
  358. { if (checkspace(1)) fprintf(outputfile, " ");
  359. print(qcar(a));
  360. a = qcdr(a);
  361. }
  362. if ((int)a != 0)
  363. { checkspace(2);
  364. fprintf(outputfile, " .");
  365. if (checkspace(1)) fprintf(outputfile, " ");
  366. print(a);
  367. }
  368. checkspace(1);
  369. fprintf(outputfile, ")");
  370. }
  371. static void evalorprint(int a)
  372. {
  373. if (a != C_nil && !atom(a))
  374. { int fn = qcar(a);
  375. if (fn != C_nil && atom(fn) && strcmp((char *)fn-1, "in")==0)
  376. { a = qcar(qcdr(a));
  377. if (a != C_nil && !atom(a))
  378. { fn = qcar(a);
  379. if (fn != C_nil && atom(fn) &&
  380. strcmp((char *)fn-1, "list")==0)
  381. { a = qcar(qcdr(a));
  382. if (a != C_nil && atom(a))
  383. { FILE *f;
  384. char filename[200];
  385. char *s = (char *)a-1;
  386. if (*s == '"')
  387. { s++;
  388. s[strlen(s)-1] = 0;
  389. }
  390. if (*s != '$') strcpy(filename, s);
  391. else
  392. { char parmname[200];
  393. int k=0;
  394. char *val;
  395. s++;
  396. parmname[k++] = '@';
  397. while (*s != '/') parmname[k++] = *s++;
  398. parmname[k] = 0;
  399. val = lookup_name(parmname);
  400. if (val == NULL) val = ".";
  401. strcpy(filename, val);
  402. strcat(filename, s);
  403. }
  404. f = fopen(filename, "r");
  405. if (f == NULL)
  406. { printf("File \"%s\" not found\n", filename);
  407. exit(1);
  408. }
  409. filestack[filestackp++] = inputfile;
  410. inputfile = f;
  411. printf("READING FILE <%s>\n", filename);
  412. return;
  413. }
  414. }
  415. }
  416. }
  417. }
  418. print(a);
  419. }
  420. #define sym_0 find_symbol("0")
  421. #define sym_car find_symbol("car")
  422. #define sym_cdr find_symbol("cdr")
  423. /* I have reversip available even in Common Lisp mode for nreverse */
  424. #define sym_reversip find_symbol("reversip")
  425. #define sym_plus find_symbol("plus")
  426. #define sym_minus find_symbol("minus")
  427. #define sym_minusp find_symbol("minusp")
  428. #define sym_getv find_symbol("getv")
  429. #define sym_difference find_symbol("difference")
  430. #define sym_times find_symbol("times")
  431. #define sym_quotient find_symbol("quotient")
  432. #define sym_expt find_symbol("expt")
  433. #define sym_cons find_symbol("cons")
  434. #define sym_list find_symbol("list")
  435. #define sym_progn find_symbol("progn")
  436. #define sym_prog find_symbol("prog")
  437. #define sym_de find_symbol("de")
  438. #define sym_dm find_symbol("dm")
  439. #define sym_ds find_symbol("ds")
  440. #define sym_greaterp find_symbol("greaterp")
  441. #define sym_lessp find_symbol("lessp")
  442. #define sym_equal find_symbol("equal")
  443. #define sym_setq find_symbol("setq")
  444. #define sym_and find_symbol("and")
  445. #define sym_or find_symbol("or")
  446. #define sym_not find_symbol("not")
  447. #define sym_member find_symbol("member")
  448. #define sym_memq find_symbol("memq")
  449. #define sym_neq find_symbol("neq")
  450. #define sym_eq find_symbol("eq")
  451. #define sym_geq find_symbol("geq")
  452. #define sym_leq find_symbol("leq")
  453. #define sym_freeof find_symbol("freeof")
  454. #define sym_symbolic find_symbol("symbolic")
  455. #define sym_algebraic find_symbol("algebraic")
  456. #define sym_expr find_symbol("expr")
  457. #define sym_macro find_symbol("macro")
  458. #define sym_smacro find_symbol("smacro")
  459. #define sym_procedure find_symbol("procedure")
  460. #define sym_for find_symbol("for")
  461. #define sym_step find_symbol("step")
  462. #define sym_until find_symbol("until")
  463. #define sym_each find_symbol("each")
  464. #define sym_foreach find_symbol("foreach")
  465. #define sym_in find_symbol("in")
  466. #define sym_on find_symbol("on")
  467. #define sym_do find_symbol("do")
  468. #define sym_collect find_symbol("collect")
  469. #define sym_sum find_symbol("sum")
  470. #define sym_if find_symbol("if")
  471. #define sym_then find_symbol("then")
  472. #define sym_else find_symbol("else")
  473. #define sym_repeat find_symbol("repeat")
  474. #define sym_while find_symbol("while")
  475. #define sym_begin find_symbol("begin")
  476. #define sym_end find_symbol("end")
  477. #define sym_lsect find_symbol("<<")
  478. #define sym_rsect find_symbol(">>")
  479. #define sym_go find_symbol("go")
  480. #define sym_to find_symbol("to")
  481. #define sym_goto find_symbol("goto")
  482. #define sym_scalar find_symbol("scalar")
  483. #define sym_integer find_symbol("integer")
  484. #define sym_lambda find_symbol("lambda")
  485. #define sym_symbol find_symbol("symbol")
  486. #define sym_number find_symbol("number")
  487. #define sym_string find_symbol("string")
  488. #define sym_quoted find_symbol("quoted")
  489. #define sym_return find_symbol("return")
  490. #define sym_where find_symbol("where")
  491. #define sym_rlistat find_symbol("rlistat")
  492. #define sym_endstat find_symbol("endstat")
  493. #define sym_null find_symbol("null")
  494. int make_where(int body, int var, int val)
  495. {
  496. return list2(
  497. list3(sym_lambda, list1(var), body),
  498. val);
  499. }
  500. int make_in_do(int var, int input, int body)
  501. {
  502. int lab1 = genlabel();
  503. int var1 = genvar();
  504. return list8(sym_prog, list1(var1),
  505. list3(sym_setq, var1, input),
  506. lab1,
  507. list3(sym_if, list2(sym_null, var1), list2(sym_return, C_nil)),
  508. list4(sym_prog, list1(var), list3(sym_setq, var, list2(sym_car, var1)), body),
  509. list3(sym_setq, var1, list2(sym_cdr, var1)),
  510. list2(sym_go, lab1));
  511. }
  512. int make_on_do(int var, int input, int body)
  513. {
  514. int lab1 = genlabel();
  515. return list8(sym_prog, list1(var),
  516. list3(sym_setq, var, input),
  517. lab1,
  518. list3(sym_if, list2(sym_null, var), list2(sym_return, C_nil)),
  519. body,
  520. list3(sym_setq, var, list2(sym_cdr, var)),
  521. list2(sym_go, lab1));
  522. }
  523. int make_in_collect(int var, int input, int body)
  524. {
  525. int lab1 = genlabel();
  526. int var1 = genvar();
  527. int var2 = genvar();
  528. return list8(sym_prog, list2(var1, var2),
  529. list3(sym_setq, var1, input),
  530. lab1,
  531. list3(sym_if,
  532. list2(sym_null, var1),
  533. list2(sym_return, list2(sym_reversip, var2))),
  534. list4(sym_prog, list1(var),
  535. list3(sym_setq, var, list2(sym_car, var1)),
  536. list3(sym_setq, var2, list3(sym_cons, body, var2))),
  537. list3(sym_setq, var1, list2(sym_cdr, var1)),
  538. list2(sym_go, lab1));
  539. }
  540. int make_on_collect(int var, int input, int body)
  541. {
  542. int lab1 = genlabel();
  543. int var2 = genvar();
  544. return list8(sym_prog, list1(var),
  545. list3(sym_setq, var, input),
  546. lab1,
  547. list3(sym_if,
  548. list2(sym_null, var),
  549. list2(sym_return, list2(sym_reversip, var2))),
  550. list3(sym_setq, var2, list3(sym_cons, body, var2)),
  551. list3(sym_setq, var, list2(sym_cdr, var)),
  552. list2(sym_go, lab1));
  553. }
  554. int make_in_sum(int var, int input, int body)
  555. {
  556. int lab1 = genlabel();
  557. int var1 = genvar();
  558. int var2 = genvar();
  559. return list9(sym_prog, list2(var1, var2),
  560. list3(sym_setq, var1, input),
  561. list3(sym_setq, var2, sym_0),
  562. lab1,
  563. list3(sym_if,
  564. list2(sym_null, var1),
  565. list2(sym_return, var2)),
  566. list4(sym_prog, list1(var),
  567. list3(sym_setq, var, list2(sym_car, var1)),
  568. list3(sym_setq, var2, list3(sym_plus, body, var2))),
  569. list3(sym_setq, var1, list2(sym_cdr, var1)),
  570. list2(sym_go, lab1));
  571. }
  572. int make_foreach(int var, int type, int input, int action, int body)
  573. {
  574. int inon = 0, docollect = 0;
  575. if (strcmp((char *)type-1, "on") == 0) inon = 1;
  576. if (strcmp((char *)action-1, "collect") == 0) docollect = 1;
  577. else if (strcmp((char *)action-1, "sum") == 0) docollect = 2;
  578. switch (inon+2*docollect)
  579. {
  580. case 0: /* in/do */
  581. return make_in_do(var, input, body);
  582. case 1: /* on/do */
  583. return make_on_do(var, input, body);
  584. case 2: /* in/collect */
  585. return make_in_collect(var, input, body);
  586. case 3: /* on/collect */
  587. return make_on_collect(var, input, body);
  588. case 4: /* in/sum */
  589. return make_in_sum(var, input, body);
  590. case 5: /* on/sum WHICH CAN NOT MAKE SENSE */
  591. default:
  592. return C_nil;
  593. }
  594. }
  595. int for_do(int var, int init, int step, int end, int body)
  596. {
  597. int lab1 = genlabel();
  598. return list8(sym_prog, list1(var),
  599. list3(sym_setq, var, init),
  600. lab1,
  601. list3(sym_if,
  602. list2(sym_minusp,
  603. list3(sym_times, step,
  604. list3(sym_difference, end, var))),
  605. list2(sym_return, C_nil)),
  606. body,
  607. list3(sym_setq, var, list3(sym_plus, var, step)),
  608. list2(sym_go, lab1));
  609. }
  610. int for_collect(int var, int init, int step, int end, int body)
  611. {
  612. int lab1 = genlabel();
  613. int var1 = genvar();
  614. return list8(sym_prog, list2(var, var1),
  615. list3(sym_setq, var, init),
  616. lab1,
  617. list3(sym_if,
  618. list2(sym_minusp,
  619. list3(sym_times, step,
  620. list3(sym_difference, end, var))),
  621. list2(sym_return, list2(sym_reversip, var1))),
  622. list3(sym_setq, var1, list3(sym_cons, body, var1)),
  623. list3(sym_setq, var, list3(sym_plus, var, step)),
  624. list2(sym_go, lab1));
  625. }
  626. int for_sum(int var, int init, int step, int end, int body)
  627. {
  628. int lab1 = genlabel();
  629. int var1 = genvar();
  630. return list9(sym_prog, list2(var, var1),
  631. list3(sym_setq, var, init),
  632. list3(sym_setq, var1, sym_0),
  633. lab1,
  634. list3(sym_if,
  635. list2(sym_minusp,
  636. list3(sym_times, step,
  637. list3(sym_difference, end, var))),
  638. list2(sym_return, var1)),
  639. list3(sym_setq, var1, list3(sym_plus, body, var1)),
  640. list3(sym_setq, var, list3(sym_plus, var, step)),
  641. list2(sym_go, lab1));
  642. }
  643. int make_for(int var, int init, int step, int end, int action, int body)
  644. {
  645. int docollect = 0;
  646. if (strcmp((char *)action-1, "collect") == 0) docollect = 1;
  647. else if (strcmp((char *)action-1, "sum") == 0) docollect = 2;
  648. switch (docollect)
  649. {
  650. case 0: /* do */
  651. return for_do(var, init, step, end, body);
  652. case 1: /* collect */
  653. return for_collect(var, init, step, end, body);
  654. case 2: /* sum */
  655. return for_sum(var, init, step, end, body);
  656. default:
  657. return C_nil;
  658. }
  659. }
  660. int lex_eof = 0;
  661. %}
  662. %token SETQ
  663. %token AND
  664. %token OR
  665. %token NOT
  666. %token MEMBER
  667. %token MEMQ
  668. %token NEQ
  669. %token EQ
  670. %token GEQ
  671. %token LEQ
  672. %token FREEOF
  673. %token SYMBOLIC
  674. %token ALGEBRAIC
  675. %token EXPR
  676. %token MACRO
  677. %token SMACRO
  678. %token PROCEDURE
  679. %token FOR
  680. %token STEP
  681. %token UNTIL
  682. %token EACH
  683. %token FOREACH
  684. %token IN
  685. %token ON
  686. %token DO
  687. %token COLLECT
  688. %token SUM
  689. %token IF
  690. %token THEN
  691. %token ELSE
  692. %token REPEAT
  693. %token UNTIL
  694. %token WHILE
  695. %token BEGIN
  696. %token END
  697. %token ENDFILE
  698. %token LSECT
  699. %token RSECT
  700. %token GO
  701. %token TO
  702. %token GOTO
  703. %token SCALAR
  704. %token INTEGER
  705. %token LAMBDA
  706. %token SYMBOL
  707. %token NUMBER
  708. %token STRING
  709. %token LIST
  710. %token RETURN
  711. %token WHERE
  712. %token RLISTAT
  713. %token ENDSTAT
  714. %token HASHIF
  715. %token HASHELSE
  716. %token HASHELIF
  717. %token HASHENDIF
  718. %%
  719. /*
  720. * The grammar here is ambiguous or delicate in several areas:
  721. * (a) It has the standard "dangling else" problem.
  722. * (b) If R is a word tagged as RLIS, then R takes as its operands
  723. * a whole bunch of things linked by commas. At present I have this
  724. * grammar ambiguous on
  725. * R1 a, b, c, R2 d, e, f;
  726. * where R2 could (as far as the grammar is concerned) be being
  727. * given one, two or three arguments. This problem arises if the
  728. * operands of R may themselves end in an R. This is harded to avoid
  729. * than I at first thought - one might well want conditionals in the
  730. * are list of an R, but then
  731. * R1 a, IF x THEN R2 b, c;
  732. * comes and bites. I guess this is a "dangling comma" problem.
  733. * The above two problems are resolved by the parser genarator favouring
  734. * shift over reduce in the ambiguous cases.
  735. * (c) "IN", "ON" are both keywords, as used in
  736. * for each x in y do ...
  737. * and words with the RLISTAT property. This is sordid! Similarly
  738. * "END" has a dual use. This is coped with by making special provision
  739. * in the grammar for these cases.
  740. */
  741. wholefile : ENDFILE {
  742. if (common) fprintf(outputfile, "\n;; end of file\n");
  743. else fprintf(outputfile, "\n%% end of file\n");
  744. exit(0);
  745. }
  746. | command wholefile
  747. command : cmnd sep { evalorprint($1);
  748. fprintf(outputfile, "\n\n");
  749. otlpos = 0;
  750. heapfringe = 0;
  751. }
  752. | proc_type sep
  753. | END
  754. | END sep
  755. ;
  756. sep : ';'
  757. | '$'
  758. ;
  759. proc_type : SYMBOLIC { $$ = sym_symbolic; }
  760. | ALGEBRAIC { $$ = sym_algebraic; }
  761. ;
  762. proc_qual : EXPR { $$ = sym_de; }
  763. | MACRO { $$ = sym_dm; }
  764. | SMACRO { $$ = sym_ds; }
  765. ;
  766. sym_list : ')' { $$ = C_nil; }
  767. | ',' SYMBOL sym_list { $$ = cons($2, $3); }
  768. ;
  769. /*
  770. * RLISP seems to want to be able to write
  771. * procedure a >= b; ...
  772. * with an infix operator being defined!
  773. */
  774. infix : SETQ { $$ = sym_setq; }
  775. | OR { $$ = sym_or; }
  776. | AND { $$ = sym_and; }
  777. | MEMBER { $$ = sym_member; }
  778. | MEMQ { $$ = sym_memq; }
  779. | '=' { $$ = sym_equal; }
  780. | NEQ { $$ = sym_neq; }
  781. | EQ { $$ = sym_eq; }
  782. | GEQ { $$ = sym_geq; }
  783. | '>' { $$ = sym_greaterp; }
  784. | LEQ { $$ = sym_leq; }
  785. | '<' { $$ = sym_lessp; }
  786. | FREEOF { $$ = sym_freeof; }
  787. | '+' { $$ = sym_plus; }
  788. | '-' { $$ = sym_difference; }
  789. | '*' { $$ = sym_times; }
  790. | '/' { $$ = sym_quotient; }
  791. | '^' { $$ = sym_expt; }
  792. | '.' { $$ = sym_cons; }
  793. ;
  794. prefix : NOT { $$ = sym_not; }
  795. | '+' { $$ = sym_plus; }
  796. | '-' { $$ = sym_minus; }
  797. ;
  798. proc_head : SYMBOL { $$ = cons($1, C_nil); }
  799. | SYMBOL SYMBOL { $$ = list2($1, $2); }
  800. | SYMBOL '(' ')' { $$ = cons($1, C_nil); }
  801. | SYMBOL '(' SYMBOL sym_list
  802. { $$ = cons($1, cons($3, $4)); }
  803. | prefix SYMBOL { $$ = list2($1, $2); }
  804. | SYMBOL infix SYMBOL { $$ = list3($2, $1, $3); }
  805. ;
  806. proc_def : PROCEDURE proc_head sep cmnd
  807. { $$ = list4(sym_de, qcar($2), qcdr($2), $4); }
  808. | proc_type PROCEDURE proc_head sep cmnd
  809. { $$ = list4(sym_de, qcar($3), qcdr($3), $5); }
  810. | proc_qual PROCEDURE proc_head sep cmnd
  811. { $$ = list4($1, qcar($3), qcdr($3), $5); }
  812. | proc_type proc_qual PROCEDURE proc_head sep cmnd
  813. { $$ = list4($2, qcar($4), qcdr($4), $6); }
  814. ;
  815. rlistat : RLISTAT
  816. | IN { $$ = sym_in; }
  817. | ON { $$ = sym_on; }
  818. ;
  819. rltail : expr { $$ = cons($1, C_nil); }
  820. | expr ',' rltail { $$ = cons($1, $3); }
  821. ;
  822. /*
  823. * The category "cmnd" really only needs separating out to try to
  824. * control the comma-lists in RLIS things.
  825. */
  826. cmnd : expr
  827. | rlistat rltail { $$ = list2($1, cons(sym_list, $2)); }
  828. ;
  829. /*
  830. * As written here the grammar exhibits the traditional "dangling else"
  831. * ambiguity. This must be resolved as SHIFT rather than REDUCE for
  832. * the proper results to emerge.
  833. */
  834. if_stmt : IF expr THEN cmnd ELSE cmnd
  835. { $$ = list4(sym_if, $2, $4, $6); }
  836. | IF expr THEN cmnd { $$ = list3(sym_if, $2, $4); }
  837. ;
  838. for_update : ':' expr { $$ = cons(find_symbol("1"), $2); }
  839. | STEP expr UNTIL expr { $$ = cons($2, $4); }
  840. ;
  841. for_action : DO { $$ = sym_do; }
  842. | SUM { $$ = sym_sum; }
  843. | COLLECT { $$ = sym_collect; }
  844. ;
  845. for_inon : IN { $$ = sym_in; }
  846. | ON { $$ = sym_on; }
  847. ;
  848. for_stmt : FOR SYMBOL SETQ expr for_update for_action cmnd
  849. { $$ = make_for($2, $4, qcar($5), qcdr($5), $6, $7); }
  850. | FOR EACH SYMBOL for_inon expr for_action cmnd
  851. { $$ = make_foreach($3, $4, $5, $6, $7); }
  852. | FOREACH SYMBOL for_inon expr for_action cmnd
  853. { $$ = make_foreach($2, $3, $4, $5, $6); }
  854. ;
  855. while_stmt : WHILE expr DO cmnd {
  856. int lab1 = genlabel();
  857. $$ = list6(sym_prog, C_nil, lab1,
  858. list3(sym_if, list2(sym_null, $2), list2(sym_return, C_nil)),
  859. $4,
  860. list2(sym_go, lab1)); }
  861. ;
  862. repeat_stmt : REPEAT cmnd UNTIL expr {
  863. int lab1 = genlabel();
  864. $$ = list5(sym_prog, C_nil, lab1,
  865. $2,
  866. list3(sym_if, list2(sym_null, $4), list2(sym_go, lab1))); }
  867. ;
  868. return_stmt : RETURN { $$ = list2(sym_return, C_nil); }
  869. | RETURN expr { $$ = list2(sym_return, $2); }
  870. ;
  871. goto_stmt : GOTO SYMBOL { $$ = list2(sym_go, $2); }
  872. | GO SYMBOL { $$ = list2(sym_go, $2); }
  873. | GO TO SYMBOL { $$ = list2(sym_go, $3); }
  874. ;
  875. group_tail : RSECT { $$ = C_nil; }
  876. | sep RSECT { $$ = C_nil; }
  877. | sep cmnd group_tail { $$ = cons($2, $3); }
  878. ;
  879. group_expr : LSECT cmnd group_tail{ $$ = cons(sym_progn, cons($2, $3)); }
  880. ;
  881. scalar_tail : sep { $$ = C_nil; }
  882. | ',' SYMBOL scalar_tail
  883. { $$ = cons($2, $3); }
  884. | ',' INTEGER scalar_tail
  885. { $$ = cons($2, $3); }
  886. ;
  887. scalar_def : SCALAR SYMBOL scalar_tail
  888. { $$ = cons($2, $3); }
  889. scalar_def : INTEGER SYMBOL scalar_tail
  890. { $$ = cons($2, $3); }
  891. ;
  892. scalar_defs : scalar_def
  893. | scalar_defs scalar_def
  894. { $$ = append($1, $2); }
  895. ;
  896. block_tail : END { $$ = C_nil; }
  897. | cmnd END { $$ = cons($1, C_nil); }
  898. | SYMBOL ':' block_tail{ $$ = cons($1, $3); }
  899. | cmnd sep block_tail { $$ = cons($1, $3); }
  900. | sep block_tail { $$ = $2; }
  901. ;
  902. block_expr : BEGIN scalar_defs block_tail
  903. { $$ = cons(sym_prog, cons($2, $3)); }
  904. | BEGIN block_tail { $$ = cons(sym_prog, cons(C_nil, $2)); }
  905. ;
  906. lambda_vars : sep { $$ = C_nil; }
  907. | ',' SYMBOL lambda_vars
  908. { $$ = cons($2, $3); }
  909. ;
  910. lambda_expr : LAMBDA SYMBOL lambda_vars cmnd
  911. { $$ = list3(sym_lambda, ncons($2), $3); }
  912. | LAMBDA '(' ')' sep cmnd
  913. { $$ = list3(sym_lambda, C_nil, $5); }
  914. | LAMBDA '(' SYMBOL sym_list sep cmnd
  915. { $$ = list3(sym_lambda, cons($3, $4), $6); }
  916. ;
  917. /*
  918. * In what follows rx0 is an expression which MUST end if a key-command,
  919. * while lx0 is an expression which MUST NOT.
  920. */
  921. expr : rx0
  922. | lx0
  923. ;
  924. rx0 : lx0 WHERE SYMBOL '=' rx1
  925. { $$ = make_where($1, $3, $5); }
  926. | rx1
  927. ;
  928. lx0 : lx0 WHERE SYMBOL '=' lx1
  929. { $$ = make_where($1, $3, $5); }
  930. | lx1
  931. ;
  932. rx1 : lx2 SETQ rx1 { $$ = list3(sym_setq, $1, $3); }
  933. | rx2
  934. ;
  935. lx1 : lx2 SETQ lx1 { $$ = list3(sym_setq, $1, $3); }
  936. | lx2
  937. ;
  938. rx2tail : rx3 { $$ = ncons($1); }
  939. | lx3 OR rx2tail { $$ = cons($1, $3); }
  940. rx2 : lx3 OR rx2tail { $$ = cons(sym_or, cons($1, $3)); }
  941. | rx3
  942. ;
  943. lx2tail : lx3 { $$ = ncons($1); }
  944. | lx3 OR lx2tail { $$ = cons($1, $3); }
  945. lx2 : lx3 OR lx2tail { $$ = cons(sym_or, cons($1, $3)); }
  946. | lx3
  947. ;
  948. rx3tail : rx4 { $$ = ncons($1); }
  949. | lx4 AND rx3tail { $$ = cons($1, $3); }
  950. rx3 : lx4 AND rx3tail { $$ = cons(sym_and, cons($1, $3)); }
  951. | rx4
  952. ;
  953. lx3tail : lx4 { $$ = ncons($1); }
  954. | lx4 AND lx3tail { $$ = cons($1, $3); }
  955. lx3 : lx4 AND lx3tail { $$ = cons(sym_and, cons($1, $3)); }
  956. | lx4
  957. ;
  958. rx4 : NOT rx4 { $$ = list2(sym_not, $2); }
  959. | rx5
  960. ;
  961. lx4 : NOT lx4 { $$ = list2(sym_not, $2); }
  962. | lx5
  963. ;
  964. rx5 : lx6 MEMBER ry6 { $$ = list3(sym_member, $1, $3); }
  965. | lx6 MEMQ ry6 { $$ = list3(sym_memq, $1, $3); }
  966. | lx6 '=' ry6 { $$ = list3(sym_equal, $1, $3); }
  967. | lx6 NEQ ry6 { $$ = list3(sym_neq, $1, $3); }
  968. | lx6 EQ ry6 { $$ = list3(sym_eq, $1, $3); }
  969. | lx6 GEQ ry6 { $$ = list3(sym_geq, $1, $3); }
  970. | lx6 '>' ry6 { $$ = list3(sym_greaterp, $1, $3); }
  971. | lx6 LEQ ry6 { $$ = list3(sym_leq, $1, $3); }
  972. | lx6 '<' ry6 { $$ = list3(sym_lessp, $1, $3); }
  973. | lx6 FREEOF ry6 { $$ = list3(sym_freeof, $1, $3); }
  974. | rx6
  975. ;
  976. lx5 : lx6 MEMBER ly6 { $$ = list3(sym_member, $1, $3); }
  977. | lx6 MEMQ ly6 { $$ = list3(sym_memq, $1, $3); }
  978. | lx6 '=' ly6 { $$ = list3(sym_equal, $1, $3); }
  979. | lx6 NEQ ly6 { $$ = list3(sym_neq, $1, $3); }
  980. | lx6 EQ ly6 { $$ = list3(sym_eq, $1, $3); }
  981. | lx6 GEQ ly6 { $$ = list3(sym_geq, $1, $3); }
  982. | lx6 '>' ly6 { $$ = list3(sym_greaterp, $1, $3); }
  983. | lx6 LEQ ly6 { $$ = list3(sym_leq, $1, $3); }
  984. | lx6 '<' ly6 { $$ = list3(sym_lessp, $1, $3); }
  985. | lx6 FREEOF ly6 { $$ = list3(sym_freeof, $1, $3); }
  986. | lx6
  987. ;
  988. ry6 : NOT ry6 { $$ = list2(sym_not, $2); }
  989. | rx6
  990. ;
  991. ly6 : NOT ly6 { $$ = list2(sym_not, $2); }
  992. | lx6
  993. ;
  994. rx6tail : ry6a { $$ = ncons($1); }
  995. | ly6a '+' rx6tail { $$ = cons($1, $3); }
  996. rx6 : lx6a '+' rx6tail { $$ = cons(sym_plus, cons($1, $3)); }
  997. | rx6a
  998. ;
  999. lx6tail : ly6a { $$ = ncons($1); }
  1000. | ly6a '+' lx6tail { $$ = cons($1, $3); }
  1001. lx6 : lx6a '+' lx6tail { $$ = cons(sym_plus, cons($1, $3)); }
  1002. | lx6a
  1003. ;
  1004. ry6a : NOT ry6a { $$ = list2(sym_not, $2); }
  1005. | rx6a
  1006. ;
  1007. rx6a : lx6a '-' ry7 { $$ = list3(sym_difference, $1, $3); }
  1008. | rx7
  1009. ;
  1010. ly6a : NOT ly6a { $$ = list2(sym_not, $2); }
  1011. | lx6a
  1012. ;
  1013. lx6a : lx6a '-' ly7 { $$ = list3(sym_difference, $1, $3); }
  1014. | lx7
  1015. ;
  1016. ry7 : NOT ry7 { $$ = list2(sym_not, $2); }
  1017. | rx7
  1018. ;
  1019. rx7 : '+' ry7 { $$ = $2; }
  1020. | '-' ry7 { $$ = list2(sym_minus, $2); }
  1021. | rx8
  1022. ;
  1023. ly7 : NOT ly7 { $$ = list2(sym_not, $2); }
  1024. | lx7
  1025. ;
  1026. lx7 : '+' ly7 { $$ = $2; }
  1027. | '-' ly7 { $$ = list2(sym_minus, $2); }
  1028. | lx8
  1029. ;
  1030. rx8tail : ry9 { $$ = ncons($1); }
  1031. | ly9 '*' rx8tail { $$ = cons($1, $3); }
  1032. rx8 : lx9 '*' rx8tail { $$ = cons(sym_times, cons($1, $3)); }
  1033. | rx9
  1034. ;
  1035. lx8tail : ly9 { $$ = ncons($1); }
  1036. | ly9 '*' lx8tail { $$ = cons($1, $3); }
  1037. lx8 : lx9 '*' lx8tail { $$ = cons(sym_times, cons($1, $3)); }
  1038. | lx9
  1039. ;
  1040. ry9 : NOT ry9 { $$ = list2(sym_not, $2); }
  1041. | '+' ry9 { $$ = $2; }
  1042. | '-' ry9 { $$ = list2(sym_minus, $2); }
  1043. | rx9
  1044. ;
  1045. rx9 : lx9 '/' ry10 { $$ = list3(sym_quotient, $1, $3); }
  1046. | rx10
  1047. ;
  1048. ly9 : NOT ly9 { $$ = list2(sym_not, $2); }
  1049. | '+' ly9 { $$ = $2; }
  1050. | '-' ly9 { $$ = list2(sym_minus, $2); }
  1051. | lx9
  1052. ;
  1053. lx9 : lx9 '/' ly10 { $$ = list3(sym_quotient, $1, $3); }
  1054. | lx10
  1055. ;
  1056. ly10 : NOT ly10 { $$ = list2(sym_not, $2); }
  1057. | '+' ly10 { $$ = $2; }
  1058. | '-' ly10 { $$ = list2(sym_minus, $2); }
  1059. | lx10
  1060. ;
  1061. lx10 : lx11 '^' ly10 { $$ = list3(sym_expt, $1, $3); }
  1062. | lx11
  1063. ;
  1064. ry10 : NOT ry10 { $$ = list2(sym_not, $2); }
  1065. | '+' ry10 { $$ = $2; }
  1066. | '-' ry10 { $$ = list2(sym_minus, $2); }
  1067. | rx10
  1068. ;
  1069. rx10 : lx11 '^' ry10 { $$ = list3(sym_expt, $1, $3); }
  1070. | rx11
  1071. ;
  1072. ry11 : NOT ry11 { $$ = list2(sym_not, $2); }
  1073. | '+' ry11 { $$ = $2; }
  1074. | '-' ry11 { $$ = list2(sym_minus, $2); }
  1075. | rx11
  1076. ;
  1077. rx11 : x12 '.' ry11 { $$ = list3(sym_cons, $1, $3); }
  1078. | if_stmt
  1079. | for_stmt
  1080. | while_stmt
  1081. | repeat_stmt
  1082. | return_stmt
  1083. | goto_stmt
  1084. | lambda_expr
  1085. | proc_def
  1086. | ENDSTAT { $$ = ncons($1); }
  1087. ;
  1088. ly11 : NOT ly11 { $$ = list2(sym_not, $2); }
  1089. | '+' ly11 { $$ = $2; }
  1090. | '-' ly11 { $$ = list2(sym_minus, $2); }
  1091. | lx11
  1092. ;
  1093. lx11 : x12 '.' ly11 { $$ = list3(sym_cons, $1, $3); }
  1094. | x12
  1095. ;
  1096. arg_list : ')' { $$ = C_nil; }
  1097. | ',' expr arg_list { $$ = cons($2, $3); }
  1098. ;
  1099. parened : '(' expr ')' { $$ = $2; }
  1100. ;
  1101. commaparened : '(' expr ',' expr arg_list { $$ = cons($2, cons($4,$5)); }
  1102. ;
  1103. x12notparened : x13b '[' expr ']' { $$ = list3(sym_getv, $1, $3); }
  1104. | x13b '(' ')' { $$ = cons($1, C_nil); }
  1105. | x13b parened { $$ = cons($1, cons($2, C_nil)); }
  1106. | x13b commaparened { $$ = cons($1, $2); }
  1107. | x13b x12notparened { $$ = list2($1, $2); }
  1108. | x13b
  1109. ;
  1110. x12 : x12notparened { $$ = $1; }
  1111. | parened { $$ = $1; }
  1112. | SETQ commaparened { $$ = cons(sym_setq, $2); }
  1113. | OR commaparened { $$ = cons(sym_or, $2); }
  1114. | AND commaparened { $$ = cons(sym_and, $2); }
  1115. | MEMBER commaparened { $$ = cons(sym_member, $2); }
  1116. | MEMQ commaparened { $$ = cons(sym_memq, $2); }
  1117. | NEQ commaparened { $$ = cons(sym_neq, $2); }
  1118. | EQ commaparened { $$ = cons(sym_eq, $2); }
  1119. | GEQ commaparened { $$ = cons(sym_geq, $2); }
  1120. | LEQ commaparened { $$ = cons(sym_leq, $2); }
  1121. | FREEOF commaparened { $$ = cons(sym_freeof, $2); }
  1122. ;
  1123. x13b : SYMBOL
  1124. | NUMBER
  1125. | STRING
  1126. | LIST
  1127. | group_expr
  1128. | block_expr
  1129. ;
  1130. %%
  1131. static keyword_code operators[] =
  1132. {
  1133. {"plus", -1},
  1134. {"minus", -1},
  1135. {"getv", -1},
  1136. {"difference", -1},
  1137. {"times", -1},
  1138. {"quotient", -1},
  1139. {"expt", -1},
  1140. {"cons", -1},
  1141. {"list", -1},
  1142. {"progn", -1},
  1143. {"prog", -1},
  1144. {"de", -1},
  1145. {"dm", -1},
  1146. {"ds", -1},
  1147. {"greaterp", -1},
  1148. {"lessp", -1},
  1149. {"equal", -1},
  1150. {"setq", SETQ},
  1151. {"and", AND},
  1152. {"or", OR},
  1153. {"not", NOT},
  1154. {"member", MEMBER},
  1155. {"memq", MEMQ},
  1156. {"neq", NEQ},
  1157. {"eq", EQ},
  1158. {"geq", GEQ},
  1159. {"leq", LEQ},
  1160. {"freeof", FREEOF},
  1161. {"symbolic", SYMBOLIC},
  1162. {"algebraic", ALGEBRAIC},
  1163. {"expr", EXPR},
  1164. {"macro", MACRO},
  1165. {"smacro", SMACRO},
  1166. {"procedure", PROCEDURE},
  1167. {"for", FOR},
  1168. {"step", STEP},
  1169. {"until", UNTIL},
  1170. {"each", EACH},
  1171. {"foreach", FOREACH},
  1172. {"in", IN},
  1173. {"on", ON},
  1174. {"do", DO},
  1175. {"collect", COLLECT},
  1176. {"sum", SUM},
  1177. {"if", IF},
  1178. {"then", THEN},
  1179. {"else", ELSE},
  1180. {"repeat", REPEAT},
  1181. {"while", WHILE},
  1182. {"begin", BEGIN},
  1183. {"end", END},
  1184. {":lsect", LSECT},
  1185. {":rsect", RSECT},
  1186. {"go", GO},
  1187. {"to", TO},
  1188. {"goto", GOTO},
  1189. {"scalar", SCALAR},
  1190. {"integer", INTEGER},
  1191. {"lambda", LAMBDA},
  1192. {":symbol", SYMBOL},
  1193. {":number", NUMBER},
  1194. {":string", STRING},
  1195. {":list", LIST},
  1196. {"return", RETURN},
  1197. {"where", WHERE},
  1198. {"rlistat", RLISTAT},
  1199. {"endstat", ENDSTAT},
  1200. {"!#if", HASHIF},
  1201. {"!#else", HASHELSE},
  1202. {"!#elif", HASHELIF},
  1203. {"!#endif", HASHENDIF},
  1204. {NULL, 0}
  1205. };
  1206. int skipcomment()
  1207. {
  1208. if (ch == '%')
  1209. { while (ch != '\n' && ch != -1) nextch();
  1210. return 1;
  1211. }
  1212. else return 0;
  1213. }
  1214. static int onechar(int c)
  1215. {
  1216. char b[4];
  1217. b[0] = c;
  1218. b[1] = 0;
  1219. return find_symbol(b);
  1220. }
  1221. int lisp_token()
  1222. {
  1223. char buffer[1000];
  1224. int bp = 0, num = 0, r;
  1225. while (isspace(ch) || skipcomment()) nextch();
  1226. num = isdigit(ch);
  1227. while (isalpha(ch) || isdigit(ch) || ch=='_' || ch == '!' ||
  1228. (num && ch == '.'))
  1229. { buffer[bp++] = ch;
  1230. if (ch == '!')
  1231. { buffer[bp++] = nextch();
  1232. }
  1233. nextch();
  1234. }
  1235. buffer[bp] = 0;
  1236. if (bp != 0)
  1237. { yylval = find_symbol((char *)buffer);
  1238. return num ? '0': 'a';
  1239. }
  1240. if (ch == '"')
  1241. { for (;;)
  1242. { buffer[bp++] = ch;
  1243. while (nextch() != '"' && ch != '\n' && ch != EOF)
  1244. buffer[bp++] = ch;
  1245. buffer[bp++] = ch;
  1246. if (nextch() != '"') break;
  1247. }
  1248. buffer[bp] = 0;
  1249. yylval = find_symbol((char *)buffer);
  1250. return '"';
  1251. }
  1252. if (ch == '\'' || ch == '(' || ch == ')' || ch == '.')
  1253. { r = ch;
  1254. nextch();
  1255. return r;
  1256. }
  1257. r = ch;
  1258. nextch();
  1259. return onechar(r);
  1260. }
  1261. static int read_tail();
  1262. /*
  1263. * L -> atom
  1264. * L -> ' L
  1265. * L -> ( T
  1266. * L -> . error
  1267. * L -> ) error
  1268. *
  1269. * T -> )
  1270. * T -> . L )
  1271. * T -> L T
  1272. *
  1273. */
  1274. static int read_list(int r)
  1275. {
  1276. switch (r)
  1277. {
  1278. case '(': return read_tail();
  1279. case '.':
  1280. case ')': return C_nil; /* errors! */
  1281. case '\'':
  1282. return list2(find_symbol("quote"), read_list(lisp_token()));
  1283. default:
  1284. return yylval;
  1285. }
  1286. }
  1287. int read_tail()
  1288. {
  1289. int r;
  1290. switch (r = lisp_token())
  1291. {
  1292. case ')': return C_nil;
  1293. case '.': r = read_list(lisp_token());
  1294. if (lisp_token() != ')') fprintf(stderr, "\nBad syntax after '.'\n");
  1295. return r;
  1296. case '\'':
  1297. r = list2(find_symbol("quote"), read_list(lisp_token()));
  1298. return cons(r, read_tail());
  1299. case '(': r = read_list(r);
  1300. return cons(r, read_tail());
  1301. default: r = yylval;
  1302. return cons(r, read_tail());
  1303. }
  1304. }
  1305. static int skipping = 0;
  1306. static int genuine_yylex();
  1307. static int evaluates_to_true(int r)
  1308. {
  1309. int fn, arg;
  1310. char *s, *v;
  1311. if (r == C_nil) return 0;
  1312. else if (atom(r))
  1313. { s = (char *)r;
  1314. v = lookup_name(s-1);
  1315. if (v == NULL) return 0;
  1316. else return 1;
  1317. }
  1318. fn = qcar(r);
  1319. r = qcdr(r);
  1320. if (fn == C_nil || !atom(fn)) return 0;
  1321. s = (char *)fn;
  1322. if (strcmp(s-1, "and") == 0)
  1323. { while (r != C_nil && !atom(r))
  1324. { arg = qcar(r);
  1325. r = qcdr(r);
  1326. if (!evaluates_to_true(arg)) return 0;
  1327. }
  1328. return 1;
  1329. }
  1330. else if (strcmp(s-1, "or") == 0)
  1331. { while (r != C_nil && !atom(r))
  1332. { arg = qcar(r);
  1333. r = qcdr(r);
  1334. if (evaluates_to_true(arg)) return 1;
  1335. }
  1336. return 0;
  1337. }
  1338. else if (strcmp(s-1, "not") == 0)
  1339. return !evaluates_to_true(qcar(r));
  1340. else return 0; /* junk treated as false! */
  1341. }
  1342. static void skip_tokens()
  1343. {
  1344. int r;
  1345. skipping = 1;
  1346. for (;;)
  1347. { r = genuine_yylex();
  1348. switch (r)
  1349. {
  1350. case HASHIF:
  1351. skipping++;
  1352. continue;
  1353. case HASHELSE:
  1354. if (skipping == 1)
  1355. { skipping = 0;
  1356. return;
  1357. }
  1358. else continue;
  1359. case HASHELIF:
  1360. if (skipping == 1)
  1361. { skipping = 0;
  1362. r = read_list(lisp_token());
  1363. if (evaluates_to_true(r)) return;
  1364. skipping = 1;
  1365. continue;
  1366. }
  1367. else continue;
  1368. case HASHENDIF:
  1369. skipping--;
  1370. if (skipping == 0) return;
  1371. else continue;
  1372. default:continue;
  1373. }
  1374. }
  1375. }
  1376. static int genuine_yylex()
  1377. {
  1378. char buffer[1000];
  1379. int bp, num, r;
  1380. restart_lex:
  1381. bp = 0;
  1382. num = 0;
  1383. while (isspace(ch) || skipcomment()) nextch();
  1384. if (ch == -1)
  1385. { if (skipping)
  1386. { printf("\n+++ EOF while within !#if\n");
  1387. exit(1);
  1388. }
  1389. return ENDFILE;
  1390. }
  1391. num = isdigit(ch);
  1392. while (isalpha(ch) || isdigit(ch) || ch=='_' || ch == '!' ||
  1393. (num && ch == '.'))
  1394. { buffer[bp++] = ch;
  1395. if (ch == '!')
  1396. { buffer[bp++] = nextch();
  1397. }
  1398. nextch();
  1399. }
  1400. buffer[bp] = 0;
  1401. if (bp != 0)
  1402. { int k;
  1403. for (k=0;;k++)
  1404. { char *n = operators[k].name;
  1405. int v = operators[k].code;
  1406. if (n == NULL) break;
  1407. if (v < 0) continue;
  1408. if (strcmp(n, buffer) == 0)
  1409. {
  1410. switch (v)
  1411. {
  1412. case HASHIF:
  1413. if (skipping != 0) return v;
  1414. r = read_list(lisp_token());
  1415. if (!evaluates_to_true(r)) skip_tokens();
  1416. goto restart_lex;
  1417. case HASHELSE:
  1418. case HASHELIF:
  1419. if (skipping != 0) return v;
  1420. skip_tokens();
  1421. goto restart_lex;
  1422. case HASHENDIF:
  1423. if (skipping != 0) return v;
  1424. else goto restart_lex; /* Ignore it! */
  1425. default:break;
  1426. }
  1427. return v;
  1428. }
  1429. }
  1430. yylval = find_symbol((char *)buffer);
  1431. return num ? NUMBER : SYMBOL;
  1432. }
  1433. if (ch == '"')
  1434. { for (;;)
  1435. { buffer[bp++] = ch;
  1436. while (nextch() != '"' && ch != EOF && ch != '\n')
  1437. buffer[bp++] = ch;
  1438. buffer[bp++] = ch;
  1439. if (nextch() != '"') break;
  1440. }
  1441. buffer[bp] = 0;
  1442. yylval = find_symbol((char *)buffer);
  1443. return STRING;
  1444. }
  1445. if (ch == '\'')
  1446. { nextch();
  1447. r = read_list(lisp_token());
  1448. yylval = list2(find_symbol("quote"), r);
  1449. return LIST;
  1450. }
  1451. r = ch;
  1452. nextch();
  1453. if (r == ':' && ch == '=') { nextch(); r = SETQ; }
  1454. else if (r == '<' && ch == '=') { nextch(); r = LEQ; }
  1455. else if (r == '>' && ch == '=') { nextch(); r = GEQ; }
  1456. else if (r == '<' && ch == '<') { nextch(); r = LSECT; }
  1457. else if (r == '>' && ch == '>') { nextch(); r = RSECT; }
  1458. return r;
  1459. }
  1460. static int yylex()
  1461. {
  1462. return genuine_yylex();
  1463. }
  1464. /* end of file */