22-parser.lpt 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. PSL Manual 7 February 1983 Parser Tools
  2. section 22.0 page 22.1
  3. CHAPTER 22 CHAPTER 22 CHAPTER 22
  4. PARSER TOOLS PARSER TOOLS PARSER TOOLS
  5. 22.1. Introduction . . . . . . . . . . . . . . . 22.1
  6. 22.2. The Table Driven Parser . . . . . . . . . . . 22.2
  7. 22.2.1. Flow Diagram for the Parser. . . . . . . . 22.2
  8. 22.2.2. Associating the Infix Operator with a Function . 22.4
  9. 22.2.3. Precedences . . . . . . . . . . . . . 22.5
  10. 22.2.4. Special Cases of 0 <-0 and 0 0. . . . . . . 22.5
  11. 22.2.5. Parenthesized Expressions . . . . . . . . 22.5
  12. 22.2.6. Binary Operators in General. . . . . . . . 22.6
  13. 22.2.7. Assigning Precedences to Key Words . . . . . 22.7
  14. 22.2.8. Error Handling . . . . . . . . . . . . 22.7
  15. 22.2.9. The Parser Program for the RLISP Language . . . 22.7
  16. 22.2.10. Defining Operators . . . . . . . . . . 22.8
  17. 22.3. The MINI Translator Writing System. . . . . . . . 22.10
  18. 22.3.1. A Brief Guide to MINI. . . . . . . . . . 22.10
  19. 22.3.2. Pattern Matching Rules . . . . . . . . . 22.12
  20. 22.3.3. A Small Example. . . . . . . . . . . . 22.12
  21. 22.3.4. Loading Mini. . . . . . . . . . . . . 22.13
  22. 22.3.5. Running Mini. . . . . . . . . . . . . 22.13
  23. 22.3.6. MINI Error messages and Error Recovery . . . . 22.13
  24. 22.3.7. MINI Self-Definition . . . . . . . . . . 22.13
  25. 22.3.8. The Construction of MINI. . . . . . . . . 22.15
  26. 22.3.9. History of MINI Development. . . . . . . . 22.16
  27. 22.4. BNF Description of RLISP Using MINI . . . . . . . 22.17
  28. 22.1. Introduction 22.1. Introduction 22.1. Introduction
  29. In many applications, it is convenient to define a special
  30. "problem-oriented" language, tailored to provide a natural input format.
  31. Examples include the RLISP ALGOL-like surface language for algebraic work,
  32. graphics languages, boolean query languages for data-base, etc. Another
  33. ________ important case is the requirement to accept existing programs in some
  34. language, either to translate them to another language, to compile to
  35. machine language, to be able to adapt existing code into the PSL
  36. environment (e.g. mathematical libraries, etc.), or because we wish to use
  37. PSL based tools to analyze a program written in another language. One
  38. approach is to hand-code a program in PSL (called a "parser") that
  39. translates the input language to the desired form; this is tedious and
  40. error prone, and it is more convenient to use a "parser-writing-tool".
  41. In this Chapter we describe in detail two important parser writing tools
  42. available to the PSL programmer: an extensible table-driven parser that is
  43. used for the RLISP parser (described in Chapter 3), and the MINI parser
  44. generator. The table-driven parser is most useful for languages that are Parser Tools 7 February 1983 PSL Manual
  45. page 22.2 section 22.1
  46. simple extensions of RLISP, or in fact for rapidly adding new syntactic
  47. constructs to RLISP. The MINI system is used for the development of more
  48. complete user languages.
  49. 22.2. The Table Driven Parser 22.2. The Table Driven Parser 22.2. The Table Driven Parser
  50. The parser is a top-down recursive descent parser, which uses a table of
  51. ___________ Precedences to control the parse; if numeric precedence is not adequate,
  52. LISP functions may be inserted into the table to provide more control. The
  53. parser described here was developed by Nordstrom [Nordstrom 73], and is
  54. very similar to parser described by Pratt [Pratt 73], and apparently used
  55. for the CGOL language, another LISP surface language.
  56. Scan Scan Scan Scan The parser reads tokens from an input stream using a function Scan. Scan
  57. ChannelReadToken ChannelReadToken calls the ChannelReadToken function described in Chapter 12, and performs
  58. some additional checks, described below. Each token is defined to be one
  59. of the following:
  60. non-operator O
  61. right operator O->
  62. binary operator <-O->
  63. All combinations of . . .O-> O. . . and O <-O->. . . are supposed to be
  64. legal, while the combinations . . .O-> <-O->. . ., . . .<-O-> <-O->. . .
  65. and O O. . . are normally illegal (error ARG MISSING and error OP MISSING,
  66. respectively).
  67. __ With each operator (which must be an id) is associated a construction
  68. function, a right precedence, and for binary operators, a left precedence.
  69. The Unary Prefix operators have this information stored under the
  70. indicator 'RLISPPREFIX and Binary operators have it stored under
  71. 'RLISPINFIX. (Actually, the indicator used at any time during parsing is
  72. the VALUE of GRAMPREFIX or GRAMINFIX, which may be changed by the user).
  73. 22.2.1. Flow Diagram for the Parser 22.2.1. Flow Diagram for the Parser 22.2.1. Flow Diagram for the Parser
  74. In this diagram RP stands for Right Precedence, LP for Left Precedence
  75. and CF for Construction Function. OP is a global variable which holds the
  76. current token. PSL Manual 7 February 1983 Parser Tools
  77. section 22.2 page 22.3
  78. procedure PARSE(RP);
  79. RDRIGHT(RP,SCAN()); % SCAN reads next token
  80. RDRIGHT(RP,Y)
  81. |
  82. \|/
  83. |
  84. ------------------------
  85. | |yes
  86. | Y is Right OP |-----> Y:=APPLY(Y.CF,
  87. | | RDRIGHT(Y.RP));
  88. ------------------------ .
  89. | .
  90. \|/ no .
  91. | .
  92. ------------------------ .
  93. ERROR yes| | no .
  94. ARG <----| Y is Binary OP |----> OP:= .
  95. MISSING | | SCAN(); .
  96. ------------------------ . .
  97. |--------<------------<------*
  98. RDLEFT: \|/ ^
  99. | ^
  100. ------------------------ ^
  101. ERROR no| | ^
  102. OP <----| OP is Binary | ^
  103. MISSING | | ^
  104. ------------------------ ^
  105. | ^
  106. \|/ yes ^
  107. | ^
  108. ------------------------ ^
  109. RETURN yes| |no ^
  110. (Y) <----| RP > OP.lp |---> Y:=APPLY(OP.cf,Y,
  111. ------------------------ PARSE(OP.lp,SCAN()); Parser Tools 7 February 1983 PSL Manual
  112. page 22.4 section 22.2
  113. This diagram reflects the major behavior, though some trivial additions
  114. are included in the RLISP case to handle cases such as OP-> <-OP, '!;, etc.
  115. [See PU:RLISP-PARSER.RED for full details.]
  116. The technique involved may also be described by the following figure:
  117. . . . 0-> Y <-0 . . .
  118. rp lp
  119. Y is a token or an already parsed expression between two operators (as
  120. indicated). If 0->'s RP is greater than <-0's LP, then 0-> is the winner
  121. and Y goes to 0->'s construction function (and vice versa). The result
  122. from the construction function is a "new Y" in another parse situation.
  123. By associating precedences and construction functions with the operators,
  124. we are now able to parse arithmetic expressions (except for function calls)
  125. and a large number of syntactical constructions such as IF - THEN - ELSE
  126. - ; etc. The following discussion of how to expand the parser to cover a
  127. language such as RLISP (or ALGOL) may also be seen as general tools for
  128. handling the parser and defining construction functions and precedences.
  129. 22.2.2. Associating the Infix Operator with a Function 22.2.2. Associating the Infix Operator with a Function 22.2.2. Associating the Infix Operator with a Function
  130. Scan RAtomHook Scan RAtomHook __ __ The Scan, after calling RAtomHook, checks ids and special ids (those with
  131. TOKTYPE!* = 3) to see if they should be renamed from external form to
  132. Plus2 Plus2 internal form (e.g. '!+ to Plus2). This is done by checking for a NEWNAM
  133. __ __ or NEWNAM!-OP property on the id. For special ids, the NEWNAM!-OP property
  134. is first checked. The value of the property is a replacement token, i.e.
  135. PUT('!+,'NEWNAM!-OP,'PLUS2)
  136. has been done.
  137. Scan RlispRead Scan RlispRead Scan also handles the ' mark, calling RlispRead to get the S-expression.
  138. RlispRead Read RlispRead Read RlispRead is a version of Read, using a special SCANTABLE,
  139. RLISPREADSCANTABLE!*.
  140. Scan Scan The function Scan also sets SEMIC!* to '!; or '!$ if CURSYM!* is detected
  141. to be '!*SEMICOL!* (the internal name for '!; and "!$). This controls the
  142. RLISP echo/no-echo capability. Finally, if the renamed token is 'COMMENT
  143. ReadCh ReadCh then characters are ReadCh'd until a '!; or '!$ . PSL Manual 7 February 1983 Parser Tools
  144. section 22.2 page 22.5
  145. 22.2.3. Precedences 22.2.3. Precedences 22.2.3. Precedences
  146. To set up precedences, it is often helpful to set up a precedence matrix
  147. of the operators involved. If any operator has one "precedence" with
  148. respect to one particular operator and another "precedence" with respect to
  149. some other, it is sometimes not possible to run the parser with just
  150. numbered precedences for the operators without introducing ambiguities. If
  151. this is the case, replace the number RP by the operator RP and test with
  152. something like:
  153. IF RP *GREATER* OP . . .
  154. *GREATER* may check in the precedence matrix. An example in which such a
  155. scheme might be used is the case for which ALGOL uses ":" both as a label
  156. marker and as an index separator (although in this case there is no need
  157. for the change above). It is also a good policy to have even numbers for
  158. right precedences and odd numbers for left precedences (or vice versa).
  159. 22.2.4. Special Cases of 0 <-0 and 0 0 22.2.4. Special Cases of 0 <-0 and 0 0 22.2.4. Special Cases of 0 <-0 and 0 0
  160. If . . .0 0. . . is a legal case (i.e. F A may translate to (F A)),
  161. ERROR OP MISSING is replaced by:
  162. Y:=REPCOM(Y,RDRIGHT(99,OP)); GO TO RDLEFT;
  163. The value 99 is chosen in order to have the first object (F) behave as a
  164. right operator with maximum precedence. If . . .0 <-0. . . is legal for
  165. some combinations of operators, replace ERROR ARG MISSING by something
  166. equivalent to the illegal RLISP statement:
  167. IF ISOPOP(OP,RP,Y)
  168. THEN <<OP:=Y;
  169. Y:=(something else, i.e. NIL);
  170. GOTO RDLEFT>>
  171. ELSE ERROR ARG MISSING;
  172. ISOPOP is supposed to return T if the present situation is legal.
  173. 22.2.5. Parenthesized Expressions 22.2.5. Parenthesized Expressions 22.2.5. Parenthesized Expressions
  174. (a) is to be translated to a.
  175. E.g. Parser Tools 7 February 1983 PSL Manual
  176. page 22.6 section 22.2
  177. BEGIN a END translates to (PROG a).
  178. Define "(" and BEGIN as right operators with low precedences (2 and -2
  179. respectively). Also define ")" and END as binary operators with matching
  180. left precedences (1 and -3 respectively). The construction functions for
  181. "(" and BEGIN are then something like: [See pu:RLISP-PARSER.RED for exact
  182. details on ParseBEGIN]
  183. BEGIN (X);PROG2(OP:=SCAN();MAKEPROG(X));
  184. "(" (X);PROG2(IF OP=') THEN OP:=SCAN()
  185. ELSE ERROR, x);
  186. Note that the construction functions in these cases have to read the next
  187. token; that is the effect of ")" closing the last "(" and not all earlier
  188. "("'s. This is also an example of binary operators declared only for the
  189. purpose of having a left precedence.
  190. 22.2.6. Binary Operators in General 22.2.6. Binary Operators in General 22.2.6. Binary Operators in General
  191. As almost all binary operators have a construction function like
  192. LIST(OP,X,Y);
  193. it is assumed to be of that kind if no other is given. If OP is a binary
  194. operator, then "a OP b OP c" is interpreted as "(a OP b) OP c" only if OP's
  195. LP is less than OP's RP.
  196. Example:
  197. A + B + C translates to (A + B) + C
  198. because +'RP = 20 and +'LP = 19
  199. A ^ B ^ C translates to A ^ (B ^ C)
  200. because ^'RP = 20 and ^'LP = 21
  201. If you want some operators to translate to n-ary expressions, you have to
  202. define a proper construction function for that operator.
  203. Example:
  204. PLUS (X,Y); IF CAR(X) = 'PLUS THEN NCONC(X,LIST(Y))
  205. ELSE LIST('PLUS,X,Y); PSL Manual 7 February 1983 Parser Tools
  206. section 22.2 page 22.7
  207. By defining "," and ";" as ordinary binary operators, the parser
  208. automatically takes care of constructions like . . .e,e,e,e,e. . . and
  209. . . . stm;stm;stm;stm;. . . It is then up to some other operators to
  210. remove the "," or the ";" from the parsed result.
  211. 22.2.7. Assigning Precedences to Key Words 22.2.7. Assigning Precedences to Key Words 22.2.7. Assigning Precedences to Key Words
  212. If you want some operators to have control immediately, insert
  213. IF RP = NIL THEN RETURN Y ELSE
  214. as the very first test in RDRIGHT and set the right precedence of those to
  215. NIL. This is sometimes useful for key-word expressions. If entering a
  216. construction function of such an operator, X is the token immediately after
  217. the operator. E.g.: We want to parse PROCEDURE EQ(X,Y); . . . Define
  218. PROCEDURE as a right operator with NIL as precedence. The construction
  219. function for PROCEDURE can always call the parser and set the rest of the
  220. expression. Note that if PROCEDURE was not defined as above, the parser
  221. would misunderstand the expression in the case of EQ as declared as a
  222. binary operator.
  223. 22.2.8. Error Handling 22.2.8. Error Handling 22.2.8. Error Handling
  224. For the present, if an error occurs a message is printed but no attempt
  225. is made to correct or handle the error. Mostly the parser goes wild for a
  226. while (until a left precedence less than current right precedence is found)
  227. and then goes on as usual.
  228. 22.2.9. The Parser Program for the RLISP Language 22.2.9. The Parser Program for the RLISP Language 22.2.9. The Parser Program for the RLISP Language
  229. SCAN();
  230. The purpose of this function is to read the next token from the input
  231. stream. It uses the general purpose table driven token scanner described
  232. in Chapter 12, with a specially set up ReadTable, RLISPSCANTABLE!*. As
  233. Scan __________ Scan RLISP has multiple identifiers for the same operators, Scan uses the
  234. following translation table:
  235. = EQUAL >= GEQ
  236. + PLUS > GREATERP
  237. - DIFFERENCE <= LEQ
  238. / QUOTIENT < LESSP
  239. . CONS * TIMES
  240. := SETQ ** EXPT
  241. Scan Scan In these cases, Scan returns the right hand side of the table values.
  242. Scan Scan Also, two special cases are taken care of in Scan: Parser Tools 7 February 1983 PSL Manual
  243. page 22.8 section 22.2
  244. a. ' is the QUOTE mark. If a parenthesized expression follows '
  245. then the syntax within the parenthesis is that of LISP, using a
  246. special scan table, RLISPREADSCANTABLE!*. The only major
  247. difference from ordinary LISP is that ! is required for all
  248. special characters.
  249. b. ! in RLISP means actually two things:
  250. i. the following symbol is not treated as a special symbol
  251. (but belongs to the print name of the atom in process);
  252. ii. the atom created cannot be an operator.
  253. Example: !( in the text behaves as the atom "(".
  254. To signal to the parser that this is the case, the flag variable ESCAPEFL
  255. must be set to T if this situation occurs.
  256. 22.2.10. Defining Operators 22.2.10. Defining Operators 22.2.10. Defining Operators
  257. To define operators use:
  258. DEFINEROP(op,p{,stm});
  259. For right or prefix operators.
  260. DEFINEBOP(op,lp,rp{,stm});
  261. For binary operators.
  262. These use the VALUE of DEFPREFIX and DEFINFIX to store the precedences
  263. and construction functions. The default is set for RLISP, to be
  264. __________ 'RLISPPREFIX and 'RLISPINFIX. The same identifier can be defined both as
  265. the right and binary operator. The context defines which one applies.
  266. Stm is the construction function. If stm is omitted, the common defaults
  267. are used:
  268. LIST(OP,x)
  269. prefix case, x is parsed expression following,
  270. x=RDRIGHT(p,SCAN()).
  271. LIST(OP,x,y)
  272. binary case, x is previously parsed expression, y is expression
  273. following, y=RDRIGHT(rp,SCAN()).
  274. __ If stm is an id, it is assumed to be a procedure of one or two arguments, PSL Manual 7 February 1983 Parser Tools
  275. section 22.2 page 22.9
  276. for "x" or "x,y". If it is an expression, it is embedded as
  277. (LAMBDA(X) stm) or (LAMBDA(X Y) stm), and should refer to X and Y, as
  278. needed.
  279. Also remember that the free variable OP holds the last token (normally
  280. the binary operator which stopped the parser). If "p" or "rp" is NIL,
  281. RDRIGHT is not called by default, so that only SCAN() (the next token) is
  282. passed.
  283. For example,
  284. DEFINEBOP('DIFFERENCE,17,18);
  285. % Most common case, left associative, stm=LIST(OP,x,y);
  286. DEFINEBOP('CONS,23,21);
  287. % Right Associative, default stm=LIST(OP,x,y)
  288. DEFINEBOP('AND,11,12,ParseAND);
  289. % Left Associative, special function
  290. PROCEDURE ParseAND(X,Y);
  291. NARY('AND,X,Y);
  292. DEFINEBOP('SETQ,7,6,ParseSETQ);
  293. % Right Associative, Special Function
  294. PROCEDURE ParseSETQ(LHS,RHS);
  295. LIST(IF ATOM LHS THEN 'SETQ ELSE 'SETF, LHS, RHS);
  296. DEFINEROP('MINUS,26); % default C-fn, just (list OP arg)
  297. DEFINEROP('PLUS,26,ParsePLUS1); %
  298. DEFINEROP('GO,NIL,ParseGO );
  299. % Special Function, DO NOT use default PARSE ahead
  300. PROCEDURE ParseGO X; X is now JUST next-token
  301. IF X EQ 'TO THEN LIST('GO,PARSE0(6,T))
  302. % Explicit Parse ahead
  303. ELSE <<OP := SCAN(); % get Next Token
  304. LIST('GO,X)>>;
  305. DEFINEROP('GOTO,NIL,ParseGOTO );
  306. % Suppress Parse Ahead, just pass NextToken
  307. PROCEDURE ParseGOTO X;
  308. <<OP := SCAN();
  309. LIST('GO,X)>>; Parser Tools 7 February 1983 PSL Manual
  310. page 22.10 section 22.3
  311. 22.3. The MINI Translator Writing System 22.3. The MINI Translator Writing System 22.3. The MINI Translator Writing System
  312. Note that MINI is now autoloading.
  313. 22.3.1. A Brief Guide to MINI 22.3.1. A Brief Guide to MINI 22.3.1. A Brief Guide to MINI
  314. The following is a brief introduction to MINI, the reader is referred
  315. to [Marti 79] for a more detailed discussion of the META/RLISP operators,
  316. which are very similar to those of MINI.
  317. The MINI system reads in a definition of a translator, using a BNF-like
  318. form. This is processed by MINI into a set of LISP functions, one for each
  319. production, which make calls on each other, and a set of support routines
  320. that recognize a variety of simple constructs. MINI uses a stack to
  321. perform parsing, and the user can access sub-trees already on the stack,
  322. replacing them by other trees built from these sub-trees. The primitive
  323. __ _______ functions that recognize ids, integers, etc. each place their recognized
  324. token on this stack.
  325. For example,
  326. FOO: ID '!- ID +(PLUS2 #2 #1) ;
  327. defines a rule FOO, which recognizes two identifiers separated by a minus
  328. __________ sign (each ID pushes the recognized identifier onto the stack). The last
  329. expression replaces the top 2 elements on the stack (#2 pops the first ID
  330. pushed onto the stack, while #1 pops the other) with a LISP statement.
  331. Id Id _______ ____ (Id ): boolean expr
  332. __________ See if current token is an identifier and not a keyword. If it
  333. is, then push onto the stack and fetch the next token.
  334. AnyId AnyId _______ ____ (AnyId ): boolean expr
  335. __ See if current token is an id whether or not it is a key word.
  336. AnyTok AnyTok _______ ____ (AnyTok ): boolean expr
  337. Always succeeds by pushing the current token onto the stack.
  338. Num Num _______ ____ (Num ): boolean expr
  339. ______ Tests to see if the current token is a number, if so it pushes
  340. ______ the number onto the stack and fetches the next token. PSL Manual 7 February 1983 Parser Tools
  341. section 22.3 page 22.11
  342. Str Str _______ ____ (Str ): boolean expr
  343. Num Num ______ Same as Num, except for strings.
  344. Specification of a parser using MINI consists of defining the syntax with
  345. BNF-like rules and semantics with LISP expressions. The following is a
  346. brief list of the operators:
  347. ' Used to designate a terminal symbol (i.e. 'WHILE, 'DO, '!=).
  348. Identifier
  349. Specifies a nonterminal.
  350. ( ) Used for grouping (i.e. (FOO BAR) requires rule FOO to parse
  351. followed immediately by BAR).
  352. < > Optional parse, if it fails then continue (i.e. <FOO> tries to
  353. parse FOO).
  354. / Optional rules (i.e. FOO / BAR allows either FOO or BAR to parse,
  355. with FOO tested first).
  356. STMT* Parse any number of STMT.
  357. STMT[ANYTOKEN]*
  358. Parse any number of STMT separated by ANYTOKEN, create a list and
  359. __________ push onto the stack (i.e. ID[,]* parses a number of identifiers
  360. separated by commas, like in an argument list).
  361. _______ ##n Refer to the nth stack location (n must be an integer).
  362. _______ #n Pop the nth stack location (n must be an integer).
  363. +(STMT) Push the unevaluated (STMT) onto the stack.
  364. .(SEXPR) Evaluate the SEXPR and ignore the result.
  365. =(SEXPR) Evaluate the SEXPR and test if result non-NIL.
  366. +.(SEXPR) Evaluate the SEXPR and push the result on the stack.
  367. @ANYTOKEN Specifies a statement terminator; used in the error recovery
  368. mechanism to search for the occurrence of errors.
  369. @@ANYTOKEN
  370. Grammar terminator; also stops scan, but if encountered in
  371. error-recovery, terminates grammar. Parser Tools 7 February 1983 PSL Manual
  372. page 22.12 section 22.3
  373. 22.3.2. Pattern Matching Rules 22.3.2. Pattern Matching Rules 22.3.2. Pattern Matching Rules
  374. In addition to the BNF-like rules that define procedures with 0 arguments
  375. and which scan tokens by calls on NEXT!-TOK() and operate on the stack,
  376. MINI also includes a simple TREE pattern matcher and syntax to define
  377. PatternProcedures that accept and return a single argument, trying a series
  378. of patterns until one succeeds.
  379. E.g. template -> replacement
  380. PATTERN = (PLUS2 &1 0) -> &1,
  381. (PLUS2 &1 &1) -> (LIST 'TIMES2 2 &1),
  382. &1 -> &1;
  383. defines a pattern with 3 rules. &n is used to indicate a matched sub-tree
  384. in both the template and replacement. A repeated &n, as in the second
  385. Equal Equal rule, requires Equal sub-trees.
  386. 22.3.3. A Small Example 22.3.3. A Small Example 22.3.3. A Small Example
  387. % A simple demo of MINI, to produce a LIST-NOTATION reader.
  388. % INVOKE 'LSPLOOP reads S-expressions, separated by ;
  389. mini 'lsploop; % Invoke MINI, give name of ROOT
  390. % Comments can appear anywhere,
  391. % prefix by % to end-of-line
  392. lsploop:lsp* @@# ; % @@# is GRAMMAR terminator
  393. % like '# but stops TOKEN SCAN
  394. lsp: sexp @; % @; is RULE terminator, like ';
  395. .(print #1) % but stops SCAN, to print
  396. .(next!-tok) ; % so call NEXT!-TOK() explicitly
  397. sexp: id / num / str / '( dotexp ') ;
  398. dotexp: sexp* < '. sexp +.(attach #2 #1) > ;
  399. fin
  400. symbolic procedure attach(x,y);
  401. <<for each z in reverse x do y:=z . y; y>>;
  402. 22.3.4. Loading Mini 22.3.4. Loading Mini 22.3.4. Loading Mini
  403. MINI is loaded from PH: using LOAD MINI;. PSL Manual 7 February 1983 Parser Tools
  404. section 22.3 page 22.13
  405. 22.3.5. Running Mini 22.3.5. Running Mini 22.3.5. Running Mini
  406. Invoke Invoke A MINI grammar is run by calling Invoke rootname;. This installs
  407. appropriate Key Words (stored on the property list of rootname), and start
  408. the grammar by calling the Rootname as first procedure.
  409. 22.3.6. MINI Error messages and Error Recovery 22.3.6. MINI Error messages and Error Recovery 22.3.6. MINI Error messages and Error Recovery
  410. If MINI detects a non-fatal error, a message be printed, and the current
  411. token and stack is shown. MINI then calls NEXT!-TOK() repeatedly until
  412. either a statement terminator (@ANYTOKEN) or grammar terminator (@ANYTOKEN)
  413. is seen. If a grammar terminator, the grammar is exited; otherwise parsing
  414. resumes from the ROOT.
  415. [??? Interaction with BREAK loop rather poor at the moment ???] [??? Interaction with BREAK loop rather poor at the moment ???] [??? Interaction with BREAK loop rather poor at the moment ???]
  416. 22.3.7. MINI Self-Definition 22.3.7. MINI Self-Definition 22.3.7. MINI Self-Definition
  417. % The following is the definition of the MINI meta system in terms of
  418. % itself. Some support procedures are needed, and exist in a
  419. % separate file.
  420. % To define a grammar, call the procedure MINI with the argument
  421. % being the root rule name. Then when the grammar is defined it may
  422. % be called by using INVOKE root rule name.
  423. % The following is the MINI Meta self definition.
  424. MINI 'RUL;
  425. % Define the diphthongs to be used in the grammar.
  426. DIP: !#!#, !-!>, !+!., !@!@ ;
  427. % The root rule is called RUL.
  428. RUL: ('DIP ': ANYTOK[,]* .(DIPBLD #1) '; /
  429. (ID .(SETQ !#LABLIST!# NIL)
  430. ( ': ALT +(DE #2 NIL #1) @; /
  431. '= PRUL[,]* @; .(RULE!-DEFINE '(PUT(QUOTE ##2)(QUOTE RB)
  432. (QUOTE #1)))
  433. +(DE ##1 (A)
  434. (RBMATCH A (GET (QUOTE #1) (QUOTE RB))
  435. NIL)))
  436. .(RULE!-DEFINE #1) .(NEXT!-TOK) ))* @@FIN ;
  437. % An alternative is a sequence of statements separated by /'s;
  438. ALT: SEQ < '/ ALT +(OR #2 #1) >;
  439. % A sequence is a list of items that must be matched.
  440. SEQ: REP < SEQ +(AND #2 (FAIL!-NOT #1)) >; Parser Tools 7 February 1983 PSL Manual
  441. page 22.14 section 22.3
  442. % A repetition may be 0 or more single items (*) or 0 or more items
  443. % separated by any token (ID[,]* parses a list of ID's separated
  444. % by ,'s.
  445. REP: ONE
  446. <'[ (ID +(#1) /
  447. '' ANYKEY +(EQTOK!-NEXT (QUOTE #1)) /
  448. ANYKEY +(EQTOK!-NEXT (QUOTE #1))) '] +(AND #2 #1) '* BLD!-EXPR /
  449. '* BLD!-EXPR>;
  450. % Create an sexpression to build a repetition.
  451. BLD!-EXPR: +(PROG (X) (SETQ X (STK!-LENGTH))
  452. $1 (COND (#1 (GO $1)))
  453. (BUILD!-REPEAT X)
  454. (RETURN T));
  455. ANYKEY: ANYTOK .(ADDKEY ##1) ; % Add a new KEY
  456. % One defines a single item.
  457. ONE: '' ANYKEY +(EQTOK!-NEXT (QUOTE #1)) /
  458. '@ ANYKEY .(ADDRTERM ##1) +(EQTOK (QUOTE #1)) /
  459. '@@ ANYKEY .(ADDGTERM ##1) +(EQTOK (QUOTE #1)) /
  460. '+ UNLBLD +(PUSH #1) /
  461. '. EVLBLD +(PROGN #1 T) /
  462. '= EVLBLD /
  463. '< ALT '> +(PROGN #1 T) /
  464. '( ALT ') /
  465. '+. EVLBLD +(PUSH #1) /
  466. ID +(#1) ;
  467. % This rule defines an un evaled list. It builds a list with
  468. % everything quoted.
  469. UNLBLD: '( UNLBLD ('. UNLBLD ') +(CONS #2 #1) /
  470. UNLBLD* ') +(LIST . (#2 . #1)) /
  471. ') +(LIST . #1)) /
  472. LBLD /
  473. ID +(QUOTE #1) ;
  474. % EVLBLD builds a list of evaled items.
  475. EVLBLD: '( EVLBLD ('. EVLBLD ') +(CONS #2 #1) /
  476. EVLBLD* ') +(#2 . #1) /
  477. ') ) /
  478. LBLD /
  479. ID ;
  480. LBLD: '# NUM +(EXTRACT #1) /
  481. '## NUM +(REF #1) /
  482. '$ NUM +(GENLAB #1) /
  483. '& NUM +(CADR (ASSOC #1 (CAR VARLIST))) /
  484. NUM /
  485. STR /
  486. '' ('( UNLBLD* ') +(LIST . #1) /
  487. ANYTOK +(QUOTE #1)); PSL Manual 7 February 1983 Parser Tools
  488. section 22.3 page 22.15
  489. % Defines the pattern matching rules (PATTERN -> BODY).
  490. PRUL: .(SETQ INDEXLIST!* NIL)
  491. PAT '-> (EVLBLD)*
  492. +(LAMBDA (VARLIST T1 T2 T3) (AND . #1))
  493. .(SETQ PNAM (GENSYM))
  494. .(RULE!-DEFINE (LIST 'PUTD (LIST 'QUOTE PNAM)
  495. '(QUOTE EXPR) (LIST 'QUOTE #1)))
  496. +.(CONS #1 PNAM);
  497. % Defines a pattern.
  498. % We now allow the . operator to be the next to last in a ().
  499. PAT: '& ('< PSIMP[/]* '> NUM
  500. +.(PROGN (SETQ INDEXLIST!* (CONS ##1 INDEXLIST!*))
  501. (LIST '!& #2 #1) ) /
  502. NUM
  503. +.(COND ((MEMQ ##1 INDEXLIST!*)
  504. (LIST '!& '!& #1))
  505. (T (PROGN (SETQ INDEXLIST!* (CONS ##1 INDEXLIST!*))
  506. (LIST '!& #1)))) )
  507. / ID
  508. / '!( PAT* <'. PAT +.(APPEND #2 #1)> '!)
  509. / '' ANYTOK
  510. / STR
  511. / NUM ;
  512. % Defines the primitives in a pattern.
  513. PSIMP: ID / NUM / '( PSIMP* ') / '' ANYTOK;
  514. % The grammar terminator.
  515. FIN
  516. 22.3.8. The Construction of MINI 22.3.8. The Construction of MINI 22.3.8. The Construction of MINI
  517. MINI is actually described in terms of a support package for any
  518. MINI-generated parser and a self-description of MINI. The useful files (on
  519. PU: and PL:) are as follows:
  520. MINI.MIN The self definition of MINI in MINI.
  521. MINI.SL A Standard LISP version of MINI.MIN, translated by MINI itself.
  522. MINI.RED The support RLISP for MINI.
  523. MINI-PATCH.RED and MINI.FIX
  524. Some additions being tested.
  525. MINI.LAP The precompiled LAP file. Use LOAD MINI.
  526. MINI-LAP-BUILD.CTL
  527. A batch file that builds PL:MINI.LAP from the above files.
  528. MINI-SELF-BUILD.CTL
  529. A batch file that builds the MINI.SL file by loading and
  530. translating MINI.MIN. Parser Tools 7 February 1983 PSL Manual
  531. page 22.16 section 22.3
  532. 22.3.9. History of MINI Development 22.3.9. History of MINI Development 22.3.9. History of MINI Development
  533. The MINI Translator Writing System was developed in two steps. The first
  534. was the enhancement of the META/RLISP [Marti 79] system with the definition
  535. of pattern matching primitives to aid in describing and performing
  536. tree-to-tree transformations. META/RLISP is very proficient at translating
  537. an input programming language into LISP or LISP-like trees, but did not
  538. have a good method for manipulating the trees nor for direct generation of
  539. target machine code. PMETA (as it was initially called) [Kessler 79]
  540. solved these problems and created a very good environment for the
  541. development of compilers. In fact, the PMETA enhancements have been fully
  542. integrated into META/RLISP.
  543. The second step was the elimination of META/RLISP and the development of
  544. a smaller, faster system (MINI). Since META/RLISP was designed to provide
  545. maximum flexibility and full generality, the parsers that is creates are
  546. large and slow. One of its most significant problems is that it uses its
  547. own single character driven LISP functions for token scanning and
  548. recognition. Elimination of this overhead has produced a faster
  549. translator. MINI uses the hand coded scanner in the underlying RLISP. The
  550. other main aspect of MINI was the elimination of various META/RLISP
  551. features to decrease the size of the system (also decreasing the
  552. flexibility, but MINI has been successful for the various purposes in COG).
  553. MINI is now small enough to run on small LISP systems (as long as a token
  554. scanner is provided). The META/RLISP features that MINI has changed or
  555. eliminated include the following:
  556. a. The ability to backup the parser state upon failure is supported
  557. in META/RLISP. However, by modifying a grammar definition, the
  558. need for backup can be mostly avoided and was therefore
  559. eliminated from MINI.
  560. b. META/RLISP has extensive mechanisms to allow arbitrary length
  561. diphthongs. MINI only supports two character diphthongs,
  562. declared prior to their use.
  563. c. The target machine language and error specification operators
  564. are not supported because they can be implemented with support
  565. routines.
  566. d. RLISP subsyntax for specification of semantic operations is not
  567. supported (only LISP is provided).
  568. Although MINI lacks many of the features of META/RLISP, it still has been
  569. quite sufficient for a variety of languages. PSL Manual 7 February 1983 Parser Tools
  570. section 22.4 page 22.17
  571. 22.4. BNF Description of RLISP Using MINI 22.4. BNF Description of RLISP Using MINI 22.4. BNF Description of RLISP Using MINI
  572. The following formal scheme for the translation of RLISP syntax to LISP
  573. syntax is presented to eliminate misinterpretation of the definitions. We
  574. have used the above MINI syntactic form since it is close enough to BNF and
  575. has also been checked mechanically.
  576. Recall that the transformation scheme produces an S-expression
  577. corresponding to the input RLISP expression. A rule has a name by which it
  578. is known and is defined by what follows the meta symbol :. Each rule of
  579. the set consists of one or more "alternatives" separated by the meta symbol
  580. /, being the different ways in which the rule is matched by source text.
  581. Each rule ends with a ;. Each alternative is composed of a "recognizer"
  582. and a "generator". The "generator" is a MINI + expression which builds an
  583. S-expression from constants and elements loaded on the stack. The result
  584. is then loaded on the stack. The #n and ##n refer to elements loaded by
  585. MINI primitives or other rules. The "generator" is thus a template into
  586. which previously generated items are substituted. Recall that terminals in
  587. both recognizer and generator are quoted with a ' mark.
  588. This RLISP/SYSLISP syntax is based on a series of META and MINI
  589. definitions, started by R. Loos in 1970, continued by M. Griss, R. Kessler
  590. and A. Wang.
  591. [??? This MINI.RLISP grammar is a bit out of date ???] [??? This MINI.RLISP grammar is a bit out of date ???] [??? This MINI.RLISP grammar is a bit out of date ???]
  592. [??? Need to confirm for latest RLISP ???] [??? Need to confirm for latest RLISP ???] [??? Need to confirm for latest RLISP ???]
  593. mini 'rlisp;
  594. dip: !: , !<!< , !>!> , !:!= , !*!* , !<!= , !>!= , !' , !#!# ;
  595. termin: '; / '$ ; % $ used to not echo result
  596. rtermin: @; / @$ ;
  597. rlisp: ( cmds rtermin .(next!-tok) )* ; % Note explicit Scan
  598. cmds: procdef / rexpr ;
  599. %------ Procedure definition:
  600. procdef: emodeproc (ftype procs/ procs) /
  601. ftype procs / procs ;
  602. ftype: 'fexpr .(setq FTYPE!* 'fexpr) / % function type
  603. 'macro .(setq FTYPE!* 'macro) /
  604. 'smacro .(setq FTYPE!* 'smacro) /
  605. 'nmacro .(setq FTYPE!* 'nmacro) /
  606. ('expr / =T) .(setq FTYPE!* 'expr) ; Parser Tools 7 February 1983 PSL Manual
  607. page 22.18 section 22.4
  608. emodeproc: 'syslsp .(setq EMODE!* 'syslsp)/
  609. ('lisp/'symbolic/=T) .(setq EMODE!* 'symbolic) ;
  610. procs: 'procedure id proctail
  611. +(putd (quote #2) (quote FTYPE!* ) #1) ;
  612. proctail: '( id[,]* ') termin rexpr +(quote (lambda #2 #1)) /
  613. termin rexpr +(quote (lambda nil #1)) /
  614. id termin rexpr +(quote (lambda (#2) #1)) ;
  615. %------ Rexpr definition:
  616. rexpr: disjunction ;
  617. disjunction: conjunction (disjunctail / =T) ;
  618. disjunctail: ('or conjunction ('or conjunction)*)
  619. +.(cons 'or (cons #3 (cons #2 #1))) ;
  620. conjunction: negation (conjunctail / =T) ;
  621. conjunctail: ('and negation ('and negation)*)
  622. +.(cons (quote and) (cons #3 (cons #2 #1))) ;
  623. negation: 'not negation +(null #1) /
  624. 'null negation +(null #1) /
  625. relation ;
  626. relation: term reltail ;
  627. reltail: relop term +(#2 #2 #1) / =T ;
  628. term: ('- factor +(minus #1) / factor) termtail ;
  629. termtail: (plusop factor +(#2 #2 #1) termtail) / =T ;
  630. factor: powerexpr factortail ;
  631. factortail: (timop powerexpr +(#2 #2 #1) factortail) / =T ;
  632. powerexpr: dotexpr powtail ;
  633. powtail: ('** dotexpr +(expt #2 #1) powtail) / =T ;
  634. dotexpr: primary dottail ;
  635. dottail: ('. primary +(cons #2 #1) dottail) / =T ;
  636. primary: ifstate / groupstate / beginstate / PSL Manual 7 February 1983 Parser Tools
  637. section 22.4 page 22.19
  638. whilestate / repeatstate / forstmts /
  639. definestate / onoffstate / lambdastate /
  640. ('( rexpr ') ) /
  641. ('' (lists / id / num) +(quote #1)) /
  642. id primtail / num ;
  643. primtail:(':= rexpr +(setq #2 #1)) /
  644. (': labstmts ) /
  645. '( actualst / (primary +(#2 #1)) / =T ;
  646. lists: '( (elements)* ') ;
  647. elements: lists / id / num ;
  648. %------ If statement:
  649. ifstate: 'if rexpr 'then rexpr elserexpr
  650. +(cond (#3 #2) (T #1)) ;
  651. elserexpr: 'else rexpr / =T +nil ;
  652. %------ While statement:
  653. whilestate: 'while rexpr 'do rexpr
  654. +(while #2 #1) ;
  655. %----- Repeat statement:
  656. repeatstate: 'repeat rexpr 'until rexpr
  657. +(repeat #2 #1) ;
  658. %---- For statement:
  659. forstmts: 'for fortail ;
  660. fortail: ('each foreachstate) / forstate ;
  661. foreachstate: id inoron rexpr actchoice rexpr
  662. +(foreach #5 #4 #3 #2 #1) ;
  663. inoron: ('in +in / 'on +on) ;
  664. actchoice: ('do +do / 'collect +collect / 'conc +conc) ;
  665. forstate: id ':= rexpr loops ;
  666. loops: (': rexpr types rexpr
  667. +(for #5 (#4 1 #3) #2 #1) ) /
  668. ('step rexpr 'until rexpr types rexpr
  669. +(for #6 (#5 #4 #3) #2 #1) ) ;
  670. types: ('do +do / 'sum +sum / 'product +product) ; Parser Tools 7 February 1983 PSL Manual
  671. page 22.20 section 22.4
  672. %----- Function call parameter list:
  673. actualst: ') +(#1) / rexpr[,]* ') +.(cons #2 #1) ;
  674. %------ Compound group statement:
  675. groupstate: '<< rexprlist '>> +.(cons (quote progn) #1) ;
  676. %------ Compound begin-end statement:
  677. beginstate: 'begin blockbody 'end ;
  678. blockbody: decllist blockstates
  679. +.(cons (quote prog) (cons #2 #1)) ;
  680. decllist: (decls[;]* +.(flatten #1)) / (=T +nil) ;
  681. decls: ('integer / 'scalar) id[,]* ;
  682. blockstates: labstmts[;]* ;
  683. labstmts: ('return rexpr +(return #1)) /
  684. (('goto / 'go 'to) id +(go #1)) /
  685. ('if rexpr 'then labstmts blkelse
  686. +(cond (#3 #2) (T #1))) /
  687. rexpr ;
  688. blkelse: 'else labstmts / =T +nil ;
  689. rexprlist: rexpr [;]* ;
  690. lambdastate: 'lambda lamtail ;
  691. lamtail: '( id[,]* ') termin rexpr +(lambda #2 #1) /
  692. termin rexpr +(lambda nil #1) /
  693. id termin rexpr +(lambda (#2) #1) ;
  694. %------ Define statement: (id and value are put onto table
  695. % named DEFNTAB:
  696. definestate: 'define delist +.(cons (quote progn) #1) ;
  697. delist: (id '= rexpr +(put (quote #2) (quote defntab)
  698. (quote #1)))[,]* ;
  699. %------ On or off statement:
  700. onoffstate: ('on +T / 'off +nil) switchlists ;
  701. switchlists: 'defn +(set '!*defn #1) ; PSL Manual 7 February 1983 Parser Tools
  702. section 22.4 page 22.21
  703. timop: ('* +times / '/ +quotient) ;
  704. plusop: ('+ +plus2 / '- +difference) ;
  705. relop: ('< +lessp / '<= +lep / '= +equal /
  706. '>= +gep / '> +greaterp) ;
  707. FIN