bovine.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. ;;; semantic/bovine.el --- LL Parser/Analyzer core.
  2. ;; Copyright (C) 1999-2004, 2006-2007, 2009-2012
  3. ;; Free Software Foundation, Inc.
  4. ;; Author: Eric M. Ludlam <eric@siege-engine.com>
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;
  18. ;; Semantic 1.x uses an LL parser named the "bovinator". This parser
  19. ;; had several conveniences in it which made for parsing tags out of
  20. ;; languages with list characters easy. This parser lives on as one
  21. ;; of many available parsers for semantic the tool.
  22. ;;
  23. ;; This parser should be used when the language is simple, such as
  24. ;; makefiles or other data-declarative languages.
  25. ;;; Code:
  26. (require 'semantic)
  27. (declare-function semantic-create-bovine-debug-error-frame
  28. "semantic/bovine/debug")
  29. (declare-function semantic-bovine-debug-create-frame
  30. "semantic/bovine/debug")
  31. (declare-function semantic-debug-break "semantic/debug")
  32. ;;; Variables
  33. ;;
  34. (defvar semantic-bovinate-nonterminal-check-obarray nil
  35. "Obarray of streams already parsed for nonterminal symbols.
  36. Use this to detect infinite recursion during a parse.")
  37. (make-variable-buffer-local 'semantic-bovinate-nonterminal-check-obarray)
  38. ;; These are functions that can be called from within a bovine table.
  39. ;; Most of these have code auto-generated from other construct in the
  40. ;; bovine input grammar.
  41. (defmacro semantic-lambda (&rest return-val)
  42. "Create a lambda expression to return a list including RETURN-VAL.
  43. The return list is a lambda expression to be used in a bovine table."
  44. `(lambda (vals start end)
  45. (append ,@return-val (list start end))))
  46. ;;; Semantic Bovination
  47. ;;
  48. ;; Take a semantic token stream, and convert it using the bovinator.
  49. ;; The bovinator takes a state table, and converts the token stream
  50. ;; into a new semantic stream defined by the bovination table.
  51. ;;
  52. (defsubst semantic-bovinate-symbol-nonterminal-p (sym table)
  53. "Return non-nil if SYM is in TABLE, indicating it is NONTERMINAL."
  54. ;; sym is always a sym, so assq should be ok.
  55. (if (assq sym table) t nil))
  56. (defmacro semantic-bovinate-nonterminal-db-nt ()
  57. "Return the current nonterminal symbol.
  58. Part of the grammar source debugger. Depends on the existing
  59. environment of `semantic-bovinate-stream'."
  60. `(if nt-stack
  61. (car (aref (car nt-stack) 2))
  62. nonterminal))
  63. (defun semantic-bovinate-nonterminal-check (stream nonterminal)
  64. "Check if STREAM not already parsed for NONTERMINAL.
  65. If so abort because an infinite recursive parse is suspected."
  66. (or (vectorp semantic-bovinate-nonterminal-check-obarray)
  67. (setq semantic-bovinate-nonterminal-check-obarray
  68. (make-vector 13 nil)))
  69. (let* ((nt (symbol-name nonterminal))
  70. (vs (symbol-value
  71. (intern-soft
  72. nt semantic-bovinate-nonterminal-check-obarray))))
  73. (if (memq stream vs)
  74. ;; Always enter debugger to see the backtrace
  75. (let ((debug-on-signal t)
  76. (debug-on-error t))
  77. (setq semantic-bovinate-nonterminal-check-obarray nil)
  78. (error "Infinite recursive parse suspected on %s" nt))
  79. (set (intern nt semantic-bovinate-nonterminal-check-obarray)
  80. (cons stream vs)))))
  81. ;;;###autoload
  82. (defun semantic-bovinate-stream (stream &optional nonterminal)
  83. "Bovinate STREAM, starting at the first NONTERMINAL rule.
  84. Use `bovine-toplevel' if NONTERMINAL is not provided.
  85. This is the core routine for converting a stream into a table.
  86. Return the list (STREAM SEMANTIC-STREAM) where STREAM are those
  87. elements of STREAM that have not been used. SEMANTIC-STREAM is the
  88. list of semantic tokens found."
  89. (if (not nonterminal)
  90. (setq nonterminal 'bovine-toplevel))
  91. ;; Try to detect infinite recursive parse when doing a full reparse.
  92. (or semantic--buffer-cache
  93. (semantic-bovinate-nonterminal-check stream nonterminal))
  94. (let* ((table semantic--parse-table)
  95. (matchlist (cdr (assq nonterminal table)))
  96. (starting-stream stream)
  97. (nt-loop t) ;non-terminal loop condition
  98. nt-popup ;non-nil if return from nt recursion
  99. nt-stack ;non-terminal recursion stack
  100. s ;Temp Stream Tracker
  101. lse ;Local Semantic Element
  102. lte ;Local matchlist element
  103. tev ;Matchlist entry values from buffer
  104. val ;Value found in buffer.
  105. cvl ;collected values list.
  106. out ;Output
  107. end ;End of match
  108. result
  109. )
  110. (condition-case debug-condition
  111. (while nt-loop
  112. (catch 'push-non-terminal
  113. (setq nt-popup nil
  114. end (semantic-lex-token-end (car stream)))
  115. (while (or nt-loop nt-popup)
  116. (setq nt-loop nil
  117. out nil)
  118. (while (or nt-popup matchlist)
  119. (if nt-popup
  120. ;; End of a non-terminal recursion
  121. (setq nt-popup nil)
  122. ;; New matching process
  123. (setq s stream ;init s from stream.
  124. cvl nil ;re-init the collected value list.
  125. lte (car matchlist) ;Get the local matchlist entry.
  126. )
  127. (if (or (byte-code-function-p (car lte))
  128. (listp (car lte)))
  129. ;; In this case, we have an EMPTY match! Make
  130. ;; stuff up.
  131. (setq cvl (list nil))))
  132. (while (and lte
  133. (not (byte-code-function-p (car lte)))
  134. (not (listp (car lte))))
  135. ;; GRAMMAR SOURCE DEBUGGING!
  136. (if (and (boundp 'semantic-debug-enabled)
  137. semantic-debug-enabled)
  138. (let* ((db-nt (semantic-bovinate-nonterminal-db-nt))
  139. (db-ml (cdr (assq db-nt table)))
  140. (db-mlen (length db-ml))
  141. (db-midx (- db-mlen (length matchlist)))
  142. (db-tlen (length (nth db-midx db-ml)))
  143. (db-tidx (- db-tlen (length lte)))
  144. (frame (progn
  145. (require 'semantic/bovine/debug)
  146. (semantic-bovine-debug-create-frame
  147. db-nt db-midx db-tidx cvl (car s))))
  148. (cmd (semantic-debug-break frame))
  149. )
  150. (cond ((eq 'fail cmd) (setq lte '(trash 0 . 0)))
  151. ((eq 'quit cmd) (signal 'quit "Abort"))
  152. ((eq 'abort cmd) (error "Abort"))
  153. ;; support more commands here.
  154. )))
  155. ;; END GRAMMAR SOURCE DEBUGGING!
  156. (cond
  157. ;; We have a nonterminal symbol. Recurse inline.
  158. ((setq nt-loop (assq (car lte) table))
  159. (setq
  160. ;; push state into the nt-stack
  161. nt-stack (cons (vector matchlist cvl lte stream end
  162. )
  163. nt-stack)
  164. ;; new non-terminal matchlist
  165. matchlist (cdr nt-loop)
  166. ;; new non-terminal stream
  167. stream s)
  168. (throw 'push-non-terminal t)
  169. )
  170. ;; Default case
  171. (t
  172. (setq lse (car s) ;Get the local stream element
  173. s (cdr s)) ;update stream.
  174. ;; Do the compare
  175. (if (eq (car lte) (semantic-lex-token-class lse)) ;syntactic match
  176. (let ((valdot (semantic-lex-token-bounds lse)))
  177. (setq val (semantic-lex-token-text lse))
  178. (setq lte (cdr lte))
  179. (if (stringp (car lte))
  180. (progn
  181. (setq tev (car lte)
  182. lte (cdr lte))
  183. (if (string-match tev val)
  184. (setq cvl (cons
  185. (if (memq (semantic-lex-token-class lse)
  186. '(comment semantic-list))
  187. valdot val)
  188. cvl)) ;append this value
  189. (setq lte nil cvl nil))) ;clear the entry (exit)
  190. (setq cvl (cons
  191. (if (memq (semantic-lex-token-class lse)
  192. '(comment semantic-list))
  193. valdot val) cvl))) ;append unchecked value.
  194. (setq end (semantic-lex-token-end lse))
  195. )
  196. (setq lte nil cvl nil)) ;No more matches, exit
  197. )))
  198. (if (not cvl) ;lte=nil; there was no match.
  199. (setq matchlist (cdr matchlist)) ;Move to next matchlist entry
  200. (let ((start (semantic-lex-token-start (car stream))))
  201. (setq out (cond
  202. ((car lte)
  203. (funcall (car lte) ;call matchlist fn on values
  204. (nreverse cvl) start end))
  205. ((and (= (length cvl) 1)
  206. (listp (car cvl))
  207. (not (numberp (car (car cvl)))))
  208. (append (car cvl) (list start end)))
  209. (t
  210. ;;(append (nreverse cvl) (list start end))))
  211. ;; MAYBE THE FOLLOWING NEEDS LESS CONS
  212. ;; CELLS THAN THE ABOVE?
  213. (nreverse (cons end (cons start cvl)))))
  214. matchlist nil) ;;generate exit condition
  215. (if (not end)
  216. (setq out nil)))
  217. ;; Nothing?
  218. ))
  219. (setq result
  220. (if (eq s starting-stream)
  221. (list (cdr s) nil)
  222. (list s out)))
  223. (if nt-stack
  224. ;; pop previous state from the nt-stack
  225. (let ((state (car nt-stack)))
  226. (setq nt-popup t
  227. ;; pop actual parser state
  228. matchlist (aref state 0)
  229. cvl (aref state 1)
  230. lte (aref state 2)
  231. stream (aref state 3)
  232. end (aref state 4)
  233. ;; update the stack
  234. nt-stack (cdr nt-stack))
  235. (if out
  236. (let ((len (length out))
  237. (strip (nreverse (cdr (cdr (reverse out))))))
  238. (setq end (nth (1- len) out) ;reset end to the end of exp
  239. cvl (cons strip cvl) ;prepend value of exp
  240. lte (cdr lte)) ;update the local table entry
  241. )
  242. ;; No value means that we need to terminate this
  243. ;; match.
  244. (setq lte nil cvl nil)) ;No match, exit
  245. )))))
  246. (error
  247. ;; On error just move forward the stream of lexical tokens
  248. (setq result (list (cdr starting-stream) nil))
  249. (when (and (boundp 'semantic-debug-enabled)
  250. semantic-debug-enabled)
  251. (require 'semantic/bovine/debug)
  252. (let ((frame (semantic-create-bovine-debug-error-frame
  253. debug-condition)))
  254. (semantic-debug-break frame)))))
  255. result))
  256. ;; Make it the default parser
  257. ;;;###autoload
  258. (defalias 'semantic-parse-stream-default 'semantic-bovinate-stream)
  259. (provide 'semantic/bovine)
  260. ;; Local variables:
  261. ;; generated-autoload-file: "loaddefs.el"
  262. ;; generated-autoload-load-name: "semantic/bovine"
  263. ;; End:
  264. ;;; semantic/bovine.el ends here