lisp-parser.sl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % Lisp-Parser.SL - NMODE's Lisp parser
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 10 December 1982
  8. % Revised: 18 February 1983
  9. %
  10. % See the document NMODE-PARSING.TXT for a description of the parsing strategy.
  11. %
  12. % 18-Feb-1983 Alan Snyder
  13. % Removed use of "obsolete" #\ names.
  14. % 6-Jan-83 Alan Snyder
  15. % Use LOAD instead of FASLIN to get macros (for portability).
  16. %
  17. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  18. (CompileTime (load objects fast-int fast-strings fast-vectors nmode-attributes))
  19. % Imported variables:
  20. (fluid '(nmode-defun-predicate
  21. nmode-defun-scanner
  22. nmode-current-parser
  23. ))
  24. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  25. (de establish-lisp-parser ()
  26. (setf nmode-defun-predicate #'lisp-current-line-is-defun?)
  27. (setf nmode-defun-scanner #'lisp-scan-past-defun)
  28. (setf nmode-current-parser #'lisp-parse-line)
  29. )
  30. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  31. %
  32. % This file defines the basic primitive used by NMODE to
  33. % analyze Lisp source code. It currently recognizes:
  34. %
  35. % ( and ) as list brackets
  36. % [ and ] as vector brackets
  37. % comments beginning with %
  38. % #/x as character constants
  39. % " ... " as string literals
  40. % !x as a quoted character
  41. % ' ` #' #. , ,@ as prefixes to ( and [
  42. (de lisp-parse-line (str vec)
  43. % Fill Vec[i] to be the attributes of Str[i].
  44. (let* ((previous-attributes -1)
  45. attributes ch is-first
  46. (high (string-upper-bound str))
  47. (in-comment NIL)
  48. (in-string NIL)
  49. (last-was-sharp NIL)
  50. (last-was-sharp-slash NIL)
  51. (last-was-sharp-quote NIL)
  52. (last-was-sharp-dot NIL)
  53. (last-was-quoter NIL)
  54. (last-was-comma NIL)
  55. (last-was-comma-atsign NIL)
  56. (last-prefix-ending-index NIL)
  57. (last-prefix-length NIL)
  58. )
  59. (for (from i 0 high)
  60. (do
  61. (setf ch (string-fetch str i))
  62. % Determine the type attributes of the current character and update
  63. % the parsing state for the next character.
  64. (cond
  65. (in-comment (setf attributes (attributes COMMENT)))
  66. (in-string
  67. (setf attributes (attributes ATOM))
  68. (setf in-string (not (= ch #/")))
  69. )
  70. (last-was-sharp-slash
  71. (setf attributes (attributes ATOM))
  72. (setf last-was-sharp-slash NIL)
  73. )
  74. (last-was-quoter
  75. (setf attributes (attributes ATOM))
  76. (setf last-was-quoter NIL)
  77. )
  78. (t
  79. (setf attributes (lisp-character-attributes ch))
  80. (setf in-comment (= ch #/%))
  81. (setf in-string (= ch #/"))
  82. (setf last-was-sharp-slash (and last-was-sharp (= ch #//)))
  83. (setf last-was-sharp-quote (and last-was-sharp (= ch #/')))
  84. (setf last-was-sharp-dot (and last-was-sharp (= ch #/.)))
  85. (setf last-was-sharp (= ch #/#))
  86. (setf last-was-quoter (= ch #/!))
  87. (setf last-was-comma-atsign (and last-was-comma (= ch #/@)))
  88. (setf last-was-comma (= ch #/,))
  89. (let ((prefix-length
  90. (cond
  91. (last-was-sharp-quote 2)
  92. (last-was-sharp-dot 2)
  93. ((= ch #/') 1)
  94. ((= ch #/`) 1)
  95. (last-was-comma 1)
  96. (last-was-comma-atsign 1) % is 1 because comma is a prefix
  97. (t 0)
  98. )))
  99. (when (> prefix-length 0)
  100. % We just passed a prefix.
  101. % Does it merge with the previous prefix?
  102. (if (and last-prefix-ending-index
  103. (= last-prefix-ending-index (- i prefix-length))
  104. )
  105. (setf last-prefix-length (+ last-prefix-length prefix-length))
  106. % Otherwise
  107. (setf last-prefix-length prefix-length)
  108. )
  109. (setf last-prefix-ending-index i)
  110. ))
  111. ))
  112. % Determine the position attributes:
  113. % LISP is simple: brackets are single characters (except for
  114. % prefixes, which are handled below), atoms are maximal
  115. % contiguous strings of atomic-characters.
  116. (setf is-first (or (= attributes (attributes OPENER))
  117. (= attributes (attributes CLOSER))
  118. (~= attributes previous-attributes)))
  119. (setf previous-attributes attributes)
  120. (cond
  121. % First we test for an open bracket immediately preceded
  122. % by one or more prefixes.
  123. ((and (= attributes (attributes OPENER))
  124. last-prefix-ending-index
  125. (= last-prefix-ending-index (- i 1))
  126. )
  127. (let ((prefix-start (- i last-prefix-length)))
  128. (vector-store vec prefix-start (attributes FIRST PREFIX OPENER))
  129. (lp-set-last vec (- prefix-start 1))
  130. (for (from j (+ prefix-start 1) (- i 1))
  131. (do (vector-store vec j (attributes MIDDLE PREFIX OPENER))))
  132. ))
  133. (is-first
  134. (setf attributes (| attributes (attributes FIRST)))
  135. (lp-set-last vec (- i 1))
  136. )
  137. (t
  138. (setf attributes (| attributes (attributes MIDDLE)))
  139. ))
  140. (vector-store vec i attributes)
  141. ))
  142. (lp-set-last vec high)
  143. ))
  144. (de lisp-character-attributes (ch)
  145. (selectq ch
  146. (NIL (attributes))
  147. ((#/( #/[) (attributes OPENER))
  148. ((#/) #/]) (attributes CLOSER))
  149. ((#\SPACE #\TAB #\LF #\CR) (attributes BLANKS))
  150. (#/% (attributes COMMENT))
  151. (t (attributes ATOM))
  152. ))
  153. (de lp-set-last (vec i)
  154. (if (>= i 0)
  155. (vector-store vec i (& (| (attributes LAST) (vector-fetch vec i))
  156. (~ (attributes MIDDLE))))))
  157. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  158. % Lisp Defun Primitives
  159. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  160. (de lisp-current-line-is-defun? ()
  161. (and (not (current-line-empty?))
  162. (= (current-line-fetch 0) #/()
  163. ))
  164. (de lisp-scan-past-defun ()
  165. % This function should be called with point at the start of a defun.
  166. % It will scan past the end of the defun (not to the beginning of the
  167. % next line, however). If the end of the defun is not found, it returns
  168. % NIL and leaves point unchanged.
  169. (move-forward-form)
  170. )