lalr.red 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570
  1. symbolic;
  2. spool "lalr.log";
  3. on comp, backtrace;
  4. unglobal '(!*raise);
  5. fluid '(!*raise);
  6. %=============================================================================
  7. % The file provides parser support for Lisp. The file contains three
  8. % major sections. The first is a lexical analyser, which has been
  9. % coded to support RLISP and Standard Lisp. Its interface is modelled after
  10. % the one used with the lex/yacc combination commonly used with Unix.
  11. %
  12. % The second section is the generic part of an LR parser. It requires
  13. % tables to tell it what actions to take, and calls the lexical analyser to
  14. % obtain tokens.
  15. %
  16. % The final part is an LALR(1) parser generator, which can take the
  17. % specification of a grammar and construct tables that direct the
  18. % generic parser skeleton.
  19. %
  20. %=============================================================================
  21. %
  22. % This is a lexical anaylser for use with RLISP. Its interface is
  23. % styles after the one needed by yacc, in that it exports a function
  24. % called yylex() that returns as a value a numeric category code, but
  25. % sets a variable yylval to hold further information about the token
  26. % just parsed. Single character objects are coded as their (ASCII?) code
  27. % [leaving this code non-portable to machines with other encodings?].
  28. % Other things must have been given 'lex_code properties indicate the
  29. % associated category code. This lexer handles ' and ` as special prefix
  30. % characters that introduce Lisp-stype s-expressions. and it knows about
  31. % RLISP-style comments and a few diphthongs. It also supports some
  32. % simple preprocessor directives.
  33. %
  34. % Arthur Norman. April 1995
  35. fluid '(!*raise !*lower !*echo);
  36. global '(lex_char yylval last64 last64p which_line);
  37. % I keep a circular buffer with the last 64 characters that have been
  38. % read. Initially the buffer contains NILs rather than characters, so I can
  39. % tell when it is only partially filled.
  40. smacro procedure yyreadch();
  41. << last64p := last64p + 1;
  42. if last64p = 64 then last64p := 0;
  43. lex_char := readch();
  44. if lex_char = !$eol!$ then which_line := which_line + 1;
  45. putv(last64, last64p, lex_char);
  46. lex_char >>;
  47. symbolic procedure yyerror msg;
  48. begin
  49. scalar c;
  50. terpri();
  51. princ "+++++ Parse error at line "; prin which_line; princ ":";
  52. if atom msg then msg := list msg;
  53. for each s in msg do << princ " "; princ s >>;
  54. terpri();
  55. for i := 1:64 do <<
  56. last64p := last64p + 1;
  57. if last64p = 64 then last64p := 0;
  58. c := getv(last64, last64p);
  59. if c = !$eof!$ then princ "<EOF>"
  60. else if not (c = nil) then princ c >>;
  61. if not (c = !$eol!$) then terpri()
  62. end;
  63. % Before a succession of calls to yylex() it is necessary to
  64. % ensure that lex_char is set suitably and that the circular buffer
  65. % used to store characters for error messages is ready for use.
  66. symbolic procedure start_parser();
  67. << last64 := mkvect 64;
  68. last64p := 0;
  69. which_line := 1;
  70. yyreadch() >>;
  71. %
  72. % The following version of YYLEX provides RLISP with a facility for
  73. % conditional compilation. The protocol is that text is included or
  74. % excluded at the level of tokens. Control by use of new reserved
  75. % tokens !#if, !#else and !#endif. These are used in the form:
  76. % !#if (some Lisp expression for use as a condition)
  77. % ... RLISP input ...
  78. % !#else
  79. % ... alternative RLISP input ...
  80. % !#endif
  81. %
  82. % The form
  83. % !#if C1 ... !#elif C2 ... !#elif C3 ... !#else ... !#endif
  84. % is also supported.
  85. %
  86. % Conditional compilation can be nested. If the Lisp expression used to
  87. % guard a condition causes an error it is taken to be a FALSE condition.
  88. % It is not necessary to have an !#else before !#endif if no alternative
  89. % text is needed. Although the examples here put !#if etc at the start of
  90. % lines this is not necessary (though it may count as good style?). Since
  91. % the condtion will be read using RLISPs own list-reader there could be
  92. % condtional compilation guarding parts of it - the exploitation of that
  93. % possibility is to be discouraged!
  94. %
  95. % Making the condition a raw Lisp expression makes sure that parsing it
  96. % is easy. It makes it possible to express arbitrary conditions, but it is
  97. % hoped that most conditions will not be very elaborate - things like
  98. % !#if (not (member 'csl lispsystem!*))
  99. % error();
  100. % !#else
  101. % magic();
  102. % !#endif
  103. % or
  104. % !#if debugging_mode % NB if variable is unset that counts as nil
  105. % print "message"; % so care should be taken to select the most
  106. % !#endif % useful default sense for such tests
  107. % should be about as complicated as reasonable people need.
  108. %
  109. % Two further facilities are provided:
  110. % !#eval (any lisp expression)
  111. % causes that expression to be evaluated at parse time. Apart from any
  112. % side-effects in the evaluation the text involved is all ignored. It is
  113. % expected that this will only be needed in rather curious cases, for instance
  114. % to set system-specific options for a compiler.
  115. %
  116. % !#define symbol value
  117. % where the value should be another symbol, a string or a number, causes
  118. % the first symbol to be mapped onto the second value wherever it occurs in
  119. % subsequent input. No special facility for undoing the effect of a
  120. % !#define is provided, but the general-purpose !#eval could be used to
  121. % remove the '!#define property that is involved.
  122. %
  123. % NOTE: The special symbols !#if etc are NOT recognised within Lisp
  124. % quoted expressions, so test like the following will be
  125. % ineffective:
  126. % a := '(
  127. % P
  128. % !#if q_is_wanted
  129. % Q
  130. % !#endif
  131. % Q);
  132. % but on the other hand code like
  133. % if sym = '!#if then ...
  134. % behaves the way that had probably been wanted. Unlike the C
  135. % preprocessor, this system recognizes directives within rather than
  136. % just at the start of lines.
  137. symbolic procedure yylex();
  138. begin
  139. scalar w, done;
  140. % I take a rather robust view here - words that are intended to be used as
  141. % keywords may not be written with included escape characters. Thus for
  142. % instance this lexer will view "be!gin" or "!begin" as being a simple
  143. % symbol and NOT being the keyword "begin".
  144. w := lex_basic_token();
  145. % The "while not done" loop is so that I can restart the scan after seeing
  146. % a pre-processor directive such as !#if.
  147. while not done do <<
  148. % The word "COMMENT" introduces a comment that terminates at the next ";"
  149. % or "$".
  150. while yylval = 'comment and
  151. w = '!:symbol_or_keyword do <<
  152. while not (lex_char = '!; or lex_char = '!$) do
  153. yyreadch();
  154. yyreadch();
  155. w := lex_basic_token() >>;
  156. % If a word was spelt out directly (without any escape characters in it) it
  157. % may be a keyword - if it is, then convert it here.
  158. if w = '!:symbol_or_keyword then <<
  159. if w := get(yylval, '!#define) then <<
  160. yylval := cdr w;
  161. w := car w >>
  162. else <<
  163. if done := get(yylval, 'lex_code) then w := done
  164. else if flagp(yylval, 'rlis) then
  165. w := get('rlistat, 'lex_code)
  166. else if flagp(yylval, 'endstat) then
  167. w := get('endstat, 'lex_code)
  168. else w := get('!:symbol, 'lex_code);
  169. done := t >> >>
  170. % A word with escapes in might be a pre-processor directive.
  171. else if w = '!:symbol then <<
  172. if yylval eq '!#if then <<
  173. read_s_expression();
  174. w := lex_conditional yylval >>
  175. else if yylval eq '!#else or
  176. yylval eq '!#elif then <<
  177. yylval := nil;
  178. w := lex_skipping(w, nil) >>
  179. else if yylval eq '!#endif then w := lex_basic_token()
  180. else if yylval eq '!#eval then <<
  181. read_s_expression();
  182. errorset(yylval, nil, nil);
  183. w := lex_basic_token() >>
  184. else if yylval eq '!#define then <<
  185. read_s_expression();
  186. w := yylval; % Ought to be a symbol
  187. done := read_s_expression();
  188. if idp w then put(w, '!#define, done . yylval);
  189. w := lex_basic_token();
  190. done := nil >>
  191. else <<
  192. w := get('!:symbol, 'lex_code);
  193. done := t >> >>
  194. else if numberp w then <<
  195. % Now gobble up extra characters for multi-character operators (eg ">=").
  196. % Note that I only look one character ahead here.
  197. while done := atsoc(lex_char, get(yylval, 'lex_dipthong)) do <<
  198. w := cdr done;
  199. yylval := cdr w;
  200. w := get(car w, 'lex_code);
  201. yyreadch() >>;
  202. if done := get(yylval, '!#define) then <<
  203. yylval := cdr done;
  204. w := car done;
  205. done := nil >>
  206. else done := t >>
  207. else <<
  208. done := t;
  209. w := get(w, 'lex_code) >> >>;
  210. return w
  211. end;
  212. % If, when reading ordinary text, I come across the token !#if I read
  213. % the expression following. If that evaluates to TRUE I just keep on
  214. % on reading. So the sequence "!#if t" is in effect ignored. Then
  215. % if later on I just ignore an "!#endif" all will be well. If on the other
  216. % hand the expression evaluates to NIL (or if evaluation fails), I will
  217. % call lex_skipping() to discard more tokens (up to and including
  218. % the next "!#else", "!#elif t" or "!endif").
  219. symbolic procedure lex_conditional x;
  220. begin
  221. scalar w;
  222. w := lex_basic_token();
  223. x := errorset(x, nil, nil);
  224. if errorp x or null car x then return lex_skipping(w, nil)
  225. else return w
  226. end;
  227. % I call lex_skipping when I find "!#if nil" or "!#else" or "!#elif"
  228. % that is processed. When a top-level "!#else" or "!#elif" is found it
  229. % is discarded before calling lex_skipping, since it must follow a
  230. % successful "!#if" and hence introduce material to be thrown away.
  231. symbolic procedure lex_skipping(w, x);
  232. begin
  233. scalar done;
  234. % In this code x keep track of the depth of testing of "!#if" constructions
  235. while not done do <<
  236. if w = 0 then done := t % End of file
  237. else <<
  238. if w = '!:symbol then <<
  239. if yylval = '!#endif then <<
  240. if null x then done := t
  241. else x := cdr x >>
  242. else if yylval = '!#if then x := nil . x
  243. else if yylval = '!#else and null x then done := t
  244. else if yylval = '!#elif and null x then <<
  245. read_s_expression();
  246. done := errorset(yylval, nil, nil);
  247. if errorp done or null car done then done := nil >> >>;
  248. w := lex_basic_token() >> >>;
  249. return w
  250. end;
  251. % In some cases RLISP operators are made up out of two (or more) characters.
  252. % I map '**' onto '^', and >=, <= onto GEQ and LEQ.
  253. % ":=" becomes SETQ. I turn << and >> onto symbols that can not be
  254. % read directly (!:lsect and !:rsect).
  255. % This means that the system that sets up lex_code properties had really
  256. % better make sure that it gives setq, geq, leq, !:rsect and !:lsect values.
  257. put('!*, 'lex_dipthong, '((!* !^ . !^)));
  258. put('!:, 'lex_dipthong, '((!= setq . setq)));
  259. put('!>, 'lex_dipthong, '((!= geq . geq),
  260. (!> !:rsect . !:rsect)));
  261. put('!<, 'lex_dipthong, '((!= leq . leq),
  262. (!< !:lsect . !:lsect)));
  263. put('!^, 'lex_code, char!-code '!^);
  264. % lex_basic_token() will read the next token from the current input stream and
  265. % leave a value in yylval to show what was found. It does not handle the
  266. % word "comment", nor does it consolidate things like ':' followed by '=' into
  267. % ':='. Those steps are left to yylex(). But lex_basic_token() does recognize
  268. % the quote prefix, as in '(lisp expression). The return value is numeric
  269. % for single-character tokens, but otherwise a descriptive symbol.
  270. % Some people would consider the Lisp dialect that I am using here to be
  271. % significantly flawed, in that I need to build symbols, numbers and
  272. % strings up as lists, and then use COMPRESS to make the real objects. The
  273. % CONS operations involved can be seen as an overhead, and going back to
  274. % something like the VERY old-fashioned clearbuff/pack/boffo world might
  275. % avoid that.
  276. symbolic procedure lex_basic_token();
  277. begin
  278. scalar r, w;
  279. % First skip over whitespace. Note that at some stage in the future RLISP
  280. % may want to make newlines significant and partially equivalent to
  281. % semicolons, but that is not supported at present.
  282. while lex_char = '! or lex_char = !$eol!$ or
  283. (lex_char = '!% and <<
  284. while not (lex_char = !$eol!$ or lex_char = !$eof!$) do
  285. yyreadch();
  286. t >>) do yyreadch();
  287. % Symbols start with a letter or an escaped character and continue with
  288. % letters, digits, underscores and escapes.
  289. if liter lex_char or
  290. (lex_char = '!! and begin
  291. scalar !*raise, !*lower; % Rebind !*raise & !*lower to avoid..
  292. r := lex_char . r; % case folding when the next character..
  293. yyreadch(); % is read.
  294. return (w := t) end) then <<
  295. r := lex_char. r;
  296. while liter(yyreadch()) or
  297. digit lex_char or
  298. lex_char = '!_ or
  299. (lex_char = '!! and begin
  300. scalar !*raise, !*lower;
  301. r := lex_char . r;
  302. yyreadch();
  303. return (w := t) end) do
  304. r := lex_char . r;
  305. % If there was a '!' in the word I will never treat it as a keyword.
  306. yylval := compress reversip r;
  307. return if w then '!:symbol else '!:symbol_or_keyword >>
  308. % Numbers are either integers or floats. A floating point number is
  309. % indicated by either a point "." or an exponent marker "e". In the code
  310. % here I keep a flag (in w) to indicate if I had a floating or integer
  311. % value, but in the end I ignore this and hand back the lexical category
  312. % :number in both cases.
  313. else if digit lex_char then <<
  314. r := list lex_char;
  315. while digit (yyreadch()) do r := lex_char . r;
  316. if lex_char = '!. then <<
  317. w := t; % Flag to indicate floating point
  318. r := lex_char . r;
  319. while digit (yyreadch()) do r := lex_char . r >>;
  320. % I permit the user to write the exponent marker in either case.
  321. if lex_char = '!e or lex_char = '!E then <<
  322. % If the input as 1234E56 I expand it as 1234.0E56
  323. if not w then r := '!0 . '!. . r;
  324. w := t;
  325. r := '!e . r;
  326. yyreadch();
  327. if lex_char = '!+ or lex_char = '!- then <<
  328. r := lex_char . r;
  329. yyreadch() >>;
  330. % If there is no digit written after "E" I insert a zero. Thus overall the
  331. % input 17E gets treated as 17.0E0
  332. if not digit lex_char then r := '!0 . r
  333. else <<
  334. r := lex_char . r;
  335. while digit (yyreadch()) do r := lex_char . r >> >>;
  336. yylval := compress reversip r;
  337. return '!:number >>
  338. % Strings are enclosed in double-quotes, and "abc""def" is a string with
  339. % a double-quote mark within it. Note no case folding on characters in a
  340. % string.
  341. else if lex_char = '!" then <<
  342. begin
  343. scalar !*raise, !*lower;
  344. repeat <<
  345. r := lex_char . r;
  346. while not ((yyreadch()) = '!") do r := lex_char . r;
  347. r := lex_char . r;
  348. yyreadch() >> until not (lex_char = '!");
  349. end;
  350. yylval := compress reversip r;
  351. return '!:string >>
  352. % "'" and "`" introduce Lisp syntax S-expressions
  353. else if lex_char = '!' then <<
  354. yyreadch();
  355. read_s_expression();
  356. yylval := list('quote, yylval);
  357. return '!:list >>
  358. else if lex_char = '!` then <<
  359. yyreadch();
  360. read_s_expression();
  361. yylval := list('backquote, yylval);
  362. return '!:list >>
  363. else <<
  364. yylval := lex_char;
  365. % I take special notice of end of file, since it is fairly drastic.
  366. % In particular I do not attempt to advance lex_char beyond it. So I do
  367. % TWO things here: I avoid advancing the input, and I return the code 0
  368. % as an end-of-file indication.
  369. if yylval = !$eof!$ then return 0
  370. else <<
  371. yyreadch();
  372. return char!-code yylval >> >>
  373. end;
  374. %
  375. % I use a hand-written recursive descent parser for Lisp S-expressions
  376. % mainly because the syntax involved is so VERY simple. A rough sketch of
  377. % the syntax required is given here, but in reality (in part because I do
  378. % not want to have to report syntax errors) I implement a more liberal
  379. % syntax, especially as it relates to dotted-pair notation. This of course
  380. % is one of the natural dangers in using recursive descent... the syntax
  381. % actually parsed is only properly defined by direct reference to the code.
  382. %
  383. % s_tail = ")" |
  384. % "." s_expr ")" |
  385. % s_expr s_tail;
  386. %
  387. % s_vectail = "]" |
  388. % s_expr s_vectail;
  389. %
  390. % s_expr = symbol |
  391. % number |
  392. % string |
  393. % "(" s_tail |
  394. % "[" s_vectail |
  395. % "'" s_expr |
  396. % "`" s_expr |
  397. % "," s_expr |
  398. % ",@" s_expr;
  399. global '(dot_char rpar_char rsquare_char);
  400. dot_char := char!-code '!.;
  401. rpar_char := char!-code '!);
  402. rsquare_char := char!-code '!];
  403. symbolic procedure read_s_expression();
  404. <<
  405. % At the start of an S-expression I want to check for the characters
  406. % "(", "[" and ",". Thus I need to skip whitespace.
  407. while lex_char = '! or lex_char = '!$eol!$ do yyreadch();
  408. if lex_char = '!( then begin
  409. scalar r, w, w1;
  410. yyreadch();
  411. w := read_s_expression();
  412. while not (w = rpar_char or w = dot_char or w = 0) do <<
  413. r := yylval . r;
  414. % Note that at the end of the list read_s_expression() will read the ")"
  415. % as a token.
  416. w := read_s_expression() >>;
  417. if not w = dot_char then yylval := reversip r
  418. else <<
  419. read_s_expression(); % Thing after the "."
  420. w := yylval;
  421. % Reverse the list putting a dotted item on the end.
  422. while r do <<
  423. w1 := cdr r;
  424. rplacd(r, w);
  425. w := r;
  426. r := w1 >>;
  427. yylval := w;
  428. % I will be somewhat liberal about syntactic problems with dotted pair
  429. % notation, since it is unclear how I can usefully report or repair errors.
  430. while lex_char = '! or lex_char = '!$eol!$ do
  431. yyreadch();
  432. % When I find a ")" I do not read beyond it immediately, but reset lex_char
  433. % to whitespace. This may help prevent unwanted hangups in interactive use.
  434. if lex_char = '!) then lex_char := '! >>;
  435. return '!:list end
  436. % "[" introduces a simple vector.
  437. else if lex_char = '![ then begin
  438. scalar r, w, w1;
  439. yyreadch();
  440. w := read_s_expression();
  441. w1 := -1;
  442. while not (w = rsquare_char or w = 0) do <<
  443. r := yylval . r;
  444. w1 := w1 + 1;
  445. w := read_s_expression() >>;
  446. % Create a vector of the correct size and copy information into it.
  447. w := mkvect w1;
  448. r := reversip r;
  449. w1 := 0;
  450. while r do <<
  451. putv(w, w1, car r);
  452. w1 := w1 + 1;
  453. r := cdr r >>;
  454. yylval := w;
  455. return '!:list end
  456. % I spot "," and ",@" here, and should wonder if I should (a) police that
  457. % they are only expected to make sense within the scope of a "`" and (b)
  458. % whether I ought to expand them in terms of LIST, CONS, APPEND etc here.
  459. % For now I just hand back markers that show where they occured.
  460. else if lex_char = '!, then <<
  461. yyreadch();
  462. if lex_char = '!@ then <<
  463. yyreadch();
  464. read_s_expression();
  465. yylval := list('!,!@, yylval) >>
  466. else <<
  467. read_s_expresssion();
  468. yylval := list('!,, yylval) >>;
  469. 'list >>
  470. % Care with ")" and "]" not to read ahead further than is essential.
  471. else if lex_char = '!) or lex_char = '!] or lex_char = '!. then <<
  472. yylval := lex_char;
  473. lex_char := '! ;
  474. char!-code yylval >>
  475. % In most cases (including "'" and "`") I just hand down to read a token.
  476. % This covers the cases of symbols, numbers and strings.
  477. else lex_basic_token() >>;
  478. %=============================================================================
  479. % Here I have a general-purpose LR(1) parser skeleton. This needs to
  480. % have a source of tokens, and some tables that will direct its actions.
  481. % The format of the tables required by this code will be a little curious,
  482. % mainly because they represent some attempt to compact the information that
  483. % is needed. Note that the CSL functions mkvect16, putv16, getv16 are
  484. % somewhat similar to the regular mkvect, putv and getv, but may be used
  485. % if the vector contents will always be 16-bit fixnums.
  486. global '(!*verbose);
  487. !*verbose := t; % How much will the parset-generator print?
  488. global '(goto_index goto_old_state goto_new_state);
  489. % For each terminal I have a pointer (stored in goto_index) into
  490. % a pair of vectors, goto_old_state and goto_new_state. The first of these
  491. % holds states that I might be in, and the second holds the ones I must
  492. % move into after a reduction has been performed. In the goto_old_state
  493. % table the value "-1" is taken to match any state that I am attempting
  494. % to look up. Thus it can be used to terminate a segment of the table. I am
  495. % entitled to let undefined locations in the goto table respond with
  496. % any value that just happens.
  497. smacro procedure get_goto(state, non_terminal);
  498. << w1 := getv16(goto_index, non_terminal);
  499. while not (((w2 := getv16(goto_old_state, w1)) = -1) or
  500. w2 = state) do w1 := w1 + 1;
  501. getv16(goto_new_state, w1) >>;
  502. global '(action_index, action_terminal action_result);
  503. % In a rather similar way, actions are found via an association-list
  504. % like look-up in a table. In this table a strictly positive number n stands
  505. % for (SHIFT n) [observe that if I reserve zero as the number of the
  506. % initial state of my augmented grammar I can never need to shift into
  507. % state 0]. The value 0 in the table represents ACCEPT. This leaves
  508. % nagative values to cover reductions and error cases.
  509. smacro procedure get_action(state, terminal);
  510. << w1 := getv16(action_index, state);
  511. while not (((w2 := getv16(action_terminal, w1)) = -1) or
  512. w2 = terminal) do w1 := w1 + 1;
  513. getv(action_result, w1) >>;
  514. global '(action_first_error action_error_messages);
  515. global '(action_fn action_A action_n);
  516. symbolic procedure yyparse();
  517. begin
  518. scalar sym_stack, state_stack, next_input, w, w1, w2;
  519. state_stack := list 0; % Note that state 0 must be the initial one.
  520. start_parser();
  521. next_input := yylex();
  522. while not (w := get_action(car state_stack, next_input)) = 0 do
  523. if w > 0 then <<
  524. sym_stack := next_input . sym_stack;
  525. state_stack := cadr w . state_stack;
  526. next_input := yylex() >>
  527. else begin
  528. scalar A, n, action;
  529. w := - (w + 1);
  530. if w < action_first_error then <<
  531. action := getv(action_fn, w);
  532. n := getv8(action_n, w);
  533. A := getv16(action_A, w);
  534. % I am now reducing by "A -> beta { action() }" where beta has n items
  535. w := nil;
  536. for i := 1:n do <<
  537. w := car sym_stack . w;
  538. sym_stack := cdr sym_stack;
  539. state_stack := cdr state_stack >>;
  540. w := reversip w;
  541. if action then w := apply1(action, w)
  542. else w := A . w;
  543. sym_stack := w . sym_stack;
  544. state_stack := get_goto(car state_stack, A) >>
  545. else <<
  546. w := w - action_first_error;
  547. yyerror getv(action_error_messages, w);
  548. % The next activity must result in the loop ending...
  549. state_stack := list 0;
  550. sym_stack := '(error);
  551. next_input := 0 >>
  552. end;
  553. return car sym_stack
  554. end;
  555. %=============================================================================
  556. %
  557. % A grammar is represented as a list of rules. A rule
  558. % sym : x y z { p q r }
  559. % | x y z { p q r }
  560. % ;
  561. % maps onto the list
  562. % (sym ((x y z) p q r)
  563. % ((x y z) p q r))
  564. % and items on the right hand side can be symbols or strings. Strings
  565. % stand for terminals. Symbols that are mentioned on a left hand side of
  566. % a production are non-terminals, others are considered to be terminals
  567. % supported by the lexer.
  568. %
  569. % ***** I am still working out what to do with the "semantic actions".
  570. global '(terminals non_terminals symbols goto_cache action_map);
  571. smacro procedure lalr_productions x;
  572. get(x, 'produces);
  573. smacro procedure lalr_set_productions(x, y);
  574. put(x, 'produces, y);
  575. symbolic procedure lalr_prin_symbol x;
  576. if x = 0 then princ "$"
  577. else if x = nil then princ "<empty>"
  578. else if x = '!. then princ "."
  579. else if numberp x and rassoc(x, terminals) then
  580. prin car rassoc(x, terminals)
  581. else if stringp x then prin x
  582. else for each c in explode2uc x do princ c;
  583. symbolic procedure lalr_display_symbols();
  584. begin
  585. princ "Terminal symbols are:"; terpri();
  586. for each x in terminals do <<
  587. princ " "; prin car x;
  588. princ ":"; prin cdr x >>;
  589. terpri();
  590. princ "Non-terminal symbols are:"; terpri();
  591. for each x in non_terminals do begin
  592. scalar w;
  593. princ "["; prin get(x, 'non_terminal_code); princ "]";
  594. lalr_prin_symbol x;
  595. w := ":";
  596. for each y in lalr_productions x do <<
  597. ttab 20; princ w; w := "|";
  598. for each z in car y do << princ " "; lalr_prin_symbol z >>;
  599. if posn() > 48 then terpri();
  600. ttab 48;
  601. princ "{";
  602. for each z in cdr y do << princ " "; prin z >>;
  603. princ " }";
  604. terpri() >>;
  605. ttab 20;
  606. princ ";";
  607. terpri() end;
  608. terpri();
  609. end;
  610. symbolic procedure lalr_print_action_map();
  611. begin
  612. princ "Action map:"; terpri();
  613. for each x in action_map do <<
  614. prin cdr x; princ ":"; ttab 12; prin car x; terpri() >>
  615. end;
  616. symbolic procedure lalr_set_grammar g;
  617. begin
  618. scalar name, vals, tnum, w;
  619. terminals := non_terminals := symbols := nil;
  620. tnum := 0;
  621. % I will start by augmenting the grammar with an initial production...
  622. g := list('s!', list list caar g) . g;
  623. for each x in g do <<
  624. name := car x; vals := cdr x;
  625. if name member non_terminals then
  626. vals := append(vals, lalr_productions name)
  627. else non_terminals := name . non_terminals;
  628. for each vv in cdr x do
  629. for each v in car vv do <<
  630. if stringp v or numberp v then <<
  631. if not assoc(v, terminals) then
  632. terminals := (v . (tnum := tnum+1)) . terminals >>
  633. else if not (v member symbols) then symbols := v . symbols >>;
  634. lalr_set_productions(name, vals) >>;
  635. for each name in non_terminals do symbols := delete(name, symbols);
  636. for each v in symbols do terminals := (v . (tnum := tnum+1)) . terminals;
  637. % I reverse the list of non-terminals here so that the starting symbol
  638. % remains as the first item.
  639. non_terminals := reversip non_terminals;
  640. tnum := -1;
  641. for each v in non_terminals do
  642. put(v, 'non_terminal_code, tnum := tnum+1);
  643. symbols := append(non_terminals, for each x in terminals collect cdr x);
  644. goto_cache := mkhash(length non_terminals, 1, 1.5);
  645. if !*verbose then lalr_display_symbols();
  646. % Map all terminals onto numeric codes.
  647. for each x in non_terminals do
  648. lalr_set_productions(x,
  649. for each y in lalr_productions x collect
  650. sublis(terminals, car y) . cdr y);
  651. % Map all actions onto numeric codes, such that identical actions all have the
  652. % same code
  653. action_map := nil;
  654. tnum := -1;
  655. for each x in non_terminals do
  656. for each a in lalr_productions x do <<
  657. w := assoc(cdr a, action_map);
  658. if null w then <<
  659. w := cdr a . (tnum := tnum + 1);
  660. action_map := w . action_map >>;
  661. rplacd(a, list cdr w) >>;
  662. action_map := reversip action_map;
  663. if !*verbose then lalr_print_action_map();
  664. lalr_calculate_first non_terminals;
  665. end;
  666. symbolic procedure lalr_clean_up();
  667. begin
  668. for each x in terminals do <<
  669. remprop(x, 'produces);
  670. remprop(x, 'lalr_first);
  671. remprop(x, 'non_terminal_code) >>;
  672. terminals := non_terminals := symbols := nil;
  673. goto_cache := action_map := nil
  674. end;
  675. symbolic procedure lalr_action(lhs, rhs);
  676. cdr assoc(rhs, lalr_productions lhs);
  677. symbolic procedure lalr_print_firsts g;
  678. begin
  679. princ "FIRST sets for each non-terminal:"; terpri();
  680. for each x in g do <<
  681. lalr_prin_symbol x;
  682. princ ": ";
  683. ttab 15;
  684. for each y in get(x, 'lalr_first) do <<
  685. princ " "; lalr_prin_symbol y >>;
  686. terpri() >>
  687. end;
  688. symbolic procedure lalr_calculate_first g;
  689. begin
  690. scalar w, y, z, done;
  691. for each x in g do
  692. if assoc(nil, lalr_productions x) then put(x, 'lalr_first, '(nil));
  693. repeat <<
  694. done := nil;
  695. for each x in g do <<
  696. z := get(x, 'lalr_first);
  697. for each y1 in lalr_productions x do <<
  698. y := car y1;
  699. while y and
  700. not numberp y
  701. and (nil member (w := get(car y, 'lalr_first))) do <<
  702. z := union(w, z);
  703. y := cdr y >>;
  704. if null y then nil
  705. else if numberp car y then z := union(list car y, z)
  706. else z := union(get(car y, 'lalr_first), z) >>;
  707. if not (z = get(x, 'lalr_first)) then done := t;
  708. put(x, 'lalr_first, z) >>
  709. >> until not done;
  710. if !*verbose then lalr_print_firsts g;
  711. return nil
  712. end;
  713. symbolic procedure lalr_first l;
  714. begin
  715. scalar r, w;
  716. while l and
  717. not numberp car l and
  718. (nil member (w := get(car l, 'lalr_first))) do <<
  719. r := union(delete(nil, w), r);
  720. l := cdr l >>;
  721. if null l then r := nil . r
  722. else if numberp car l then r := union(list car l, r)
  723. else r := union(w, r);
  724. return r
  725. end;
  726. % The next few procedures are as documented in Figure 4.38 of Red Dragon
  727. symbolic procedure lalr_print_items(heading, cc);
  728. begin
  729. princ heading;
  730. terpri();
  731. for each y in cc do <<
  732. princ "Item number "; prin cdr y; terpri();
  733. for each x in sort(car y, function orderp) do <<
  734. lalr_prin_symbol caar x; princ " ->";
  735. for each y in cdar x do << princ " "; lalr_prin_symbol y >>;
  736. princ " : ";
  737. lalr_prin_symbol cadr x;
  738. terpri() >>;
  739. for each x in hashcontents goto_cache do
  740. for each xx in cdr x do
  741. if car xx = cdr y then <<
  742. ttab 10; lalr_prin_symbol car x;
  743. princ " GOTO state "; prin cdr xx; terpri() >> >>
  744. end;
  745. symbolic procedure lalr_items g;
  746. begin
  747. scalar c, val, done, w, w1, w2, n;
  748. val := lalr_productions 's!';
  749. if cdr val then error(0, "Starting state must only reduce to one thing")
  750. else val := caar val;
  751. n := 0;
  752. c := list (lalr_closure list list(('s!' . '!. . val), 0) . n);
  753. repeat <<
  754. done := nil;
  755. for each i in c do
  756. for each x in symbols do
  757. if w := lalr_goto(car i, x) then <<
  758. w1 := assoc(w, c);
  759. if w1 then <<
  760. w2 := gethash(x, goto_cache);
  761. if not assoc(cdr i, w2) then
  762. puthash(x, goto_cache, (cdr i . cdr w1) . w2) >>
  763. else <<
  764. c := (w . (n := n + 1)) . c;
  765. puthash(x, goto_cache,
  766. (cdr i . n) . gethash(x, goto_cache));
  767. done := t >> >>
  768. >> until not done;
  769. c := reversip c; % So that item numbers come out in nicer order.
  770. if !*verbose then lalr_print_items("LR(1) Items:", c);
  771. return c
  772. end;
  773. symbolic procedure lalr_closure i;
  774. begin
  775. scalar pending, a, rule, tail, done, ff, w;
  776. pending := i;
  777. while pending do <<
  778. ff := car pending; % [(A -> alpha . B beta), a]
  779. pending := cdr pending;
  780. rule := car ff; a := cadr ff; tail := cdr ('!. member rule);
  781. if tail and not numberp car tail then <<
  782. ff := lalr_first append(cdr tail, list a);
  783. for each p in lalr_productions car tail do
  784. for each b in ff do <<
  785. w := list(car tail . '!. . car p, b);
  786. % It might be better to store items as hash tables, since then the
  787. % member-check here would be much faster.
  788. if not (w member i) then <<
  789. i := w . i;
  790. pending := w . pending >> >> >> >>;
  791. return i
  792. end;
  793. symbolic procedure lalr_move_dot(z, x);
  794. begin
  795. scalar r;
  796. while not (car z = '!.) do <<
  797. r := car z . r;
  798. z := cdr z >>;
  799. z := cdr z;
  800. if not (z and car z = x) then return nil;
  801. z := car z . '!. . cdr z;
  802. while r do <<
  803. z := car r . z;
  804. r := cdr r >>;
  805. return z
  806. end;
  807. symbolic procedure lalr_goto(i, x);
  808. begin
  809. scalar j, w;
  810. for each z in i do <<
  811. w := lalr_move_dot(car z, x);
  812. if w then j := list(w, cadr z) . j >>;
  813. return lalr_closure j
  814. end;
  815. symbolic procedure lalr_cached_goto(i, x);
  816. cdr assoc(i, gethash(x, goto_cache));
  817. % Next part of Algorithm 4.11 from the Red Dragon
  818. symbolic procedure lalr_remove_duplicates x;
  819. begin
  820. scalar r;
  821. if null x then return nil;
  822. x := sort(x, function orderp);
  823. r := list car x;
  824. x := cdr x;
  825. while x do <<
  826. if not (car x = car r) then r := car x . r;
  827. x := cdr x >>;
  828. return r
  829. end;
  830. symbolic procedure lalr_core i;
  831. lalr_remove_duplicates for each x in car i collect car x;
  832. symbolic procedure lalr_same_core(i1, i2);
  833. lalr_core i1 = lalr_core i2;
  834. % cc is a list of items, while i is a single item. If cc already contains
  835. % an item with the same core as I then merge i into that, and adjust any
  836. % goto records either out of or into i to refer now to the thing merged
  837. % with.
  838. fluid '(renamings);
  839. symbolic procedure lalr_insert_core(i, cc);
  840. if null cc then list i
  841. else if lalr_same_core(i, car cc) then <<
  842. renamings := (i . cdar cc) . renamings;
  843. (union(car i, caar cc) . cdar cc) . cdr cc >>
  844. else car cc . lalr_insert_core(i, cdr cc);
  845. symbolic procedure lalr_rename_gotos();
  846. begin
  847. scalar w;
  848. for each x in non_terminals do <<
  849. w := sublis(renamings, gethash(x, goto_cache));
  850. puthash(x, goto_cache, lalr_remove_duplicates w) >>
  851. end;
  852. % Part of Algorithm 4.10 of the Red Dragon
  853. symbolic procedure lalr_print_actions action_table;
  854. begin
  855. scalar w;
  856. princ "Actions:"; terpri();
  857. for each x in action_table do
  858. for each xx in cdr x do <<
  859. prin car x; ttab 20;
  860. lalr_prin_symbol car xx; ttab 40;
  861. w := cadr xx;
  862. if eqcar(w, 'reduce) then <<
  863. princ "reduce ";
  864. lalr_prin_symbol caadr w;
  865. princ " ->";
  866. for each v in cdadr w do << princ " "; lalr_prin_symbol v >>;
  867. princ " {";
  868. for each v in caddr w do << princ " "; prin v >>;
  869. princ " }";
  870. terpri() >>
  871. else << prin w; terpri() >> >>
  872. end;
  873. symbolic procedure lalr_make_actions c;
  874. begin
  875. scalar action_table, aa, j, w;
  876. for each i in c do <<
  877. aa := nil;
  878. for each r in car i do <<
  879. w := cdr ('!. member cdar r);
  880. if w and numberp car w then <<
  881. j := lalr_cached_goto(cdr i, car w);
  882. aa := list(car w, list('shift, j)) . aa >>
  883. else if null w and not (caar r = 's!') then <<
  884. w := reverse cdr reverse car r;
  885. aa :=
  886. list(cadr r, list('reduce, w, lalr_action(car w, cdr w))) .
  887. aa >>
  888. else if null w and caar r = 's!' then
  889. aa := list(0, 'accept) . aa >>;
  890. action_table := (cdr i . lalr_remove_duplicates aa) . action_table >>;
  891. action_index := mkvect16 caar action_table;
  892. action_table := reversip action_table;
  893. if !*verbose then lalr_print_actions action_table;
  894. j := 0; w := nil;
  895. for each x in action_table do <<
  896. putv16(action_index, car x, j);
  897. aa := lalr_lay_out_actions cdr x;
  898. while aa do <<
  899. w := (0 . 0) . w;
  900. j := j + 1 >> >>;
  901. action_terminal := mkvect16 j;
  902. action_result := mkvect16 j;
  903. while j > 0 do <<
  904. j := j - 1;
  905. putv16(action_terminal, j, caar w);
  906. putv16(action_result, j, cdar w);
  907. w := cdr w >>
  908. end;
  909. symbolic procedure lalr_most_common_dest p;
  910. begin
  911. scalar r, w;
  912. for each x in p do
  913. if (w := assoc(cdr x, r)) then rplacd(w, cdr w + 1)
  914. else r := (cdr x . 1) . r;
  915. w := car r;
  916. for each x in cdr r do if cdr x > cdr w then w := x;
  917. return car w
  918. end;
  919. symbolic procedure lalr_make_gotos();
  920. begin
  921. scalar p, r1, w, r;
  922. p := 0;
  923. for each x in hashcontents goto_cache do
  924. if not numberp car x then <<
  925. if !*verbose then
  926. for each xx in cdr x do <<
  927. prin car xx; ttab 10; lalr_prin_symbol car x;
  928. princ " GOTO state "; prin cdr xx; terpri() >>;
  929. r1 := (get(car x, 'non_terminal_code) . p) . r1;
  930. if cdr x then <<
  931. w := lalr_most_common_dest cdr x;
  932. for each xx in cdr x do if not (cdr xx = w) then <<
  933. r := xx . r;
  934. p := p + 1 >>;
  935. r := ((-1) . w) . r;
  936. p := p + 1 >> >>;
  937. goto_index := mkvect16 length non_terminals;
  938. goto_old_state := mkvect16 p;
  939. goto_new_state := mkvect16 p;
  940. for each x in r1 do putv16(goto_index, car x, cdr x);
  941. while p > 0 do <<
  942. p := p - 1;
  943. putv16(goto_old_state, p, caar r);
  944. putv16(goto_new_state, p, cdar r);
  945. r := cdr r >>;
  946. princ "goto_index: "; print goto_index;
  947. princ "goto_old_state: "; print goto_old_state;
  948. princ "goto_new_state: "; print goto_new_state
  949. end;
  950. % A main driver function that performs all the steps involved
  951. % in building parse tables for a given grammar.
  952. symbolic procedure lalr_construct_parser g;
  953. begin
  954. scalar c, cc, renamings;
  955. lalr_set_grammar g;
  956. c := lalr_items non_terminals;
  957. renamings := nil;
  958. for each i in c do cc := lalr_insert_core(i, cc);
  959. lalr_rename_gotos();
  960. if !*verbose then lalr_print_items("Merged Items:", cc);
  961. lalr_make_actions cc;
  962. lalr_make_gotos();
  963. lalr_clean_up()
  964. end;
  965. %=============================================================================
  966. % Now some test cases
  967. on time;
  968. % Here I set up a sample grammar
  969. % S' -> S
  970. % S -> CC { A1 }
  971. % C -> cC { A2 }
  972. % | d { A3 }
  973. % (example 4.42 from Aho, Sethi and Ullman's Red Dragon book, with
  974. % some dummy semantic actions added. Note that I do not need to insert
  975. % the production S' -> S for myself since the analysis code will
  976. % augment my grammar with it for me anyway.
  977. grammar := '((S ((C C) A1))
  978. (C (("c" C) A2)
  979. (("d") A3))
  980. );
  981. lalr_construct_parser grammar;
  982. % Example 4.46 from the Red Dragon
  983. g4_46 := '((S ((L "=" R) a1)
  984. ((R) a2))
  985. (L (("*" R) a3)
  986. ((id) a4))
  987. (R ((L) a5)));
  988. lalr_construct_parser g4_46;
  989. % Now a much more complicated grammar - one that recognizes the syntax of
  990. % RLISP.
  991. rlisp_grammar := '(
  992. (command (( cmnd sep ) action)
  993. (( end sep ) action)
  994. (( command cmnd sep ) action)
  995. (( command end sep ) action)
  996. )
  997. (sep (( ";" ) action)
  998. (( "$" ) action)
  999. )
  1000. (proc_type (( symbolic ) action)
  1001. (( algebraic ) action)
  1002. )
  1003. (proc_qual (( expr ) action)
  1004. (( macro ) action)
  1005. (( smacro ) action)
  1006. )
  1007. (sym_list (( ")" ) action)
  1008. (( "," symbol sym_list ) action)
  1009. )
  1010. (infix (( setq ) action)
  1011. (( or ) action)
  1012. (( and ) action)
  1013. (( member ) action)
  1014. (( memq ) action)
  1015. (( "=" ) action)
  1016. (( neq ) action)
  1017. (( eq ) action)
  1018. (( geq ) action)
  1019. (( ">" ) action)
  1020. (( leq ) action)
  1021. (( "<" ) action)
  1022. (( freeof ) action)
  1023. (( "+" ) action)
  1024. (( "-" ) action)
  1025. (( "*" ) action)
  1026. (( "/" ) action)
  1027. (( "^" ) action)
  1028. (( "." ) action)
  1029. )
  1030. (prefix (( not ) action)
  1031. (( "+" ) action)
  1032. (( "-" ) action)
  1033. )
  1034. (proc_head (( symbol ) action)
  1035. (( symbol symbol ) action)
  1036. (( symbol "(" ")" ) action)
  1037. (( symbol "(" symbol sym_list ) action)
  1038. (( prefix symbol ) action)
  1039. (( symbol infix symbol ) action)
  1040. )
  1041. (proc_def (( procedure proc_head sep cmnd ) action)
  1042. (( proc_type procedure proc_head sep cmnd ) action)
  1043. (( proc_qual procedure proc_head sep cmnd ) action)
  1044. (( proc_type proc_qual procedure proc_head sep cmnd ) action)
  1045. )
  1046. (rlistat (( rlistat ) action)
  1047. (( in ) action)
  1048. (( on ) action)
  1049. )
  1050. (rltail (( expr ) action)
  1051. (( expr "," rltail ) action)
  1052. )
  1053. (cmnd (( expr ) action)
  1054. (( rlistat rltail ) action)
  1055. )
  1056. (if_stmt (( if expr then cmnd else cmnd ) action)
  1057. (( if expr then cmnd ) action)
  1058. )
  1059. (for_update (( ":" expr ) action)
  1060. (( step expr until expr ) action)
  1061. )
  1062. (for_action (( do ) action)
  1063. (( sum ) action)
  1064. (( collect ) action)
  1065. )
  1066. (for_inon (( in ) action)
  1067. (( on ) action)
  1068. )
  1069. (for_stmt (( for symbol setq expr for_update for_action cmnd ) action)
  1070. (( for each symbol for_inon expr for_action cmnd ) action)
  1071. (( foreach symbol for_inon expr for_action cmnd ) action)
  1072. )
  1073. (while_stmt (( while expr do cmnd ) action)
  1074. )
  1075. (repeat_stmt (( repeat cmnd until expr ) action)
  1076. )
  1077. (return_stmt (( return ) action)
  1078. (( return expr ) action)
  1079. )
  1080. (goto_stmt (( goto symbol ) action)
  1081. (( go symbol ) action)
  1082. (( go to symbol ) action)
  1083. )
  1084. (group_tail (( rsect ) action)
  1085. (( sep rsect ) action)
  1086. (( sep cmnd group_tail ) action)
  1087. )
  1088. (group_expr (( lsect cmnd group_tail ) action)
  1089. )
  1090. (scalar_tail (( sep ) action)
  1091. (( "," symbol scalar_tail ) action)
  1092. (( "," integer scalar_tail ) action)
  1093. )
  1094. (scalar_def (( scalar symbol scalar_tail ) action)
  1095. (( integer symbol scalar_tail ) action)
  1096. )
  1097. (scalar_defs (( scalar_def ) action)
  1098. (( scalar_defs scalar_def ) action)
  1099. )
  1100. (block_tail (( end ) action)
  1101. (( cmnd end ) action)
  1102. (( symbol ":" block_tail ) action)
  1103. (( cmnd sep block_tail ) action)
  1104. (( sep block_tail ) action)
  1105. )
  1106. (block_expr (( begin scalar_defs block_tail ) action)
  1107. (( begin block_tail ) action)
  1108. )
  1109. (lambda_vars (( sep ) action)
  1110. (( "," symbol lambda_vars ) action)
  1111. )
  1112. (lambda_expr (( lambda symbol lambda_vars cmnd ) action)
  1113. (( lambda "(" ")" sep cmnd ) action)
  1114. (( lambda "(" symbol sym_list sep cmnd ) action)
  1115. )
  1116. (expr (( rx0 ) action)
  1117. (( lx0 ) action)
  1118. )
  1119. (rx0 (( lx0 where symbol "=" rx1 ) action)
  1120. (( rx1 ) action)
  1121. )
  1122. (lx0 (( lx0 where symbol "=" lx1 ) action)
  1123. (( lx1 ) action)
  1124. )
  1125. (rx1 (( lx2 setq rx1 ) action)
  1126. (( rx2 ) action)
  1127. )
  1128. (lx1 (( lx2 setq lx1 ) action)
  1129. (( lx2 ) action)
  1130. )
  1131. (rx2tail (( rx3 ) action)
  1132. (( lx3 or rx2tail ) action)
  1133. )
  1134. (rx2 (( lx3 or rx2tail ) action)
  1135. (( rx3 ) action)
  1136. )
  1137. (lx2tail (( lx3 ) action)
  1138. (( lx3 or lx2tail ) action)
  1139. )
  1140. (lx2 (( lx3 or lx2tail ) action)
  1141. (( lx3 ) action)
  1142. )
  1143. (rx3tail (( rx4 ) action)
  1144. (( lx4 and rx3tail ) action)
  1145. )
  1146. (rx3 (( lx4 and rx3tail ) action)
  1147. (( rx4 ) action)
  1148. )
  1149. (lx3tail (( lx4 ) action)
  1150. (( lx4 and lx3tail ) action)
  1151. )
  1152. (lx3 (( lx4 and lx3tail ) action)
  1153. (( lx4 ) action)
  1154. )
  1155. (rx4 (( not rx4 ) action)
  1156. (( rx5 ) action)
  1157. )
  1158. (lx4 (( not lx4 ) action)
  1159. (( lx5 ) action)
  1160. )
  1161. (rx5 (( lx6 member ry6 ) action)
  1162. (( lx6 memq ry6 ) action)
  1163. (( lx6 "=" ry6 ) action)
  1164. (( lx6 neq ry6 ) action)
  1165. (( lx6 eq ry6 ) action)
  1166. (( lx6 geq ry6 ) action)
  1167. (( lx6 ">" ry6 ) action)
  1168. (( lx6 leq ry6 ) action)
  1169. (( lx6 "<" ry6 ) action)
  1170. (( lx6 freeof ry6 ) action)
  1171. (( rx6 ) action)
  1172. )
  1173. (lx5 (( lx6 member ly6 ) action)
  1174. (( lx6 memq ly6 ) action)
  1175. (( lx6 "=" ly6 ) action)
  1176. (( lx6 neq ly6 ) action)
  1177. (( lx6 eq ly6 ) action)
  1178. (( lx6 geq ly6 ) action)
  1179. (( lx6 ">" ly6 ) action)
  1180. (( lx6 leq ly6 ) action)
  1181. (( lx6 "<" ly6 ) action)
  1182. (( lx6 freeof ly6 ) action)
  1183. (( lx6 ) action)
  1184. )
  1185. (ry6 (( not ry6 ) action)
  1186. (( rx6 ) action)
  1187. )
  1188. (ly6 (( not ly6 ) action)
  1189. (( lx6 ) action)
  1190. )
  1191. (rx6tail (( ry6a ) action)
  1192. (( ly6a "+" rx6tail ) action)
  1193. )
  1194. (rx6 (( lx6a "+" rx6tail ) action)
  1195. (( rx6a ) action)
  1196. )
  1197. (lx6tail (( ly6a ) action)
  1198. (( ly6a "+" lx6tail ) action)
  1199. )
  1200. (lx6 (( lx6a "+" lx6tail ) action)
  1201. (( lx6a ) action)
  1202. )
  1203. (ry6a (( not ry6a ) action)
  1204. (( rx6a ) action)
  1205. )
  1206. (rx6a (( lx6a "-" ry7 ) action)
  1207. (( rx7 ) action)
  1208. )
  1209. (ly6a (( not ly6a ) action)
  1210. (( lx6a ) action)
  1211. )
  1212. (lx6a (( lx6a "-" ly7 ) action)
  1213. (( lx7 ) action)
  1214. )
  1215. (ry7 (( not ry7 ) action)
  1216. (( rx7 ) action)
  1217. )
  1218. (rx7 (( "+" ry7 ) action)
  1219. (( "-" ry7 ) action)
  1220. (( rx8 ) action)
  1221. )
  1222. (ly7 (( not ly7 ) action)
  1223. (( lx7 ) action)
  1224. )
  1225. (lx7 (( "+" ly7 ) action)
  1226. (( "-" ly7 ) action)
  1227. (( lx8 ) action)
  1228. )
  1229. (rx8tail (( ry9 ) action)
  1230. (( ly9 "*" rx8tail ) action)
  1231. )
  1232. (rx8 (( lx9 "*" rx8tail ) action)
  1233. (( rx9 ) action)
  1234. )
  1235. (lx8tail (( ly9 ) action)
  1236. (( ly9 "*" lx8tail ) action)
  1237. )
  1238. (lx8 (( lx9 "*" lx8tail ) action)
  1239. (( lx9 ) action)
  1240. )
  1241. (ry9 (( not ry9 ) action)
  1242. (( "+" ry9 ) action)
  1243. (( "-" ry9 ) action)
  1244. (( rx9 ) action)
  1245. )
  1246. (rx9 (( lx9 "/" ry10 ) action)
  1247. (( rx10 ) action)
  1248. )
  1249. (ly9 (( not ly9 ) action)
  1250. (( "+" ly9 ) action)
  1251. (( "-" ly9 ) action)
  1252. (( lx9 ) action)
  1253. )
  1254. (lx9 (( lx9 "/" ly10 ) action)
  1255. (( lx10 ) action)
  1256. )
  1257. (ly10 (( not ly10 ) action)
  1258. (( "+" ly10 ) action)
  1259. (( "-" ly10 ) action)
  1260. (( lx10 ) action)
  1261. )
  1262. (lx10 (( lx11 "^" ly10 ) action)
  1263. (( lx11 ) action)
  1264. )
  1265. (ry10 (( not ry10 ) action)
  1266. (( "+" ry10 ) action)
  1267. (( "-" ry10 ) action)
  1268. (( rx10 ) action)
  1269. )
  1270. (rx10 (( lx11 "^" ry10 ) action)
  1271. (( rx11 ) action)
  1272. )
  1273. (ry11 (( not ry11 ) action)
  1274. (( "+" ry11 ) action)
  1275. (( "-" ry11 ) action)
  1276. (( rx11 ) action)
  1277. )
  1278. (rx11 (( x12 "." ry11 ) action)
  1279. (( if_stmt ) action)
  1280. (( for_stmt ) action)
  1281. (( while_stmt ) action)
  1282. (( repeat_stmt ) action)
  1283. (( return_stmt ) action)
  1284. (( goto_stmt ) action)
  1285. (( lambda_expr ) action)
  1286. (( proc_type ) action)
  1287. (( proc_def ) action)
  1288. (( endstat ) action)
  1289. )
  1290. (ly11 (( not ly11 ) action)
  1291. (( "+" ly11 ) action)
  1292. (( "-" ly11 ) action)
  1293. (( lx11 ) action)
  1294. )
  1295. (lx11 (( x12 "." ly11 ) action)
  1296. (( x12 ) action)
  1297. )
  1298. (arg_list (( expr ")" ) action)
  1299. (( expr "," arg_list ) action)
  1300. )
  1301. (x12 (( x13 "[" expr "]" ) action)
  1302. (( x13 "(" ")" ) action)
  1303. (( x13 "(" expr "," arg_list ) action)
  1304. (( x13 x12 ) action)
  1305. (( x13 ) action)
  1306. )
  1307. (x13 (( symbol ) action)
  1308. (( number ) action)
  1309. (( string ) action)
  1310. (( quoted ) action)
  1311. (( backquoted ) action)
  1312. (( group_expr ) action)
  1313. (( block_expr ) action)
  1314. (( "(" expr ")" ) action)
  1315. )
  1316. )$
  1317. % lalr_construct_parser rlisp_grammar;
  1318. end;