rlisp-parser.red 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. %
  2. % RLISP-PARSER.RED - RLISP parser based on Nordstrom and Pratt model
  3. %
  4. % Author: Martin Griss and Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: May 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % Known Bugs and Problems:
  12. % Procedure TEMPLATES parsed at wrong precendence, so
  13. % procedure x/y; is ok
  14. % procedure (x/Y) fails!
  15. %
  16. % IF a Then B; ELSE c; parses badly, doesnt catch ELSE
  17. % QUOTIENT(A,B) parses as RECIP(A)
  18. %
  19. % Edit by Cris Perdue, 28 Jan 1983 2038-PST
  20. % Occurrences of "dipthong" changed to "diphthong"
  21. % <PSL.UTIL.NEWVERSIONS>RLISP-PARSER.RED.4, 16-Dec-82 12:11:15, Edit by KESSLER
  22. % Make SEMIC!* a Global (as in rlisp-support), so it won't be made fluid in
  23. % compilation of Scan.
  24. % <PSL.UTIL>RLISP-PARSER.RED.3, 13-Dec-82 13:14:36, Edit by OTHMER
  25. % Flagged EMB as 'FTYPE so debug functions will work
  26. % <PSL.UTIL>RLISP-PARSER.RED.42, 17-Mar-82 02:36:14, Edit by BENSON
  27. % Finally infix as prefix works!!!
  28. % <PSL.UTIL>RLISP-PARSER.RED.25, 14-Jan-82 13:16:34, Edit by BENSON
  29. % Added JOIN to for each
  30. % <PSL.UTIL>RLISP-PARSER.RED.24, 30-Dec-81 01:01:30, Edit by BENSON
  31. % Unfixed infix as prefix. Have to check to make sure the thing is an arglist
  32. % <PSL.UTIL>RLISP-PARSER.RED.21, 28-Dec-81 15:22:37, Edit by BENSON
  33. % fixed LAMBDA();...
  34. % <PSL.UTIL>RLISP-PARSER.RED.21, 28-Dec-81 15:21:43, Edit by BENSON
  35. % Infix operators used as prefix are parsed correctly
  36. % <PSL.UTIL>RLISP-PARSER.RED.19, 28-Dec-81 14:44:47, Edit by BENSON
  37. % Removed assign-op in favor of SetF
  38. % <PSL.UTIL>RLISP-PARSER.RED.36, 5-Feb-82 07:17:34, Edit by GRISS
  39. % Add NE as infix
  40. CompileTime flag('(DefineBOpX DefineROpX DoInfixAsPrefix IsOpOp
  41. DoPrefix DoInfix MakeLocals MkQuotList
  42. PrecSet InfixOp PrefixOp RlispRead RemSemicol
  43. SymErr RAtomHook
  44. CommentPart), 'InternalFunction);
  45. FLUID '(CURSYM!* !*InsideStructureRead);
  46. CURSYM!*:='! ;
  47. global '(Semic!* TokType!*);
  48. lisp procedure SymErr(X, Y);
  49. StdError BldMsg("Syntax error %r", X);
  50. SYMBOLIC PROCEDURE SCAN;
  51. BEGIN SCALAR X;
  52. A: CURSYM!* := RATOMHOOK();
  53. IF TOKTYPE!* EQ 3 THEN %/ Also a R,
  54. (IF CURSYM!* EQ '!' THEN CURSYM!* := LIST('QUOTE, RLISPREAD())
  55. ELSE IF (X:=GET(CURSYM!*,'NeWNAM!-OP))THEN
  56. <<IF X EQ '!*SEMICOL!* THEN SEMIC!* := CURSYM!*;
  57. CURSYM!*:=X >> );
  58. IF (X:=(GET(CURSYM!*,'NEWNAM))) THEN CURSYM!*:=X;
  59. IF CURSYM!* EQ 'COMMENT THEN
  60. << WHILE NOT (READCH() MEMQ '(!; !$)) DO ; GOTO A >>;
  61. RETURN CURSYM!*;
  62. END;
  63. SYMBOLIC PROCEDURE RESETPARSER;
  64. CURSYM!*:= '! ;
  65. %-----------------------------------------------------------------
  66. %--- Boot strap functions, move to build file-----;
  67. FLUID '( %. Name of Grammer being defined
  68. DEFPREFIX
  69. DEFINFIX
  70. GRAMPREFIX
  71. GRAMINFIX
  72. ); %. Name of grammer running
  73. DEFPREFIX := 'RLISPPREFIX; %. Key for Grammer being defined
  74. DEFINFIX := 'RLISPINFIX; %. Key for Grammer being defined
  75. GRAMPREFIX := 'RLISPPREFIX; %. Key for Grammer being defined
  76. GRAMINFIX := 'RLISPINFIX; %. Key for Grammer being defined
  77. SYMBOLIC FEXPR PROCEDURE DEFINEBOP U;
  78. DEFINEBOPX U;
  79. SYMBOLIC PROCEDURE DEFINEBOPX U;
  80. % u=(opname, lprec, rprec,function)
  81. BEGIN SCALAR W,Y;
  82. W := EVAL CAR U; % Opname; Remove ' which used to suppress OP props
  83. Y :=
  84. EVAL CADR U % Lprec
  85. . EVAL CADDR U % Rprec
  86. . IF NULL CDDDR U THEN NIL % Default function is NIL
  87. ELSE IF ATOM CADDDR U THEN CADDDR U
  88. ELSE LIST('LAMBDA,'(X Y),CADDDR U);
  89. PUT(W,DEFINFIX,Y) % Binop in CAR
  90. END;
  91. SYMBOLIC PROCEDURE INFIXOP U; % Used also in REDUCE
  92. GET(U,GRAMINFIX);
  93. SYMBOLIC PROCEDURE INFIXPREC U; % Used in REDUCE MathPrint
  94. BEGIN SCALAR V;
  95. IF NULL(V:=INFIXOP U) THEN RETURN NIL;
  96. IF PAIRP V AND NUMBERP CAR V THEN RETURN CAR V;
  97. RETURN NIL;
  98. END;
  99. SYMBOLIC FEXPR PROCEDURE DEFINEROP U;
  100. DEFINEROPX U;
  101. SYMBOLIC PROCEDURE DEFINEROPX U;
  102. % u=(opname,lprec,function)
  103. BEGIN SCALAR W,Y;
  104. W := EVAL CAR U; % Name, remove ' mark
  105. Y :=
  106. EVAL CADR U % Lprec
  107. . IF NULL CDDR U THEN NIL % Default is NIL
  108. ELSE IF ATOM CADDR U THEN CADDR U % function name
  109. ELSE LIST('LAMBDA,'(X),CADDR U); %
  110. PUT(W,DEFPREFIX,Y)
  111. END;
  112. SYMBOLIC PROCEDURE PREFIXOP U;
  113. GET(U,GRAMPREFIX);
  114. FLUID '(OP); %. Current TOKEN being studied
  115. % ***** General Parser Functions *****;
  116. SYMBOLIC PROCEDURE PARSE0(RP,PRESCAN); %. Collect Phrase to LP<RP
  117. BEGIN SCALAR CURSYM,U;
  118. %/ IF COMPR!* AND CURSYM!* EQ CAAR COMPR!*
  119. %/ THEN <<CURSYM := CAR COMPR!*; COMPR!* := CDR COMPR!*>>;
  120. OP := IF PRESCAN THEN SCAN() ELSE CURSYM!*;
  121. %/ IF PRESCAN AND COMPR!* AND CURSYM!* EQ CAAR COMPR!*
  122. %/ THEN <<CURSYM := CAR COMPR!*; COMPR!* := CDR COMPR!*>>;
  123. U := RDRIGHT(RP,OP);
  124. %/ IF CURSYM THEN RPLACA(CURSYM,U);
  125. RETURN U
  126. END;
  127. SYMBOLIC PROCEDURE RDRIGHT(RP,Y); %. Collect phrase until OP with LP<RP
  128. % Y is starting TOKEN.
  129. % RP=NIL - Caller applies Function to Y, without collecting RHS subphrase
  130. BEGIN SCALAR TEMP,OP1,TEMPSCAN, TEMPOP, !*InsideStructureRead;
  131. !*InsideStructureRead := T;
  132. IF NULL RP THEN RETURN Y
  133. %/ ELSE IF IDFLAG THEN OP := SCAN() % Set IDFLAG if not Operator
  134. ELSE IF RP=0 AND Y EQ '!*SEMICOL!* THEN RETURN NIL %/ Toplevel ; or $?
  135. ELSE IF (TEMP:=PREFIXOP Y)
  136. THEN
  137. << TEMPSCAN := SCAN();
  138. IF STRONGERINFIXOP(TEMPSCAN, Y, CAR TEMP) THEN
  139. OP := TEMPSCAN
  140. ELSE
  141. Y := DOPREFIX(CDR TEMP,Y,RDRIGHT(CAR TEMP,TEMPSCAN)) >>
  142. ELSE IF NOT INFIXOP Y THEN OP := SCAN()
  143. %/ Binary OP in Prefix Position
  144. ELSE IF ISOPOP(OP,RP,Y) THEN <<OP := Y; Y := NIL>>
  145. ELSE OP := SCAN();% Y:=DoINFIXasPREFIX(Y,OP:=SCAN());
  146. RDLEFT:
  147. IF %/IDFLAG OR
  148. NOT (TEMP := INFIXOP OP)
  149. THEN IF NULL OP
  150. THEN <<Y := LIST(Y,NIL); OP := SCAN()>>
  151. ELSE Y := REPCOM(Y,RDRIGHT(99,OP)) %. Do as PREFIX
  152. ELSE IF RP>CAR TEMP THEN RETURN Y
  153. ELSE <<OP1:=OP; %/ !*ORD PROBLEM?
  154. TEMPSCAN := SCAN();
  155. IF TEMPSCAN = '!*LPAR!* AND NOT FUNBOUNDP OP1 THEN
  156. << OP := TEMPSCAN; %/ kludge to allow infix/prefix
  157. TEMPSCAN := RDRIGHT(CADR TEMP, OP);
  158. IF EQCAR(TEMPSCAN, '!*COMMA!*) THEN
  159. Y := LIST(Y, REPCOM(OP1, TEMPSCAN))
  160. ELSE Y := DOINFIX(CDDR TEMP,Y,OP1,TEMPSCAN) >>
  161. ELSE IF STRONGERINFIXOP(TEMPSCAN, OP1, CADR TEMP) THEN
  162. << Y := LIST(Y, OP1);
  163. OP := TEMPSCAN >>
  164. ELSE
  165. Y := DOINFIX(CDDR TEMP,Y,OP1,RDRIGHT(CADR TEMP,TEMPSCAN))>>;
  166. GO TO RDLEFT
  167. END;
  168. SYMBOLIC PROCEDURE STRONGERINFIXOP(NEXTOP, LASTOP, LASTPREC);
  169. BEGIN SCALAR TEMPOP, MATCHER;
  170. RETURN NOT PREFIXOP NEXTOP
  171. AND (TEMPOP := INFIXOP NEXTOP)
  172. AND NUMBERP LASTPREC AND NUMBERP CAR TEMPOP
  173. AND CAR TEMPOP <= 6
  174. AND CAR TEMPOP <= LASTPREC
  175. AND NOT ((MATCHER := GET(LASTOP, 'CLOSER))
  176. AND MATCHER EQ NEXTOP)
  177. AND NOT ISOPOP(NEXTOP, LASTPREC, LASTOP);
  178. END;
  179. DefList('((BEGIN END)
  180. (!*LPAR!* !*RPAR!*)
  181. (!*LSQB!* !*RSQB!*)
  182. (!*LVEC!* !*RVEC!*)), 'CLOSER);
  183. SYMBOLIC PROCEDURE DoINFIXasPREFIX(LHS,BOP);
  184. REPCOM(LHS,RDRIGHT(99,BOP));
  185. %. Note that PREFIX functions have next token SCANed, and get an argument,
  186. %. "X", that is either this TOKEN, or a complete parsed Phrase
  187. SYMBOLIC PROCEDURE DOPREFIX(ACT,ROP,RHS);
  188. IF NULL ACT THEN LIST(ROP,RHS)
  189. ELSE APPLY(ACT,LIST RHS);
  190. %. Note that INFIX functions have next token SCANed, and get two arguments,
  191. %. "X" and "Y"; "X" is LHS phrase,
  192. %. "Y" is either the scanned TOKEN, or a complete parsed Phrase
  193. SYMBOLIC PROCEDURE DOINFIX(ACT,LHS,BOP,RHS);
  194. IF NULL ACT THEN LIST(BOP,LHS,RHS)
  195. ELSE APPLY(ACT,LIST(LHS,RHS));
  196. SYMBOLIC PROCEDURE ISOPOP(XOP,RP,Y); %. Test for legal OP-> <-OP
  197. IF RP=2 THEN Y EQ '!*RPAR!* % LPAR scans for LP 2
  198. ELSE IF RP=0 AND XOP EQ 'END
  199. AND Y MEMBER '(!*SEMICOL!* !*COLON!* !*RSQB!* END) THEN T
  200. ELSE IF Y MEMQ '(!*SEMICOL!* END !*RSQB!*) % Special cases in BEGIN-END
  201. THEN RP= -2 OR XOP MEMQ '(!*SEMICOL!* !*COLON!* !*RSQB!*)
  202. ELSE NIL;
  203. SYMBOLIC PROCEDURE PARERR(X,Y);
  204. StdError X;
  205. SYMBOLIC PROCEDURE REMCOM X; %. (, x y z) -> (x y z)
  206. IF EQCAR(X,'!*COMMA!*) THEN CDR X ELSE LIST X;
  207. SYMBOLIC PROCEDURE REMSEMICOL X; %. (; x y z) -> (x y z)
  208. IF EQCAR(X,'!*SEMICOL!*) THEN CDR X ELSE LIST X;
  209. SYMBOLIC PROCEDURE REPCOM(TYPE,X); %. Create ARGLIST
  210. IF EQCAR(X,'!*COMMA!*) THEN (TYPE . CDR X)
  211. ELSE IF X EQ '!*EMPTY!* THEN LIST(TYPE)
  212. ELSE LIST(TYPE,X);
  213. %SYMBOLIC PROCEDURE SELF RHS; %. Prefix Operator returns RHS
  214. % RHS;
  215. SYMBOLIC PROCEDURE ParseNOOP X;
  216. <<OP:=SCAN();X>>;
  217. DEFINEROP('NOOP,NIL,ParseNOOP); %. Prevent TOKEN from being an OP
  218. SYMBOLIC PROCEDURE MKQUOTLIST U;
  219. %this could be replaced by MKQUOTE in most cases;
  220. 'LIST
  221. . FOR EACH X IN U COLLECT IF CONSTANTP X THEN X ELSE MKQUOTE X;
  222. SYMBOLIC PROCEDURE NARY(XOP,LHS,RHS); %. Remove repeated NARY ops
  223. IF EQCAR(LHS,XOP) THEN ACONC(LHS,RHS) ELSE LIST(XOP,LHS,RHS);
  224. % ***** Tables for Various Infix Operators *****;
  225. SYMBOLIC PROCEDURE ParseCOMMA(X,Y);
  226. NARY('!*COMMA!*,X,Y);
  227. DEFINEBOP('!*COMMA!*,5,6,ParseCOMMA );
  228. SYMBOLIC PROCEDURE ParseSEMICOL(X,Y);
  229. NARY('!*SEMICOL!*,X,Y);
  230. DEFINEBOP('!*SEMICOL!*, - 1,0,ParseSEMICOL );
  231. SYMBOLIC PROCEDURE ParseSETQ(LHS,RHS); %. Extended SETQ
  232. LIST(IF ATOM LHS THEN 'SETQ ELSE 'SETF, LHS, RHS);
  233. DEFINEBOP('SETQ,7,6,ParseSETQ);
  234. DEFINEBOP('CONS,23,21);
  235. SYMBOLIC PROCEDURE ParsePLUS2(X,Y);
  236. NARY('PLUS,X,Y);
  237. DEFINEBOP('PLUS,17,18,ParsePLUS2);
  238. %SYMBOLIC PROCEDURE ParsePLUS1(X);
  239. % IF EQCAR(X,'!*COMMA!*) THEN REPCOM('PLUS,X) ELSE X;
  240. %
  241. %DEFINEROP('PLUS,26,ParsePLUS1); %/ **** Prefix + sign...
  242. DEFINEROP('MINUS,26);
  243. SYMBOLIC PROCEDURE ParseDIFFERENCE(X);
  244. IF NUMBERP X THEN (0 - X )
  245. ELSE IF EQCAR(X,'!*COMMA!*)
  246. THEN REPCOM('DIFFERENCE,X)
  247. ELSE LIST('MINUS,X);
  248. DEFINEROP('DIFFERENCE,26,ParseDIFFERENCE );
  249. DEFINEBOP('DIFFERENCE,17,18);
  250. DEFINEBOP('TIMES,19,20);
  251. SYMBOLIC PROCEDURE ParseQUOTIENT(X);
  252. IF NOT EQCAR(X,'!*COMMA!*) THEN LIST('RECIP,X)
  253. ELSE REPCOM('QUOTIENT,X);
  254. DEFINEROP('QUOTIENT,26,ParseQUOTIENT);
  255. DEFINEBOP('QUOTIENT,19,20);
  256. DEFINEROP('RECIP,26);
  257. DEFINEBOP('EXPT,23,24);
  258. SYMBOLIC PROCEDURE ParseOR(X,Y);
  259. NARY('OR,X,Y);
  260. DEFINEBOP('OR,9,10,ParseOR);
  261. %/DEFINEROP('OR,26,REPCOM('OR,X));
  262. SYMBOLIC PROCEDURE ParseAND(X,Y);
  263. NARY('AND,X,Y);
  264. DEFINEBOP('AND,11,12,ParseAND);
  265. %/DEFINEROP('AND,26,REPCOM('AND,X));
  266. DEFINEROP('NOT,14);
  267. DEFINEBOP('MEMBER,15,16);
  268. %/DEFINEROP('MEMBER,26,REPCOM('MEMBER,X));
  269. DEFINEBOP('MEMQ,15,16);
  270. %/DEFINEROP('MEMQ,26,REPCOM('MEMQ,X));
  271. DEFINEBOP('EQ,15,16);
  272. %/DEFINEROP('EQ,26,REPCOM('EQ,X));
  273. DEFINEBOP('EQUAL,15,16);
  274. DEFINEBOP('GEQ,15,16);
  275. DEFINEBOP('GREATERP,15,16);
  276. DEFINEBOP('LEQ,15,16);
  277. DEFINEBOP('LESSP,15,16);
  278. DEFINEBOP('NEQ,15,16);
  279. DEFINEBOP('NE,15,16);
  280. % ***** Tables and Definitions for Particular Parsing Constructs *****;
  281. % ***** IF Expression *****;
  282. DEFINEROP('IF,4,ParseIF);
  283. DEFINEBOP('THEN,3,6);
  284. DEFINEBOP('ELSE,3,6);
  285. SYMBOLIC PROCEDURE ParseIF X;
  286. BEGIN SCALAR Y,Z;
  287. IF OP EQ 'THEN THEN Y := PARSE0(6,T) ELSE PARERR("IF missing THEN",T);
  288. IF OP EQ 'ELSE THEN Z := LIST PARSE0(6,T);
  289. RETURN 'COND
  290. . LIST(X,Y)
  291. . IF Z
  292. THEN IF EQCAR(CAR Z,'COND) THEN CDAR Z
  293. ELSE LIST (T . Z)
  294. ELSE NIL
  295. END;
  296. SYMBOLIC PROCEDURE ParseCASE(X); %. Parser function
  297. BEGIN
  298. IF NOT (OP EQ 'OF) THEN PARERR("CASE Missing OF",T);
  299. RETURN 'CASE . X . CASELIST()
  300. END;
  301. DEFINEBOP('OF,3,6);
  302. DEFINEBOP('TO,8,9);
  303. DEFINEROP('CASE,4,ParseCASE);
  304. SYMBOLIC PROCEDURE CASELIST;
  305. BEGIN SCALAR TG,BOD,TAGLIST,BODLIST;
  306. L1: OP := SCAN(); % Drop OF, : , etc
  307. IF OP EQ 'END THEN GOTO L2; % For optional ; before END
  308. TG := PARSETAGS(); % The TAG expressions
  309. BOD:= PARSE0(6,T); % The expression
  310. BODLIST:=LIST(TG,BOD) . BODLIST;
  311. IF OP EQ '!*SEMICOL!* THEN GOTO L1;
  312. IF OP NEQ 'END THEN PARERR("Expect END after CASE list",T);
  313. L2: OP:=SCAN(); % Skip 'END
  314. RETURN REVERSE BODLIST;
  315. END;
  316. SYMBOLIC PROCEDURE PARSETAGS();
  317. % Collects a single CASE-tag form; OP prescanned
  318. BEGIN SCALAR TG,TGLST;
  319. TG:=PARSE0(6,NIL); % , and : below 6
  320. IF EQCAR(TG,'TO) THEN TG:='RANGE . CDR TG; % TO is infix OP
  321. IF TG MEMQ '(OTHERWISE DEFAULT)
  322. THEN RETURN <<IF OP NEQ '!*COLON!*
  323. THEN PARERR("OTHERWISE in CASE must be SINGLE tag",T);
  324. NIL>>;
  325. IF OP EQ '!*COLON!* THEN RETURN LIST(TG);
  326. IF OP EQ '!*COMMA!*
  327. THEN RETURN
  328. <<OP:=SCAN();
  329. TGLST:=PARSETAGS();
  330. IF NULL TGLST
  331. THEN PARERR("OTHERWISE in CASE must be SINGLE tag",T);
  332. TG . TGLST>>;
  333. PARERR("Expect one or more tags before : in CASE",T);
  334. END;
  335. % ***** Block Expression *****;
  336. fluid '(BlockEnders!*);
  337. BlockEnders!* :='(END !*RPAR!* !*SEMICOL!* ELSE UNTIL !*RSQB!*);
  338. SYMBOLIC PROCEDURE ParseBEGIN(X);
  339. ParseBEGIN1(REMSEMICOL X,
  340. COMMENTPART(SCAN(),BlockEnders!*));
  341. DEFINEROP('BEGIN,-2,ParseBEGIN);
  342. DEFINEBOP('END,-3,-2);
  343. SYMBOLIC PROCEDURE ParseGO X;
  344. IF X EQ 'TO THEN LIST('GO,PARSE0(6,T)) % Why not Just SCAN?
  345. ELSE <<OP := SCAN(); LIST('GO,X)>>;
  346. DEFINEROP('GO,NIL,ParseGO );
  347. SYMBOLIC PROCEDURE ParseGOTO X;
  348. <<OP := SCAN(); LIST('GO,X)>>;
  349. DEFINEROP('GOTO,NIL,ParseGOTO );
  350. SYMBOLIC PROCEDURE ParseRETURN X;
  351. Begin Scalar XOP;
  352. RETURN LIST('RETURN,
  353. IF (XOP := INFIXOP X) AND NUMBERP CAR XOP AND CAR XOP <= 1
  354. THEN <<OP := X; NIL>> ELSE RDRIGHT(6,X));
  355. END;
  356. DEFINEROP('RETURN,NIL,ParseRETURN);
  357. SYMBOLIC PROCEDURE ParseEXIT X;
  358. Begin Scalar XOP;
  359. RETURN LIST('EXIT,
  360. IF (XOP := INFIXOP X) AND NUMBERP CAR XOP AND CAR XOP <= 1
  361. THEN <<OP := X; NIL>> ELSE RDRIGHT(6,X));
  362. END;
  363. DEFINEROP('EXIT,NIL,ParseEXIT);
  364. DEFINEBOP('!*COLON!*,1,0 );
  365. SYMBOLIC PROCEDURE COMMENTPART(A,L);
  366. IF A MEMQ L THEN <<OP := A; NIL>>
  367. ELSE A . COMMENTPART(SCAN(),L);
  368. SYMBOLIC PROCEDURE ParseBEGIN1(L,COMPART);
  369. BEGIN SCALAR DECLS,S;
  370. % Look for Sequence of Decls after Block Header
  371. A: IF NULL L THEN GO TO ND
  372. %/ SCAN();
  373. %/ IF CURSYM!* MEMQ '(INTEGER REAL SCALAR)
  374. %/ THEN <<Z1:=REPCOM(CURSYM!*,PARSE0(0,NIL))>>; % Arg Decl;
  375. ELSE IF NULL CAR L THEN <<L := CDR L; GO TO A>>
  376. ELSE IF EQCAR(CAR L,'DECLARE)
  377. THEN <<DECLS :=APPEND(CDAR L, DECLS); % Reverse order collection
  378. L := CDR L>>
  379. ELSE <<S:=L; GO TO B>>; % Hold Body for Rescan
  380. GO TO A;
  381. B: IF NULL L THEN GO TO ND
  382. ELSE IF EQCAR(CAR L,'DECLARE)
  383. THEN PARERR("DECLARATION invalid in BEGIN body",NIL)
  384. ELSE IF EQCAR(CAR L,'!*COLON!*)
  385. THEN <<RPLACD(CDDAR L,CDR L);
  386. RPLACD(L,CDDAR L);
  387. RPLACA(L,CADAR L)>>
  388. ELSE IF CDR L AND NULL CADR L
  389. THEN <<RPLACD(L,CDDR L); L := NIL . L>>;
  390. L := CDR L;
  391. GO TO B;
  392. ND: RETURN ('PROG . MAKELOCALS(DECLS) . S);
  393. END;
  394. SYMBOLIC PROCEDURE MAKELOCALS(U); %. Remove Types from Reversed DECLARE
  395. IF NULL U THEN NIL
  396. ELSE APPEND(CDAR U,MAKELOCALS CDR U);
  397. % ***** Procedure Expression *****;
  398. GLOBAL '(!*MODE);
  399. !*MODE := 'SYMBOLIC;
  400. SYMBOLIC PROCEDURE NMODESTAT VV; % Parses TOP-LEVEL mode ....;
  401. BEGIN SCALAR TMODE,X;
  402. X:= CURSYM!*;
  403. % SCAN();
  404. IF CURSYM!* EQ '!*SEMICOL!*
  405. THEN RETURN <<NEWMODE VV;
  406. OP:='!*SEMICOL!*;NIL>>;
  407. IF FLAGP(CURSYM!*,'DELIM)
  408. THEN RETURN <<NEWMODE VV;
  409. OP:='!*SEMICOL!*;NIL>>;
  410. TMODE := !*MODE;
  411. !*MODE := VV; % Local MODE change for MKPROC
  412. X := ERRORSET('(PARSE0 0 NIL),T,!*BACKTRACE);
  413. !*MODE := TMODE;
  414. RETURN IF ATOM X OR CDR X THEN NIL ELSE CAR X
  415. END;
  416. SYMBOLIC PROCEDURE NEWMODE VV;
  417. <<PRINT LIST('NEWMODE,LIST('QUOTE,VV));
  418. IF NULL VV THEN VV:='SYMBOLIC;
  419. !*MODE := VV>>;
  420. CommentOutCode <<
  421. fluid '(FTypes!*);
  422. FTYPES!* := '(EXPR FEXPR MACRO);
  423. SYMBOLIC PROCEDURE OLDPROCSTAT;
  424. BEGIN SCALAR BOOL,U,TYPE,X,Y,Z;
  425. IF FNAME!* THEN GO TO B
  426. ELSE IF CURSYM!* EQ 'PROCEDURE THEN TYPE := 'EXPR
  427. ELSE PROGN(TYPE := CURSYM!*,SCAN());
  428. IF NOT CURSYM!* EQ 'PROCEDURE THEN GO TO C;
  429. X := ERRORSET('(PARSE0 0 T),T,!*BACKTRACE);
  430. IF ATOM X OR CDR X THEN GO TO A
  431. ELSE IF ATOM (X := CAR X) THEN X := LIST X; %no arguments;
  432. FNAME!* := CAR X; %function name;
  433. IF IDP FNAME!* %AND NOT(TYPE MEMQ FTYPES!*);
  434. THEN IF NULL FNAME!* OR (Z := GETTYPE FNAME!*)
  435. AND NOT Z MEMQ '(PROCEDURE OPERATOR)
  436. THEN GO TO D
  437. ELSE IF NOT GETD FNAME!* THEN FLAG(LIST FNAME!*,'FNC);
  438. %to prevent invalid use of function name in body;
  439. U := CDR X;
  440. Y := ERRORSET(LIST('FLAGTYPE,MKQUOTE U,MKQUOTE 'SCALAR),
  441. T,!*BACKTRACE);
  442. IF ATOM Y OR CDR Y THEN Y := NIL ELSE Y := CAR Y;
  443. X := CAR X . Y;
  444. A: Z := ERRORSET('(PARSE0 0 T),T,!*BACKTRACE);
  445. IF NOT ATOM Z AND NULL CDR Z THEN Z := CAR Z;
  446. IF NULL ERFG!* THEN Z:=PROCSTAT1(X,Z,TYPE);
  447. REMTYPE Y;
  448. REMFLAG(LIST FNAME!*,'FNC);
  449. FNAME!*:=NIL;
  450. IF NOT BOOL AND ERFG!* THEN REDERR "ERROR TERMINATION";
  451. RETURN Z;
  452. B: BOOL := T;
  453. C: ERRORSET('(SYMERR (QUOTE PROCEDURE) T),T,!*BACKTRACE);
  454. GO TO A;
  455. D: LPRIE LIST(Z,FNAME!*,"INVALID AS PROCEDURE");
  456. GO TO A
  457. END;
  458. >>;
  459. % Some OLD Crap looks at 'STAT values!!!
  460. DEFLIST ('((PROCEDURE PROCSTAT)
  461. (EXPR PROCSTAT)
  462. (FEXPR PROCSTAT)
  463. (EMB PROCSTAT)
  464. (MACRO PROCSTAT) (NMACRO PROCSTAT) (SMACRO PROCSTAT)),
  465. 'STAT);
  466. DEFLIST ('((ALGEBRAIC MODESTAT)
  467. (SYMBOLIC MODESTAT)
  468. (SYSLSP MODESTAT)
  469. ),
  470. 'STAT); %/ STAT used for OLD style BEGIN KEY search
  471. DEFLIST('((LISP SYMBOLIC)),'NEWNAM);
  472. DEFINEROP('SYMBOLIC,NIL,NMODESTAT('SYMBOLIC)); % Make it a Prefix OP
  473. DEFINEROP('ALGEBRAIC,NIL,NMODESTAT('ALGEBRAIC)); % Make it a Prefix OP
  474. DEFINEROP('SYSLSP,NIL,NMODESTAT('SYMBOLIC)); % Make it a Prefix OP
  475. DEFINEBOP('PROCEDURE,1,NIL,ParsePROCEDURE); % Pick up MODE -- will go
  476. DEFINEROP('PROCEDURE,NIL,ParsePROCEDURE('EXPR,X)); %/ Unary, use DEFAULT mode?
  477. SYMBOLIC PROCEDURE ParsePROCEDURE2(NAME,VARLIS,BODY,TYPE);
  478. BEGIN SCALAR Y;
  479. % IF FLAGP(NAME,'LOSE) AND (!*LOSE OR NULL !*DEFN)
  480. % THEN RETURN PROGN(LPRIM LIST(NAME,
  481. % "Not defined (LOSE Flag)"),
  482. % NIL);
  483. if (Y := get(Type, 'FunctionDefiningFunction)) then
  484. Body := list(Y, Name, VarLis, Body)
  485. else if (Y := get(Type, 'ImmediateDefiningFunction)) then return
  486. Apply(Y, list(Name, VarLis, Body))
  487. ELSE BODY := LIST('PUTC,
  488. MKQUOTE NAME,
  489. MKQUOTE TYPE,
  490. MKQUOTE LIST('LAMBDA,VARLIS, REFORM BODY));
  491. RETURN IF !*MODE NEQ 'ALGEBRAIC THEN BODY
  492. %/ ELSE LIST('PROGN,
  493. %/ LIST('FLAG,MKQUOTE LIST NAME,MKQUOTE 'OPFN),
  494. %/ BODY)
  495. END;
  496. DefList('((Expr DE)
  497. (FExpr DF)
  498. (Macro DM)
  499. (NExpr DN)
  500. (SMacro DS)), 'FunctionDefiningFunction);
  501. put('Emb, 'ImmediateDefiningFunction, 'EmbFn);
  502. SYMBOLIC PROCEDURE ParsePROCEDURE1(NAM,ARGS,BODY,ARGTYPE,TYPES);
  503. %/ Crude conversion of PROC to PUTD. Need make Etypes and Ftypes
  504. %/ Keywords also.
  505. BEGIN SCALAR ETYPE,FTYPE;
  506. ETYPE:=!*MODE; FTYPE:='EXPR;
  507. IF NOT PAIRP TYPES THEN TYPES:=TYPES . NIL;
  508. FOR EACH Z IN TYPES DO
  509. IF FLAGP(Z,'ETYPE) THEN ETYPE:=Z
  510. ELSE IF FLAGP(Z,'FTYPE) THEN FTYPE:=Z;
  511. RETURN ParsePROCEDURE2(NAM,ARGS,BODY,FTYPE);
  512. END;
  513. FLAG('(EXPR FEXPR NEXPR NFEXPR MACRO SMACRO NMACRO EMB),'FTYPE);
  514. FLAG('(SYMBOLIC ALGEBRAIC LISP SYSLISP SYSLSP),'ETYPE);
  515. SYMBOLIC PROCEDURE ParsePROCEDURE(EFTYPES,Y);
  516. BEGIN SCALAR OP1,Z,Z1;
  517. OP := OP1 := SCAN();
  518. IF OP1 EQ '!*SEMICOL!* THEN Y := LIST Y
  519. ELSE IF INFIXOP OP1 THEN Y := LIST(OP1,Y,PARSE0(8,T))
  520. % Binary as Prefix
  521. ELSE Y := REPCOM(Y,PARSE0(8,NIL)); %/ Why 8
  522. IF OP NEQ '!*SEMICOL!*
  523. THEN PARERR("PROCEDURE missing terminator after template",T);
  524. %/ SCAN();
  525. %/ IF CURSYM!* MEMQ '(INTEGER REAL SCALAR)
  526. %/ THEN <<Z1:=REPCOM(CURSYM!*,PARSE0(0,NIL))>>; % Arg Decl;
  527. Z := PARSE0(0,T);
  528. IF EQCAR(Z,'DECLARE) THEN <<Z1 := Z; Z := PARSE0(0,T)>>; % repeated DECL?
  529. RETURN ParsePROCEDURE1(CAR Y,CDR Y,Z,Z1,EFTYPES);
  530. % Nam, args, body, arg decl, E/Fmode
  531. END;
  532. % ***** Left and Right Parentheses Handling *****;
  533. DEFINEROP('!*LPAR!*,NIL,ParseLPAR);
  534. DEFINEBOP('!*RPAR!*,1,0);
  535. SYMBOLIC PROCEDURE ParseLPAR X;
  536. BEGIN SCALAR RES;
  537. IF X EQ '!*RPAR!* THEN <<OP := X; RES := '!*EMPTY!*>>
  538. ELSE RES:= RDRIGHT(2,X);
  539. IF OP EQ '!*RPAR!* THEN OP := SCAN()
  540. ELSE PARERR("Missing ) after argument list",NIL);
  541. RETURN RES
  542. END;
  543. % ***** Left and Right << and >> Handling *****;
  544. DEFINEROP('!*LSQB!*,-2,ParseRSQB);
  545. SYMBOLIC PROCEDURE ParseRSQB(X);
  546. IF OP EQ '!*RSQB!*
  547. THEN <<OP := SCAN(); 'PROGN . REMSEMICOL X>>
  548. ELSE PARERR("Missing right >> after Group",NIL);
  549. DEFINEBOP('!*RSQB!*,-3,0);
  550. %COMMENT ***** [] vector syntax;
  551. REMPROP('![,'NEWNAM);
  552. REMPROP('!],'NEWNAM);
  553. % ***** [] vector syntax;
  554. DEFINEBOP('!*LVEC!*,121,6,ParseLVEC);
  555. SYMBOLIC PROCEDURE ParseLVEC(X,Y);
  556. IF OP EQ '!*RVEC!* THEN <<OP :=SCAN(); LIST('INDX,X,Y)>>
  557. ELSE PARERR("Missing ] in index expression ",NIL);
  558. % INDX is used for both Vectors and Strings in PSL. You will need to
  559. % have INDX map to GETV in vanilla Standard Lisp
  560. DEFINEBOP('!*RVEC!*,5,7);
  561. % ***** Lambda Expression *****;
  562. DEFINEROP('LAMBDA,0,ParseLAMBDA);
  563. SYMBOLIC PROCEDURE ParseLAMBDA X;
  564. LIST('LAMBDA,IF X AND X NEQ '!*EMPTY!* THEN REMCOM X ELSE NIL,
  565. PARSE0(6,T));
  566. % ***** Repeat Expression *****;
  567. DEFINEROP('REPEAT,4,ParseREPEAT);
  568. SYMBOLIC PROCEDURE ParseREPEAT X;
  569. LIST('REPEAT,X,
  570. IF OP EQ 'UNTIL THEN PARSE0(6,T)
  571. ELSE PARERR("REPEAT missing UNTIL clause",T)) ;
  572. DEFINEBOP('UNTIL,3,6);
  573. % ***** While Expression *****;
  574. DEFINEROP('WHILE,4, ParseWHILE);
  575. SYMBOLIC PROCEDURE ParseWHILE X;
  576. LIST('WHILE,X,
  577. IF OP EQ 'DO THEN PARSE0(6,T)
  578. ELSE PARERR("WHILE missing DO clause",T)) ;
  579. DEFINEBOP('DO,3,6);
  580. % ***** Declare Expression *****;
  581. DEFINEROP('DECLARE,2,ParseDECL);
  582. DEFINEROP('DCL,2,ParseDECL);
  583. SYMBOLIC PROCEDURE ParseDECL X;
  584. BEGIN SCALAR Y,Z;
  585. A:
  586. IF OP NEQ '!*COLON!* THEN PARERR("DECLARE needs : before mode",T);
  587. IF (Z := SCAN()) MEMQ '(INTEGER REAL SCALAR) THEN OP := SCAN()
  588. ELSE Z := PARSE0(6,NIL);
  589. Y := ACONC(Y,Z . REMCOM X);
  590. IF OP EQ '!*SEMICOL!* THEN RETURN 'DECLARE . Y
  591. ELSE IF OP NEQ '!*COMMA!*
  592. THEN PARERR("DECLAREd variables separated by ,",T);
  593. X := PARSE0(2,T);
  594. GO TO A
  595. END;
  596. SYMBOLIC FEXPR PROCEDURE DECLARE U;
  597. %to take care of top level declarations;
  598. <<LPRIM "Declarations are not permitted at the top level";
  599. NMODESTAT U>>;
  600. % ***** For Expression *****;
  601. DEFINEROP('FOR,NIL,ParseFOR);
  602. DEFINEBOP('STEP,3,6);
  603. DEFINEBOP('SUM,3,6);
  604. DEFINEBOP('PRODUCT,3,6);
  605. SYMBOLIC PROCEDURE ParseFOR X;
  606. BEGIN SCALAR INIT,STP,UNTL,ACTION,ACTEXPR;
  607. IF X EQ 'EACH THEN RETURN ParseFOREACH SCAN()
  608. ELSE IF X EQ 'ALL THEN RETURN ParseFORALL PARSE0(4,T)
  609. ELSE IF (OP := SCAN()) EQ 'SETQ THEN INIT := PARSE0(6,T)
  610. ELSE PARERR("FOR missing loop VAR assignment",T);
  611. IF OP EQ '!*COLON!* THEN <<STP := 1; OP := 'UNTIL>>
  612. ELSE IF OP EQ 'STEP THEN STP := PARSE0(6,T)
  613. ELSE PARERR("FOR missing : or STEP clause",T);
  614. IF OP EQ 'UNTIL THEN UNTL := PARSE0(6,T)
  615. ELSE PARERR("FOR missing UNTIL clause",T);
  616. ACTION := OP;
  617. IF ACTION MEMQ '(DO SUM PRODUCT) THEN ACTEXPR := PARSE0(6,T)
  618. ELSE PARERR("FOR missing action keyword",T);
  619. RETURN LIST('FOR,
  620. LIST('FROM,X,INIT,UNTL,STP),
  621. LIST(ACTION,ACTEXPR))
  622. END;
  623. % ***** Foreach Expression *****;
  624. DEFINEROP('FOREACH,NIL,ParseFOREACH);
  625. DEFINEBOP('COLLECT,3,6);
  626. DEFINEBOP('CONC,3,6);
  627. DEFINEBOP('JOIN,3,6);
  628. SYMBOLIC PROCEDURE ParseFOREACH X;
  629. BEGIN SCALAR L,INON,ACTION;
  630. IF NOT ((INON := SCAN()) EQ 'IN OR INON EQ 'ON)
  631. THEN PARERR("FOR EACH missing iterator clause",T);
  632. L := PARSE0(6,T);
  633. IF NOT ((ACTION := OP) MEMBER '(DO COLLECT CONC JOIN))
  634. THEN PARERR("FOR EACH missing action clause",T);
  635. RETURN LIST('FOREACH,X,INON,L,ACTION,PARSE0(6,T))
  636. END;
  637. % ***** Let Expression *****;
  638. DEFINEBOP('LET,1,0,ParseLET);
  639. DEFINEROP('LET,0,ParseLET(NIL . NIL,X) );
  640. DEFINEBOP('CLEAR,0,1,ParseCLEAR);
  641. DEFINEROP('CLEAR,0,ParseCLEAR(NIL . NIL,X));
  642. DEFINEBOP('SUCH,3,6);
  643. SYMBOLIC PROCEDURE ParseLET(X,Y); ParseLET1(X,Y,NIL);
  644. SYMBOLIC PROCEDURE ParseCLEAR(X,Y); ParseLET1(X,Y,T);
  645. SYMBOLIC PROCEDURE ParseLET1(X,Y,Z);
  646. LIST('LET!*,CAR X,REMCOM Y,CDR X,NIL,Z);
  647. SYMBOLIC PROCEDURE ParseFORALL X;
  648. BEGIN SCALAR BOOL;
  649. IF OP EQ 'SUCH
  650. THEN IF SCAN() EQ 'THAT THEN BOOL := PARSE0(6,T)
  651. ELSE PARERR("FOR ALL missing SUCH THAT clause",T);
  652. IF NOT OP MEMQ '(LET CLEAR) THEN PARERR("FOR ALL missing ACTION",T);
  653. RETURN REMCOM X . BOOL
  654. END;
  655. % ******** Standard Qoted LIST collectors
  656. SYMBOLIC PROCEDURE RLISF(U,V,W); %. Used to Collect a list of IDs to
  657. %. FLAG with Something
  658. BEGIN
  659. V := RDRIGHT(0,V);
  660. V :=
  661. IF EQCAR(V,'!*COMMA!*) THEN CDR V
  662. ELSE IF V THEN LIST V
  663. ELSE V;
  664. RETURN FLAG(V,U)
  665. END;
  666. SYMBOLIC PROCEDURE FLAGOP U; %. Declare U as Flagger
  667. RLISTAT(U,'FLAGOP);
  668. SYMBOLIC PROCEDURE RLISTAT(OPLIST,B); %. Declare els of OPLIST to be RLIS
  669. FOR EACH U IN OPLIST DO
  670. DEFINEROPX LIST(MKQUOTE U,NIL,
  671. LIST(IF B EQ 'FLAGOP THEN 'RLISF ELSE 'RLIS1,
  672. MKQUOTE U,'X,MKQUOTE B));
  673. SYMBOLIC PROCEDURE RLIS1(U,V,W); %. parse LIST of args, maybe quoted
  674. % U=funcname, V=following Phrase, W=arg treatment
  675. BEGIN
  676. IF V EQ '!*SEMICOL!* THEN RETURN
  677. <<OP := V;
  678. IF W = 'NOQUOTE THEN LIST U ELSE LIST(U, NIL) >>
  679. ELSE V := RDRIGHT(0,V);
  680. V :=
  681. IF EQCAR(V,'!*COMMA!*) THEN CDR V
  682. ELSE IF V THEN LIST V
  683. ELSE V;
  684. IF W EQ 'IO
  685. THEN V := MAPCAR(V,FUNCTION (LAMBDA J; NEWMKFIL J));
  686. RETURN IF W EQ 'NOQUOTE THEN U . V ELSE LIST(U,MKQUOTLIST V)
  687. END;
  688. % ***** Parsing Rules For Various IO Expressions *****;
  689. RLISTAT('(IN OUT SHUT),'NOQUOTE);
  690. RLISTAT('(TR UNTR BR UNBR),'NOQUOTE); % for mini-trace in PSL
  691. RLISTAT('(LOAD HELP), 'NOQUOTE);
  692. FLAG('(IN OUT SHUT ON OFF
  693. TR UNTR UNTRST TRST),'NOCHANGE); % No REVAL of args
  694. DEFINEROP('FSLEND,NIL,ESTAT('FasLEND));
  695. DEFINEROP('FaslEND,NIL,ESTAT('FaslEND));
  696. RLISTAT('(WRITE),'NOQUOTE);
  697. RLISTAT('(ARRAY),1);
  698. % 2.11.3 ON/OFF STATEMENTS
  699. RLISTAT('(ON OFF), 'NOQUOTE);
  700. % ***** Parsing Rules for INTEGER/SCALAR/REAL *****;
  701. % These will eventually be removed in favor of DECLARE;
  702. DEFINEROP('INTEGER,0,ParseINTEGER);
  703. SYMBOLIC PROCEDURE ParseINTEGER X;
  704. LIST('DECLARE,REPCOM('INTEGER,X));
  705. DEFINEROP('REAL,0,ParseREAL);
  706. SYMBOLIC PROCEDURE ParseREAL X;
  707. LIST('DECLARE,REPCOM('REAL,X));
  708. DEFINEROP('SCALAR,0,ParseSCALAR);
  709. SYMBOLIC PROCEDURE ParseSCALAR X;
  710. LIST('DECLARE,REPCOM('SCALAR,X));
  711. %/ Cuase problems in INTEGER procedure foo;...
  712. SYMBOLIC PROCEDURE COMM1 U; %. general Comment Parser
  713. BEGIN
  714. IF U EQ 'END THEN SCAN();
  715. A:
  716. IF CURSYM!* EQ '!*SEMICOL!*
  717. OR U EQ 'END
  718. AND CURSYM!*
  719. MEMQ '(END ELSE UNTIL !*RPAR!* !*RSQB!*)
  720. THEN RETURN NIL;
  721. SCAN();
  722. GOTO A;
  723. END;
  724. SYMBOLIC PROCEDURE ESTAT(FN); %. returns (FN), dropping till semicol ;
  725. BEGIN
  726. WHILE CURSYM!* NEQ '!*SEMICOL!* DO SCAN();
  727. OP := '!*SEMICOL!*;
  728. RETURN LIST(FN);
  729. END;
  730. SYMBOLIC PROCEDURE ENDSTAT;
  731. %This procedure can also be used for any key-words which take no
  732. %arguments;
  733. BEGIN SCALAR X;
  734. X := OP;
  735. COMM1 'END;
  736. OP := '!*SEMICOL!*;
  737. RETURN LIST X
  738. END;
  739. % Some useful ESTATs:
  740. DEFINEROP('QUIT,NIL,ESTAT('QUIT));
  741. DEFINEROP('PAUSE,NIL,ESTAT('PAUSE));
  742. DEFINEROP('CONT,NIL,ESTAT('CONT));
  743. DEFINEROP('RECLAIM,NIL,ESTAT('RECLAIM));
  744. DEFINEROP('RETRY,NIL,ESTAT('RETRY));
  745. DEFINEROP('SHOWTIME,NIL,ESTAT('SHOWTIME));
  746. FLAG('(FSLEND CONT RECLAIM RETRY SHOWTIME QUIT PAUSE),'OPFN);
  747. % Symbolic OPS, or could use NOCHANGE
  748. RLISTAT('(FLAGOP),1);
  749. CommentOutCode <<
  750. SYMBOLIC PROCEDURE INFIX X; % Makes Left ASSOC, not like CONS
  751. FOR EACH Y IN X DO
  752. DEFINEBOPX LIST(MKQUOTE Y,8,9,NIL);
  753. >>;
  754. FLAG('(NEWTOK),'EVAL);
  755. SYMBOLIC PROCEDURE PRECEDENCE U;
  756. PRECSET(CAR U,CADR U);
  757. SYMBOLIC PROCEDURE PRECSET(U,V);
  758. BEGIN SCALAR Z;
  759. IF NULL (Z := INFIXOP V) OR NULL (Z := CDR Z)
  760. THEN REDERR LIST(V,"NOT INFIX")
  761. ELSE DEFINEBOPX LIST(MKQUOTE U,CAR Z,CADR Z,NIL)
  762. END;
  763. RLISTAT('(INFIX PRECEDENCE),3);
  764. REMPROP('SHOWTIME,'STAT);
  765. %*********************************************************************
  766. % DEFINE STATEMENT
  767. %********************************************************************;
  768. SYMBOLIC PROCEDURE ParseDEFINE(X); % X is following Token
  769. BEGIN SCALAR Y,Z;
  770. B: IF X EQ '!*SEMICOL!* THEN RETURN <<OP:='!*SEMICOL!*;
  771. MKPROG(NIL,Z)>>
  772. ELSE IF X EQ '!*COMMA!* THEN <<X:=SCAN(); %/ Should use SCAN0
  773. GO TO B>>
  774. ELSE IF NOT IDP X THEN GO TO ER;
  775. Y := SCAN();
  776. IF NOT (Y EQ 'EQUAL) THEN GO TO ER;
  777. Z := ACONC(Z,LIST('PUT,MKQUOTE X,MKQUOTE 'NEWNAM,
  778. MKQUOTE PARSE0(6,T))); % So doesnt include ,
  779. X := CURSYM!*;
  780. GO TO B;
  781. ER: SYMERR('DEFINE,T)
  782. END;
  783. DEFINEROP('DEFINE,NIL,ParseDEFINE);
  784. FLAG('(DEFINE),'EVAL);
  785. %*********************************************************************
  786. % 3.2.4 WRITE STATEMENT
  787. %********************************************************************;
  788. SYMBOLIC PROCEDURE ParseWRITE(X);
  789. BEGIN SCALAR Y,Z;
  790. X := REMCOM XREAD1 'LAMBDA;
  791. A: IF NULL X
  792. THEN RETURN MKPROG(NIL,'(TERPRI) . Y);
  793. Z := LIST('PRIN2,CAR X);
  794. IF NULL CDR X THEN Z := LIST('RETURN,Z);
  795. B: Y := ACONC(Y,Z);
  796. X := CDR X;
  797. GO TO A;
  798. END;
  799. DEFINEROP('WRITE,NIL,ParseWRITE);
  800. %*********************************************************************
  801. % VARIOUS DECLARATIONS
  802. %********************************************************************;
  803. SYMBOLIC PROCEDURE ParseOPERATOR(X);
  804. BEGIN SCALAR Y;
  805. Y := REMCOM PARSE0(0,NIL);
  806. RETURN
  807. IF !*MODE EQ 'SYMBOLIC
  808. THEN MKPROG(NIL,LIST LIST('FLAG,MKQUOTE Y,MKQUOTE 'OPFN))
  809. ELSE IF X NEQ 'OPERATOR
  810. THEN IF EQCAR(CAR Y,'PROG) THEN CAR Y
  811. ELSE X . MAPCAR(LIST Y,FUNCTION MKARG)
  812. ELSE IF KEY!* NEQ 'OPERATOR AND GET(KEY!*,'FN)
  813. THEN (LAMBDA K; MKPROG(NIL,MAPCAR(Y,FUNCTION (LAMBDA J;
  814. LIST('FLAG,LIST('LIST,MKQUOTE J),
  815. K,K)))))
  816. MKQUOTE GET(KEY!*,'FN)
  817. ELSE MKPROG(NIL,
  818. LIST LIST('OPERATOR,MKQUOTE Y))
  819. END;
  820. SYMBOLIC PROCEDURE OPERATOR U; MAPCAR(U,FUNCTION MKOP);
  821. DEFINEROP('OPERATOR,NIL,ParseOPERATOR);
  822. %. Diphthongs and READtable Changes
  823. Symbolic Procedure ChangeCharType(TBL,Ch,Ty); %. Set Character type
  824. begin scalar IDNum;
  825. If IDP Ch and (IDNum := ID2Int Ch) < 128 and
  826. Numberp Ty and Ty >=0 and Ty <=19 then
  827. PutV(TBL,IDNum,Ty)
  828. Else Error(99,"Cant Set ReadTable");
  829. end;
  830. Symbolic Procedure MakeDiphthong(TBL,DipIndicator,StartCh, FollowCh, Diphthong);
  831. If IDP Startch and IDP FollowCh and IDP Diphthong
  832. then <<ChangeCharType(TBL,StartCh,13);
  833. PUT(StartCh,DipIndicator,
  834. (FollowCh . Diphthong) . GET(StartCh,DipIndicator))>>
  835. else Error(99, "Cant Declare Diphthong");
  836. SYMBOLIC PROCEDURE MYNEWTOK(X,REPLACE,PRTCHARS);
  837. BEGIN SCALAR Y;
  838. PUT(X,'NEWNAM!-OP,REPLACE);
  839. IF NULL PRTCHARS THEN Y:=LIST(X,X)
  840. ELSE IF IDP PRTCHARS THEN Y:=LIST(PRTCHARS,X)
  841. ELSE Y:=PRTCHARS;
  842. PUT(REPLACE,'PRTCH,Y);
  843. END;
  844. MYNEWTOK('!;,'!*SEMICOL!*,NIL)$
  845. MYNEWTOK('!$,'!*SEMICOL!*,NIL)$
  846. MYNEWTOK('!,,'!*COMMA!*,NIL)$
  847. MYNEWTOK('!.,'CONS,NIL)$
  848. MYNEWTOK('!:!=,'SETQ,'! !:!=! )$
  849. MYNEWTOK('!+,'PLUS,'! !+! )$
  850. MYNEWTOK('!-,'DIFFERENCE,'! !-! )$
  851. MYNEWTOK('!*,'TIMES,NIL)$
  852. MYNEWTOK('!/,'QUOTIENT,NIL)$
  853. MYNEWTOK('!*!*,'EXPT,NIL)$
  854. MYNEWTOK('!^,'EXPT,NIL)$
  855. MYNEWTOK('!=,'EQUAL,NIL)$
  856. MYNEWTOK('!:,'!*COLON!*,NIL)$
  857. MYNEWTOK('!(,'!*LPAR!*,NIL)$
  858. MYNEWTOK('!),'!*RPAR!*,NIL)$
  859. MYNEWTOK('!{,'!*LSQB!*,NIL)$
  860. MYNEWTOK('!},'!*RSQB!*,NIL)$
  861. MYNEWTOK('!<!<,'!*LSQB!*,NIL)$
  862. MYNEWTOK('!>!>,'!*RSQB!*,NIL)$
  863. MYNEWTOK('![,'!*LVEC!*,NIL)$
  864. MYNEWTOK('!],'!*RVEC!*,NIL)$
  865. MYNEWTOK('!<,'LESSP,NIL)$
  866. MYNEWTOK('!<!=,'LEQ,NIL)$
  867. MYNEWTOK('!>!=,'GEQ,NIL)$
  868. MYNEWTOK('!>,'GREATERP,NIL)$
  869. fluid '(RLispScanTable!* RLispReadScanTable!*);
  870. RLispReadScanTable!* := '
  871. [17 11 11 11 11 11 11 11 11 17 17 11 17 17 11 11 11 11 11 11 11 11 11 11
  872. 11 11 11 11 11 11 11 11 17 14 15 11 11 12 11 11 11 11 13 19 11 18 20 11
  873. 0 1 2 3 4 5 6 7 8 9 13 11 13 11 13 11 11 10 10 10 10 10 10 10 10 10 10
  874. 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 16 11 11 10 11 10 10
  875. 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
  876. 11 11 11 11 11 LispDiphthong];
  877. RLispScanTable!* := TotalCopy RLispReadScanTable!*;
  878. PutV(RLispScanTable!*, 128, 'RLISPDIPHTHONG);
  879. ChangeCharType(RLispScanTable!*, '!-, 11);
  880. ChangeCharType(RLispScanTable!*, '!+, 11);
  881. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!:,'!=,'!:!= );
  882. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!<,'!=,'!<!= );
  883. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!>,'!=,'!>!= );
  884. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!<,'!<,'!<!< );
  885. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!>,'!>,'!>!> );
  886. MAKEDIPHTHONG(RLISPSCANTABLE!*,'RLISPDIPHTHONG,'!*,'!*,'!*!* );
  887. Symbolic Procedure XReadEof(Channel,Ef);
  888. if !*InsideStructureRead then
  889. StdError BldMsg("Unexpected EOF while parsing on channel %r", Channel)
  890. else Throw('!$ERROR!$, list !$EOF!$); % embarrasingly gross kludge
  891. Put(Int2ID char EOF, 'RlispReadMacro, 'XReadEOF);
  892. Symbolic Procedure RatomHOOK(); %. To get READ MACRO', EG EOF
  893. ChannelReadTokenWithHooks IN!*;
  894. lisp procedure RlispChannelRead Channel; %. Parse S-expression from channel
  895. begin scalar CurrentScanTable!*, CurrentReadMacroIndicator!*,
  896. CurrentDiphthongIndicator!*;
  897. CurrentScanTable!* := RLispReadScanTable!*;
  898. CurrentReadMacroIndicator!* := 'LispReadMacro;
  899. CurrentDiphthongIndicator!* := 'LispDiphthong;
  900. return ChannelReadTokenWithHooks Channel;
  901. end;
  902. lisp procedure RlispRead(); %. Parse S-expr from current input
  903. RlispChannelRead IN!*;
  904. END;