home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / RECA.DOC < prev    next >
Encoding:
Text File  |  1986-12-01  |  23.9 KB  |  518 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.           REC -  A Regular Expression Compiler
  13.  
  14.  
  15.  
  16.                  Gerardo Cisneros
  17.  
  18.        Escuela Superior de Ingenieria Mecanica y Electrica
  19.          Instituto Politecnico Nacional
  20.  
  21.             
  22.  
  23.                  and
  24.  
  25.  
  26.  
  27.               Harold V. McIntosh
  28.  
  29.      Departamento de Aplicacion de Microcomputadoras
  30.             Instituto de Ciencias
  31.         Universidad Autonoma de Puebla
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.              Copyright (c) 1985
  47.               Gerardo Cisneros
  48.                H. V. McIntosh
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.             PREFACE
  64.  
  65.     With dropping prices of microcomputers, programming is 
  66. becoming accessible to more people, and software is assuming an 
  67. increasing importance in the total balance of the operation of a 
  68. computer. This has originated much controversy about an author's 
  69. rights to his software, ranging from the idea that the world can be 
  70. held to ransom for a brilliant idea to the suggestion that there 
  71. should be no impediment to any copying whatsoever.
  72.  
  73.     The research reported in this document has been supported by 
  74. public funds (Mexican, Northamerican, Swedish) in a number of 
  75. institutions (Universities, Atomic Energy Commissions, Polytechnic 
  76. Institutes) over a decade or two. Its result has especially been used 
  77. in programming and applied mathematics courses in an attempt to get 
  78. people to learn it and to use it. Accordingly it might be held to 
  79. belong in the public domain.
  80.        
  81.     Most people read scientific literature, as well as any other 
  82. literature, to establish a background. Should they encounter 
  83. something particularly useful, they are expected to acknowledge its 
  84. source, because the resulting fame more than anything is the author's 
  85. compensation for his work. In those rare instances where a resounding 
  86. commercial success has been the sole or a substantial consequence of 
  87. the largely unaltered use of an author's work, it is to be expected 
  88. that he, his associates, and his employer will expect to share in the 
  89. benefits. It is curious that there does not seem to be a 
  90. corresponding willingness to share in the consequences of a bungling 
  91. or even bona fide misapplication of the work or the attendant 
  92. catastrophe, should something go wrong.
  93.  
  94.                 Gainesville, Florida, U.S.A.
  95.                 Puebla, Puebla, Mexico.
  96.  
  97.  
  98.  
  99.             Introduction
  100.  
  101.     REC (Regular Expression Compiler) is the end product of an 
  102. effort begun many years ago at the University of Florida to find an 
  103. aesthetic structure to take the place of the "program feature" in 
  104. McCarthy's LISP. "Operator Predicates" were the solution evolved at 
  105. that time. Later, when they were taken completely out of the context 
  106. of LISP and implemented on a PDP-8 computer at the National 
  107. Autonomous University of Mexico in 1966, the programming language REC 
  108. arose.
  109.  
  110.     For more than a decade thereafter it was used in programming, 
  111. numerical analysis and mathematical logic courses at the National 
  112. Polytechnic Institute, also in Mexico City, acquiring a number of 
  113. versions and giving many people considerable experience in its 
  114. presentation and usage. REC compilers developed at the Polytechnic 
  115. included versions suitable for matrix manipulations, text editing and 
  116. numerical integration of second order differential equations; REC was 
  117. also used there to program hand calculations on the Friden 132 desk 
  118. calculator, one of the first machines to offer an operand stack.  One 
  119. version was used extensively in the administration and data 
  120. processing of the Mexican Nuclear Energy Institute, in conjunction 
  121. with the monitor system of the PDP-10.
  122.  
  123.     In the last five years, and with the advent of 
  124. microcomputers, REC has matured at the Autonomous University of 
  125. Puebla into a very powerful symbolic manipulation language with some 
  126. arithmetic capabilities, which has proved to be very well suited to 
  127. the construction of compilers and operating systems.
  128.  
  129.     REC possesses an extremely simple control structure 
  130. consisting of four symbols: the two parentheses, the colon, and the 
  131. semicolon. Besides these there may be any number of predicates and 
  132. operators (these being a special case of predicates), which are 
  133. responsible for all the work to be done.  This represents an attempt 
  134. to reduce computer programming to its barest essentials, both for 
  135. pedagogical reasons, and in the expectation that it will be a 
  136. manageable structure when it is cast in its simplest terms. The 
  137. resulting language is very concise, not unlike APL or TECO. 
  138.  
  139.     As the allusion to regular expressions implies, there is also 
  140. the expectation that the language is intimately related to the theory 
  141. of computations. In effect, REC derives its appeal from the fact that 
  142. computers can be regarded reasonably well as Turing machines with 
  143. very elaborate built-in shortcuts to eliminate the grotesque 
  144. inefficiency of manipulating individual bits on a single linear tape. 
  145. A Turing machine itself consists of a finite-state machine acting as 
  146. the control of a tape memory; finite state machines in turn are 
  147. conveniently described by regular expressions.  The REC notation 
  148. simply allows one to write regular expressions in a manner somewhat 
  149. more amenable to programming the Turing machine which they control.  
  150. If one does not wish to think so strictly in terms of Turing 
  151. machines, REC expressions still provide a means of defining the flow 
  152. of control in a program which is quite convenient for many 
  153. applications.
  154.  
  155.     REC defines only a control structure. It takes some getting 
  156. used to, but coincides well with contemporary ideas about "structured 
  157. programming."  Some particularly useful REC languages come into being 
  158. when specific sets of operators and predicates are chosen. One 
  159. selection gives the symbol-manipulation language REC/MARKOV. People 
  160. who are familiar with DEC's PDP-10 will note a strong resemblance to 
  161. TECO, although REC actually contemporizes with or even antedates 
  162. TECO. One of the most important differences between these two 
  163. languages is that TECO lacks REC's orderly control structure.
  164.  
  165.     The REC/MARKOV processor is remarkably compact, fitting into 
  166. about 5Kbytes of memory in many machines (7.5Kbytes when floating 
  167. point arithmetic operations are included), exclusive of working 
  168. storage. In the course of this book we shall analyze the operation of 
  169. the microcomputer implementation of REC/MARKOV mentioned earlier; we 
  170. shall call it simply REC throughout the remainder of the book. Our 
  171. principal objective will be to introduce a symbol manipulation 
  172. programming language sufficiently powerful that it can handle the 
  173. compilation of REC languages in a wide variety of different 
  174. computers. At the same time one will have a language useful for text 
  175. editing, assembly including macro assembly and cross assemblers, 
  176. compiling, and even file maintenance and data analysis.  To do all 
  177. this will also entail some discussion of programming languages and 
  178. computer architecture, but not to the extent that no previous 
  179. familiarity with such things is needed.
  180.  
  181.         Chapter 1.  The Structure of REC
  182.  
  183.     In order to define a REC expression seven characters will be 
  184. used as metasymbols, that is, symbols which would not appear 
  185. explicitly in an actual instance of the object being defined and 
  186. whose significance as metasymbols is limited to the definition in 
  187. which they are used.  These characters are [, ], E, P, |, * and =. 
  188. Using the language of regular expressions and establishing the 
  189. convention that concatenation is implicit, that alternatives are 
  190. separated by |, that repetition - even zero times - is denoted by *, 
  191. that = means "is defined as", and using square brackets rather than 
  192. parentheses as symbols of aggrupation, a REC expression E is defined 
  193. recursively by
  194.  
  195.         E = ( [[P | E]*[: | ;]*]* [P | E]* ) 
  196.  
  197. where the enclosing parentheses are essential and P denotes a 
  198. predicate. In more common terms, a REC expression is a string 
  199. enclosed by balanced parentheses, which consists of a sequence of 
  200. operators, predicates, or further REC expressions separated by 
  201. punctuation consisting of one more colons or semicolons.
  202.  
  203.     Operators and predicates carry out operations, not all of 
  204. them necessarily primitive. They may be coded either in machine 
  205. language or consist of subroutines themselves defined in REC. 
  206. Predicates differ from operators by acquiring either of two truth 
  207. values as a consequence of their operation; operators always have the 
  208. value TRUE.  The difference between operators and predicates makes 
  209. itself felt in the way that predicates can affect the sequence of 
  210. operations which is chosen to execute a program.  A REC expression 
  211. also acquires a truth value as a result of its execution and may be 
  212. thus regarded as a composite predicate.
  213.  
  214.     A REC expression is executed by reading it from left to right 
  215. in sequence.  Operators or predicates are performed in the order in 
  216. which they occur, except that jumps occur after predicates if their 
  217. truth value turns out to be FALSE.  On encountering a right 
  218. parenthesis, the expression terminates with the value FALSE, but if a 
  219. semicolon is encountered, termination results with the value TRUE. 
  220. Colons mean repetition from the opening left parenthesis. Finally we 
  221. have to say what kinds of jumps are caused by predicates whose truth 
  222. value is FALSE.  If there is a colon or semicolon to the right of the 
  223. predicate and on the same parenthesis level, the jump is to the next 
  224. position beyond. If there is none, the jump is beyond the terminating 
  225. right parenthesis, resulting in the value TRUE just as if a semicolon 
  226. had been encountered. It should be mentioned that parentheses within 
  227. parentheses are treated as a single expression, so that all jumps 
  228. originating inside a given level of parentheses refer to locations 
  229. only on the same level and never to locations within subexpressions.
  230.  
  231.     The following figure illustrates the flow of control in REC, 
  232. assuming the only colons, semicolons and parentheses are those 
  233. explicitly shown, and P is any predicate.
  234.  
  235.  
  236.     (     (P     )     :     (     P   ;     )    :   ;     )
  237.  
  238.  
  239.     The structure which we have described allows Boolean 
  240. combinations of predicates. Suppose that P, P1, and P2 are 
  241. predicates. Then
  242.  
  243.     (P)       is not-P,        ()  is always FALSE,
  244.     (P1; P2;)  is (P1 or P2),    (;) is always TRUE,
  245.     (P1 P2;)   is (P1 and P2).
  246.  
  247.     Some care has to be taken with the Boolean interpretation 
  248. because the combinations which were described do not strictly follow 
  249. the laws of Boolean algebra. The principal discrepancy is the failure 
  250. of the commutative law, because the order in which the two predicates 
  251. are executed might make a difference. One reason for the importance 
  252. of the order might be that an irreversible operation is effected, 
  253. such as initiating an input-output operation, or changing the value 
  254. of a variable, or something similar. Another factor is the fact that 
  255. algorithms are sometimes undefined, either because their arguments 
  256. are inappropriate, or the attempt to follow them out would never 
  257. terminate. By testing first for terminal conditions or for the 
  258. suitability of data, the undefined conditions can be avoided.
  259.  
  260.     Subroutines are defined in REC by grouping them together with 
  261. a main program within a pair of braces; any printing ASCII character 
  262. other than the space, atsign (@) or right brace may be assigned as a 
  263. subroutine name.  The structure of a subroutine group is as follows:
  264.  
  265.         { E1 n1 E2 n2   ...  Ek nk Em }
  266.  
  267. where E1, E2, ... Ek and Em are REC expressions as defined above; n1, 
  268. n2, ... nk are the ASCII characters assigned as names to E1, E2, ... 
  269. Ek, respectively, and hence declaring them to be subroutines with the 
  270. given names, and Em is the main program, with which execution of the 
  271. braced group starts.  Since a program within braces also has a truth 
  272. value (that of its main program), such a structure may also be given 
  273. a name within an outer level of braces, or it may appear as a 
  274. composite predicate within another expression.  Subroutines are 
  275. recursive and definitions that become active when entering a pair of 
  276. braces replace definitions of the same name which were active in the 
  277. previous level; on exit from a braced expression all of its 
  278. definitions become inactive and any definitions which were replaced 
  279. on entry become active again.  Calls are effected by the predicate 
  280. @x, which produces a call to subroutine x and whose truth value is 
  281. that of the expression represented by x.
  282.  
  283.     All of the above is illustrated in the following example, in 
  284. which ellipses (...) are used to denote features not essential to our 
  285. discussion and the numbers on the left are for reference only:
  286.  
  287.     1    {   {    ( ... @A ... ) A
  288.     2        ( ... @C ... @D ... ) B
  289.     3        ( ... @A ... )   } C
  290.     4        ( ... ) A
  291.     5        ( ... ) D
  292.     6        ( ... @A ...
  293.     7        {( ... ) A   ( ... @A ... ) }
  294.     8        ... @C ... @A ... )    }
  295.  
  296.  
  297.     Assume the only subroutine definitions are the ones shown 
  298. explicitly in the example.  The main program is defined in lines 6 
  299. through 8; its level of braces (which runs through the whole example) 
  300. contains also definitions for subroutines C (lines 1-3), A (line 4) 
  301. and D (line 5). @A in lines 6 and 8 are calls to subroutine A of line 
  302. 4, while @A in lines 1 and 3 refer to subroutine A defined in line 1. 
  303. The call @A appearing in line 7 calls subroutine A of the same line. 
  304. Due to the mechanism whereby upon entrance to a brace level previous 
  305. definitions of the names defined in that level are saved and the new 
  306. definitions become active (with reversal of the process on exit), it 
  307. will be noticed that in our example the definition of subroutines D 
  308. (line 5) and C (lines 1-3) remain active throughout the entire 
  309. program while the definition of A depends on which pair of braces is 
  310. currently executing.  B is only defined within the brace pair 
  311. defining C (lines 1-3) and reference to B from any of the programs 
  312. defined in lines 4-8 would cause immediate termination of execution 
  313. and return to the computer's operating system.
  314.  
  315.     Finally, both square brackets, the space and the comma have 
  316. been reserved for readability and documentation purposes.  Brackets 
  317. are used to delimit comments; these may be nested, so that it is 
  318. possible to inhibit compilation of a program or portion of a program 
  319. containing comments by enclosing it with a pair of brackets.  
  320. Comments may appear anywhere except between an expression defining a 
  321. subroutine and its name and between the main program of a group and 
  322. its closing right brace.  No operations have been assigned to either 
  323. the space or the comma, so they may be freely used to improve the 
  324. readability of programs.
  325.  
  326.  
  327.     Chapter 2.  Operator Arguments and Data Structures
  328.  
  329.  
  330.     Insofar as REC is defined as a language exclusively in terms 
  331. of its control structure, leaving the selection of operators and 
  332. predicates to be chosen as best fits a given problem or application 
  333. area, there can be differing versions of REC, such as one dedicated 
  334. to arithmetic, or another to text editing, or even monitor systems 
  335. whose primitive operations are fairly complicated file handling 
  336. subroutines.
  337.  
  338.     However, there are still general aspects of operators, such 
  339. as the way that they pass data to one another, or how they are formed 
  340. into subroutines, which remain the same from one version of REC to 
  341. another.  No doubt it is desirable to establish norms and a 
  342. vocabulary for these aspects of the language just as was done for the 
  343. control structure.  For example, the problem of data transmission can 
  344. be considered.
  345.  
  346.     There are about three ways of passing information from one 
  347. part of a program to another - at least three that have found a 
  348. noticeably popular acceptance. These are: by means of a calling 
  349. sequence, by depositing the information in known locations, or by 
  350. means of a pushdown list.
  351.  
  352.     Calling sequences are associated with subroutine usage; one 
  353. might write
  354.  
  355.             CALL SUBROUTINE
  356.             (data # 1)
  357.             ( ... )
  358.             (data # n)
  359.         RETURN: ...
  360.  
  361.     Here, it is the program counter which localizes the area in 
  362. which data is stored. From the point of view of writing a program, 
  363. especially in assembly language, the registers following the 
  364. subroutine call are a convenient place to locate data, the more so if 
  365. the computer being used does not provide an automatic pushdown stack. 
  366. This is particularly so if the data is constant from one subroutine 
  367. call to another, but differs from one calling location to another.
  368.  
  369.     A second device for data transmission is to store information 
  370. in a known location which is accessible to all the subroutines and to 
  371. the main program.  A typical example of this type of communication is 
  372. through COMMON or labelled COMMON in FORTRAN programs. The method is 
  373. particularly useful when the data is never changed or only 
  374. infrequently modified. Even though this is its preferred use, it is 
  375. not a real restriction because programs can always store data in 
  376. COMMON just before a subroutine jump. Speed can be gained by thereby 
  377. bypassing the way in which FORTRAN copies and restores the arguments 
  378. in subroutine calling sequences. Nevertheless the use of fixed 
  379. locations is most likely when the data is constant, or it is so 
  380. widely used throughout the program that it would be redundant to 
  381. incorporate it in a large number of calling sequences.
  382.  
  383.     The third technique of data communication is the use of a 
  384. stack pointer which locates the head of a structure known as a 
  385. pushdown list. This is the preferred method of handling temporary 
  386. storage of the type which is required in such applications as the 
  387. execution of algebraic formulas. It is nearly unavoidable whenever 
  388. recursive programming is involved.
  389.  
  390.     The idea is to maintain a pointer to an array of temporary 
  391. storage. As the arguments of a function or subroutine are evaluated 
  392. they are deposited in the array and the pointer advanced to be ready 
  393. for the next result.  When all of the arguments are present, the 
  394. calculations are made and the pointer moves backward, effectively 
  395. erasing the arguments. Then the result of the calculation is left in 
  396. the last position on the array, in place of the first argument if 
  397. threre was one, and the process continues.
  398.  
  399.     Since each subroutine knows how many arguments it needs and 
  400. how many values it is going to deposit, the maintenance of the 
  401. pointer and the pushdown list is quite automatic. Errors can occur 
  402. through setting up an incorrect number or arguments, and it is always 
  403. possible, especially in a very deep recursion, that the pushdown list 
  404. may grow beyond available space.  Some checking should always be done 
  405. to prevent the pointer from straying out of bounds.
  406.  
  407.     Primitive functions which have several arguments and which 
  408. are coded in machine language can easily locate their arguments 
  409. through a displacement relative to the stack pointer, but it is 
  410. sometimes convenient to have a way of directing a component of a 
  411. composite subroutine to the nth argument. A much more systematic way 
  412. to make these arguments accessible is to give them names, and set 
  413. aside a special storage area for them. This leads to the idea of a 
  414. variable, even though its name may be nothing more than a serial 
  415. number.
  416.  
  417.     Two activities concern the variables. First, its value has to 
  418. be transferred to the pushdown list when it occurs in a program so 
  419. that it will be available for use as an argument. Second, the value 
  420. has to be transferred from the pushdown list to the special storage 
  421. area so as to define the variable on entry into the subroutine.
  422.  
  423.     Two complications can occur, both aggravated when recursive 
  424. subroutines are allowed. One is that the same names may be in use in 
  425. various parts of the program, particularly when this happens both in 
  426. the subroutine and in the main program which called it. Then it is 
  427. necessary that previous values be set aside - not destroyed - when 
  428. the subroutine is entered, and that they be replaced upon exit.  Then 
  429. all will work smoothly and the conflict in variable names will not be 
  430. noticed.
  431.  
  432.     The other complication which can occur is the one of free 
  433. variables, wherein we might not only want to refer to the kth 
  434. argument of a subroutine, but as well to the mth argument of a higher 
  435. level subroutine which called it. If no recursion is involved and one 
  436. knows how many arguments each subroutine had, the position of any 
  437. given argument on the pushdown list can be calculated; this is not 
  438. possible when recursive subroutine chains are permitted.
  439.  
  440.     Rather, it is much more convenient to use the device of named 
  441. variables and copies of the arguments rather than working with 
  442. offsets from the stack pointer even though under restricted 
  443. circumstances the latter is more economical.
  444.  
  445.     Some argumentation also surrounds the decision as to whether 
  446. an operator ought to erase its own arguments, or whether the erasure 
  447. ought to be done by a separate operator. The argument in favor of 
  448. automatic erasure is that the pushdown list is then self-balancing, 
  449. while the argument against stems from the possibility of the iterated 
  450. use of an operator.  In that case it would seem futile to keep 
  451. loading and erasing the same argument over and over again.
  452.  
  453.     Finally we might want to get the nth argument directly off 
  454. the pushdown list without having to fetch it up to the top. This 
  455. would facilitate the definition of subroutines with an arbitrary 
  456. number of arguments by allowing them to be used directly without the 
  457. intermediate step of storing them as variables and fetching them out 
  458. again later. However this direct access will not work if some part of 
  459. the subroutine itself involved a recursive process, and thus direct 
  460. access would not be usable in general.
  461.  
  462.     As a practical matter pushdown underflow and overflow have to 
  463. be detected and acted upon - probably resulting in a fatal error 
  464. message.
  465.  
  466.     Even though the definition of techniques of argument 
  467. communication does not form part of the official specification of 
  468. REC, most varieties of REC will naturally require data handling 
  469. capabilities.  The current version of REC has
  470.  
  471.     - An array, together with a pointer and limit
  472.       registers, which can be used as a pushdown
  473.       list.
  474.  
  475.     - A space which can be used to store the
  476.       values or addresses of variables.
  477.  
  478.     - A workspace into which text may be inserted and
  479.       in which searches, deletions and substitutions may
  480.       be carried out.
  481.  
  482.     Any other version of REC would be expected to have at
  483. least the first two data structures.
  484.  
  485.     In summary, the three data transference techniques and the 
  486. error detection aspect affect current REC programming in the 
  487. following way:
  488.  
  489.       - A double push down list is used systematically; "double"
  490.     referring to the fact that both ends of the (finite) list
  491.     are available for argument storage.
  492.  
  493.       - Constants are introduced into a program through a
  494.     subroutine which expects to find the constant as part of its
  495.     calling sequence. Parameters may also be introduced into a
  496.     subroutine through a calling sequence, but otherwise calling
  497.     sequences are not much used. More elaborate compilers
  498.     may even set aside variable space rather than calling sequence
  499.     space for constants, referring to the constants only through 
  500.     pointers.
  501.  
  502.       - Variables or registers which are of central importance
  503.     to a program are set aside, and manipulated through special
  504.     operators.  This takes the form of  a workspace for text
  505.     manipulation and a set of locations in which values or pointers
  506.     to values may be stored.  Otherwise there is not much data
  507.     communication through fixed program areas.
  508.  
  509.       - In order to conserve space, error detection and handling is 
  510.     kept to a minimum.  Pushdown list, workspace and compile area 
  511.     overflows cause a message to be issued and immediate 
  512.     termination of execution.  So does an attempt to read a 
  513.     source file or a memory buffer beyond its end during 
  514.     compilation (usually due to an excess of opening braces or 
  515.     parentheses).  Other errors are noted in a location reserved 
  516.     for this purpose; the question mark '?' is the predicate the 
  517.     programmer may use to find out whether an error has occurred.
  518.