PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/cedet/semantic/bovine/semantic-bovine.el

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