antlr-mode.el 107 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662
  1. ;;; antlr-mode.el --- major mode for ANTLR grammar files
  2. ;; Copyright (C) 1999-2015 Free Software Foundation, Inc.
  3. ;; Author: Christoph Wedler <Christoph.Wedler@sap.com>
  4. ;; Keywords: languages, ANTLR, code generator
  5. ;; Version: 2.2c
  6. ;; X-URL: http://antlr-mode.sourceforge.net/
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs is free software: you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation, either version 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; The Emacs package ANTLR-Mode provides: syntax highlighting for ANTLR grammar
  20. ;; files, automatic indentation, menus containing rule/token definitions and
  21. ;; supported options and various other things like running ANTLR from within
  22. ;; Emacs.
  23. ;; For details, check <http://antlr-mode.sourceforge.net/> or, if you prefer
  24. ;; the manual style, follow all commands mentioned in the documentation of
  25. ;; `antlr-mode'. ANTLR is a LL(k)-based recognition tool which generates
  26. ;; lexers, parsers and tree transformers in Java, C++ or Sather and can be
  27. ;; found at <http://www.antlr.org/>.
  28. ;; Bug fixes, bug reports, improvements, and suggestions for the newest version
  29. ;; are strongly appreciated.
  30. ;; To-do/Wish-list:
  31. ;;
  32. ;; * Next Version [C-c C-w]. Produce HTML document with syntax highlighted
  33. ;; and hyper-links (using htmlize).
  34. ;; * Next Version [C-c C-u]. Insert/update special comments: each rule lists
  35. ;; all rules which use the current rule. With font-lock update.
  36. ;; * Next Version. Make hiding much more customizable.
  37. ;; * Planned [C-c C-j]. Jump to generated coding.
  38. ;; * Planned. Further support for imenu, i.e., include entries for method
  39. ;; definitions at beginning of grammar class.
  40. ;; * Planned [C-c C-p]. Pack/unpack rule/subrule & options (one/multi-line).
  41. ;;
  42. ;; * Probably. Show rules/dependencies for ANT like for Makefile (does ANT
  43. ;; support vocabularies and grammar inheritance?), I have to look at
  44. ;; jde-ant.el: http://jakarta.apache.org/ant/manual/OptionalTasks/antlr.html
  45. ;; * Probably. Make `indent-region' faster, especially in actions. ELP
  46. ;; profiling in a class init action shows half the time is spent in
  47. ;; `antlr-next-rule', the other half in `c-guess-basic-syntax'.
  48. ;; * Unlikely. Sather as generated language with syntax highlighting etc/.
  49. ;; Questions/problems: is sather-mode.el the standard mode for sather, is it
  50. ;; still supported, what is its relationship to eiffel3.el? Requirement:
  51. ;; this mode must not depend on a Sather mode.
  52. ;; * Unlikely. Faster syntax highlighting: sectionize the buffer into Antlr
  53. ;; and action code and run special highlighting functions on these regions.
  54. ;; Problems: code size, this mode would depend on font-lock internals.
  55. ;;; Installation:
  56. ;; This file requires Emacs-20.3, XEmacs-20.4 or higher and package cc-mode.
  57. ;; If antlr-mode is not part of your distribution, put this file into your
  58. ;; load-path and the following into your init file:
  59. ;; (autoload 'antlr-mode "antlr-mode" nil t)
  60. ;; (setq auto-mode-alist (cons '("\\.g\\'" . antlr-mode) auto-mode-alist))
  61. ;; (add-hook 'speedbar-load-hook ; would be too late in antlr-mode.el
  62. ;; (lambda () (speedbar-add-supported-extension ".g")))
  63. ;; I strongly recommend to use font-lock with a support mode like fast-lock,
  64. ;; lazy-lock or better jit-lock (Emacs-21.1+) / lazy-shot (XEmacs).
  65. ;; To customize, use menu item "Antlr" -> "Customize Antlr".
  66. ;;; Code:
  67. (eval-when-compile
  68. (require 'cl))
  69. (require 'easymenu)
  70. (require 'cc-mode)
  71. ;; Just to get the rid of the byte compiler warning. The code for
  72. ;; this function and its friends are too complex for their own good.
  73. (declare-function cond-emacs-xemacs-macfn "antlr-mode" (args &optional msg))
  74. ;; General Emacs/XEmacs-compatibility compile-time macros
  75. (eval-when-compile
  76. (defmacro cond-emacs-xemacs (&rest args)
  77. (cond-emacs-xemacs-macfn
  78. args "`cond-emacs-xemacs' must return exactly one element"))
  79. (defun cond-emacs-xemacs-macfn (args &optional msg)
  80. (if (atom args) args
  81. (and (eq (car args) :@) (null msg) ; (:@ ...spliced...)
  82. (setq args (cdr args)
  83. msg "(:@ ....) must return exactly one element"))
  84. (let ((ignore (if (featurep 'xemacs) :EMACS :XEMACS))
  85. (mode :BOTH) code)
  86. (while (consp args)
  87. (if (memq (car args) '(:EMACS :XEMACS :BOTH)) (setq mode (pop args)))
  88. (if (atom args)
  89. (or args (error "Used selector %s without elements" mode))
  90. (or (eq ignore mode)
  91. (push (cond-emacs-xemacs-macfn (car args)) code))
  92. (pop args)))
  93. (cond (msg (if (or args (cdr code)) (error msg) (car code)))
  94. ((or (null args) (eq ignore mode)) (nreverse code))
  95. (t (nconc (nreverse code) args))))))
  96. ;; Emacs/XEmacs-compatibility `defun': remove interactive "_" for Emacs, use
  97. ;; existing functions when they are `fboundp', provide shortcuts if they are
  98. ;; known to be defined in a specific Emacs branch (for short .elc)
  99. (defmacro defunx (name arglist &rest definition)
  100. (let ((xemacsp (featurep 'xemacs)) reuses)
  101. (while (memq (car definition)
  102. '(:try :emacs-and-try :xemacs-and-try))
  103. (if (eq (pop definition) (if xemacsp :xemacs-and-try :emacs-and-try))
  104. (setq reuses (car definition)
  105. definition nil)
  106. (push (pop definition) reuses)))
  107. (if (and reuses (symbolp reuses))
  108. `(defalias ',name ',reuses)
  109. (let* ((docstring (if (stringp (car definition)) (pop definition)))
  110. (spec (and (not xemacsp)
  111. (eq (car-safe (car definition)) 'interactive)
  112. (null (cddar definition))
  113. (cadar definition))))
  114. (if (and (stringp spec)
  115. (not (string-equal spec ""))
  116. (eq (aref spec 0) ?_))
  117. (setq definition
  118. (cons (if (string-equal spec "_")
  119. '(interactive)
  120. `(interactive ,(substring spec 1)))
  121. (cdr definition))))
  122. (if (null reuses)
  123. `(defun ,name ,arglist ,docstring
  124. ,@(cond-emacs-xemacs-macfn definition))
  125. ;; no dynamic docstring in this case
  126. `(eval-and-compile ; no warnings in Emacs
  127. (defalias ',name
  128. (cond ,@(mapcar (lambda (func) `((fboundp ',func) ',func))
  129. (nreverse reuses))
  130. (t ,(if definition
  131. `(lambda ,arglist ,docstring
  132. ,@(cond-emacs-xemacs-macfn definition))
  133. 'ignore))))))))))
  134. (defmacro ignore-errors-x (&rest body)
  135. (let ((specials '((scan-sexps . 4) (scan-lists . 5)))
  136. spec nils)
  137. (if (and (featurep 'xemacs)
  138. (null (cdr body)) (consp (car body))
  139. (setq spec (assq (caar body) specials))
  140. (>= (setq nils (- (cdr spec) (length (car body)))) 0))
  141. `(,@(car body) ,@(make-list nils nil) t)
  142. `(ignore-errors ,@body)))))
  143. ;; More compile-time-macros
  144. (eval-when-compile
  145. (defmacro save-buffer-state-x (&rest body) ; similar to EMACS/lazy-lock.el
  146. (let ((modified (with-no-warnings (gensym "save-buffer-state-x-modified-"))))
  147. `(let ((,modified (buffer-modified-p)))
  148. (unwind-protect
  149. (let ((buffer-undo-list t) (inhibit-read-only t)
  150. ,@(unless (featurep 'xemacs)
  151. '((inhibit-point-motion-hooks t) deactivate-mark))
  152. (inhibit-modification-hooks t)
  153. buffer-file-name buffer-file-truename)
  154. ,@body)
  155. (and (not ,modified) (buffer-modified-p)
  156. (set-buffer-modified-p nil)))))))
  157. (put 'save-buffer-state-x 'lisp-indent-function 0)
  158. (defvar outline-level)
  159. (defvar imenu-use-markers)
  160. (defvar imenu-create-index-function)
  161. ;; We cannot use `c-forward-syntactic-ws' directly since it is a macro since
  162. ;; cc-mode-5.30 => antlr-mode compiled with older cc-mode would fail (macro
  163. ;; call) when used with newer cc-mode. Also, antlr-mode compiled with newer
  164. ;; cc-mode would fail (undefined `c-forward-sws') when used with older cc-mode.
  165. ;; Additional to the `defalias' below, we must set `antlr-c-forward-sws' to
  166. ;; `c-forward-syntactic-ws' when `c-forward-sws' is not defined after requiring
  167. ;; cc-mode.
  168. (defalias 'antlr-c-forward-sws 'c-forward-sws)
  169. ;;;;##########################################################################
  170. ;;;; Variables
  171. ;;;;##########################################################################
  172. (defgroup antlr nil
  173. "Major mode for ANTLR grammar files."
  174. :group 'languages
  175. :link '(emacs-commentary-link "antlr-mode.el")
  176. :link '(url-link "http://antlr-mode.sourceforge.net/")
  177. :prefix "antlr-")
  178. (defconst antlr-version "2.2c"
  179. "ANTLR major mode version number.
  180. Check <http://antlr-mode.sourceforge.net/> for the newest.")
  181. ;;;===========================================================================
  182. ;;; Controlling ANTLR's code generator (language option)
  183. ;;;===========================================================================
  184. (defvar antlr-language nil
  185. "Major mode corresponding to ANTLR's \"language\" option.
  186. Set via `antlr-language-alist'. The only useful place to change this
  187. buffer-local variable yourself is in `antlr-mode-hook' or in the \"local
  188. variable list\" near the end of the file, see
  189. `enable-local-variables'.")
  190. (defcustom antlr-language-alist
  191. '((java-mode "Java" nil "\"Java\"" "Java")
  192. (c++-mode "C++" "\"Cpp\"" "Cpp"))
  193. "List of ANTLR's supported languages.
  194. Each element in this list looks like
  195. (MAJOR-MODE MODELINE-STRING OPTION-VALUE...)
  196. MAJOR-MODE, the major mode of the code in the grammar's actions, is the
  197. value of `antlr-language' if the first group in the string matched by
  198. REGEXP in `antlr-language-limit-n-regexp' is one of the OPTION-VALUEs.
  199. An OPTION-VALUE of nil denotes the fallback element. MODELINE-STRING is
  200. also displayed in the mode line next to \"Antlr\"."
  201. :group 'antlr
  202. :type '(repeat (group :value (java-mode "")
  203. (function :tag "Major mode")
  204. (string :tag "Mode line string")
  205. (repeat :tag "ANTLR language option" :inline t
  206. (choice (const :tag "Default" nil)
  207. string )))))
  208. (defcustom antlr-language-limit-n-regexp
  209. '(8192 . "language[ \t]*=[ \t]*\\(\"?[A-Z][A-Za-z_]*\"?\\)")
  210. "Used to set a reasonable value for `antlr-language'.
  211. Looks like \(LIMIT . REGEXP). Search for REGEXP from the beginning of
  212. the buffer to LIMIT and use the first group in the matched string to set
  213. the language according to `antlr-language-alist'."
  214. :group 'antlr
  215. :type '(cons (choice :tag "Limit" (const :tag "No" nil) (integer :value 0))
  216. regexp))
  217. ;;;===========================================================================
  218. ;;; Hide/Unhide, Indent/Tabs
  219. ;;;===========================================================================
  220. (defcustom antlr-action-visibility 3
  221. "Visibility of actions when command `antlr-hide-actions' is used.
  222. If nil, the actions with their surrounding braces are hidden. If a
  223. number, do not hide the braces, only hide the contents if its length is
  224. greater than this number."
  225. :group 'antlr
  226. :type '(choice (const :tag "Completely hidden" nil)
  227. (integer :tag "Hidden if longer than" :value 3)))
  228. (defcustom antlr-indent-comment 'tab
  229. "Non-nil, if the indentation should touch lines in block comments.
  230. If nil, no continuation line of a block comment is changed. If t, they
  231. are changed according to `c-indentation-line'. When not nil and not t,
  232. they are only changed by \\[antlr-indent-command]."
  233. :group 'antlr
  234. :type '(radio (const :tag "No" nil)
  235. (const :tag "Always" t)
  236. (sexp :tag "With TAB" :format "%t" :value tab)))
  237. (defcustom antlr-tab-offset-alist
  238. '((antlr-mode nil 4 nil)
  239. (java-mode "antlr" 4 nil))
  240. "Alist to determine whether to use ANTLR's convention for TABs.
  241. Each element looks like \(MAJOR-MODE REGEXP TAB-WIDTH INDENT-TABS-MODE).
  242. The first element whose MAJOR-MODE is nil or equal to `major-mode' and
  243. whose REGEXP is nil or matches variable `buffer-file-name' is used to
  244. set `tab-width' and `indent-tabs-mode'. This is useful to support both
  245. ANTLR's and Java's indentation styles. Used by `antlr-set-tabs'."
  246. :group 'antlr
  247. :type '(repeat (group :value (antlr-mode nil 8 nil)
  248. (choice (const :tag "All" nil)
  249. (function :tag "Major mode"))
  250. (choice (const :tag "All" nil) regexp)
  251. (integer :tag "Tab width")
  252. (boolean :tag "Indent-tabs-mode"))))
  253. (defcustom antlr-indent-style "java"
  254. "If non-nil, cc-mode indentation style used for `antlr-mode'.
  255. See `c-set-style' and for details, where the most interesting part in
  256. `c-style-alist' is the value of `c-basic-offset'."
  257. :group 'antlr
  258. :type '(choice (const nil) regexp))
  259. (defcustom antlr-indent-item-regexp
  260. "[]}):;|&]" ; & is local ANTLR extension (SGML's and-connector)
  261. "Regexp matching lines which should be indented by one TAB less.
  262. See `antlr-indent-line' and command \\[antlr-indent-command]."
  263. :group 'antlr
  264. :type 'regexp)
  265. (defcustom antlr-indent-at-bol-alist
  266. ;; eval-when-compile not usable with defcustom...
  267. '((java-mode . "\\(package\\|import\\)\\>")
  268. (c++-mode . "#\\(assert\\|cpu\\|define\\|endif\\|el\\(if\\|se\\)\\|i\\(dent\\|f\\(def\\|ndef\\)?\\|mport\\|nclude\\(_next\\)?\\)\\|line\\|machine\\|pragma\\|system\\|un\\(assert\\|def\\)\\|warning\\)\\>"))
  269. "Alist of regexps matching lines are indented at column 0.
  270. Each element in this list looks like (MODE . REGEXP) where MODE is a
  271. function and REGEXP is a regular expression.
  272. If `antlr-language' equals to a MODE, the line starting at the first
  273. non-whitespace is matched by the corresponding REGEXP, and the line is
  274. part of a header action, indent the line at column 0 instead according
  275. to the normal rules of `antlr-indent-line'."
  276. :group 'antlr
  277. :type '(repeat (cons (function :tag "Major mode") regexp)))
  278. ;; adopt indentation to cc-engine
  279. (defvar antlr-disabling-cc-syntactic-symbols
  280. '(statement-block-intro
  281. defun-block-intro topmost-intro statement-case-intro member-init-intro
  282. arglist-intro brace-list-intro knr-argdecl-intro inher-intro
  283. objc-method-intro
  284. block-close defun-close class-close brace-list-close arglist-close
  285. inline-close extern-lang-close namespace-close))
  286. ;;;===========================================================================
  287. ;;; Options: customization
  288. ;;;===========================================================================
  289. (defcustom antlr-options-use-submenus t
  290. "Non-nil, if the major mode menu should include option submenus.
  291. If nil, the menu just includes a command to insert options. Otherwise,
  292. it includes four submenus to insert file/grammar/rule/subrule options."
  293. :group 'antlr
  294. :type 'boolean)
  295. (defcustom antlr-tool-version 20701
  296. "The version number of the Antlr tool.
  297. The value is an integer of the form XYYZZ which stands for vX.YY.ZZ.
  298. This variable is used to warn about non-supported options and to supply
  299. version correct option values when using \\[antlr-insert-option].
  300. Don't use a number smaller than 20600 since the stored history of
  301. Antlr's options starts with v2.06.00, see `antlr-options-alists'. You
  302. can make this variable buffer-local."
  303. :group 'antlr
  304. :type 'integer)
  305. (defcustom antlr-options-auto-colon t
  306. "Non-nil, if `:' is inserted with a rule or subrule options section.
  307. A `:' is only inserted if this value is non-nil, if a rule or subrule
  308. option is inserted with \\[antlr-insert-option], if there was no rule or
  309. subrule options section before, and if a `:' is not already present
  310. after the section, ignoring whitespace, comments and the init action."
  311. :group 'antlr
  312. :type 'boolean)
  313. (defcustom antlr-options-style nil
  314. "List of symbols which determine the style of option values.
  315. If a style symbol is present, the corresponding option value is put into
  316. quotes, i.e., represented as a string, otherwise it is represented as an
  317. identifier.
  318. The only style symbol used in the default value of `antlr-options-alist'
  319. is `language-as-string'. See also `antlr-read-value'."
  320. :group 'antlr
  321. :type '(repeat (symbol :tag "Style symbol")))
  322. (defcustom antlr-options-push-mark t
  323. "Non-nil, if inserting an option should set & push mark.
  324. If nil, never set mark when inserting an option with command
  325. \\[antlr-insert-option]. If t, always set mark via `push-mark'. If a
  326. number, only set mark if point was outside the options area before and
  327. the number of lines between point and the insert position is greater
  328. than this value. Otherwise, only set mark if point was outside the
  329. options area before."
  330. :group 'antlr
  331. :type '(radio (const :tag "No" nil)
  332. (const :tag "Always" t)
  333. (integer :tag "Lines between" :value 10)
  334. (sexp :tag "If outside options" :format "%t" :value outside)))
  335. (defcustom antlr-options-assign-string " = "
  336. "String containing `=' to use between option name and value.
  337. This string is only used if the option to insert did not exist before
  338. or if there was no `=' after it. In other words, the spacing around an
  339. existing `=' won't be changed when changing an option value."
  340. :group 'antlr
  341. :type 'string)
  342. ;;;===========================================================================
  343. ;;; Options: definitions
  344. ;;;===========================================================================
  345. (defvar antlr-options-headings '("file" "grammar" "rule" "subrule")
  346. "Headings for the four different option kinds.
  347. The standard value is (\"file\" \"grammar\" \"rule\" \"subrule\"). See
  348. `antlr-options-alists'")
  349. (defvar antlr-options-alists
  350. '(;; file options ----------------------------------------------------------
  351. (("language" antlr-language-option-extra
  352. (20600 antlr-read-value
  353. "Generated language: " language-as-string
  354. (("Java") ("Cpp") ("HTML") ("Diagnostic")))
  355. (20700 antlr-read-value
  356. "Generated language: " language-as-string
  357. (("Java") ("Cpp") ("HTML") ("Diagnostic") ("Sather"))))
  358. ("mangleLiteralPrefix" nil
  359. (20600 antlr-read-value
  360. "Prefix for literals (default LITERAL_): " t))
  361. ("namespace" antlr-c++-mode-extra
  362. (20700 antlr-read-value
  363. "Wrap generated C++ code in namespace: " t))
  364. ("namespaceStd" antlr-c++-mode-extra
  365. (20701 antlr-read-value
  366. "Replace ANTLR_USE_NAMESPACE(std) by: " t))
  367. ("namespaceAntlr" antlr-c++-mode-extra
  368. (20701 antlr-read-value
  369. "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
  370. ("genHashLines" antlr-c++-mode-extra
  371. (20701 antlr-read-boolean
  372. "Include #line in generated C++ code? "))
  373. )
  374. ;; grammar options --------------------------------------------------------
  375. (("k" nil
  376. (20600 antlr-read-value
  377. "Lookahead depth: "))
  378. ("importVocab" nil
  379. (20600 antlr-read-value
  380. "Import vocabulary: "))
  381. ("exportVocab" nil
  382. (20600 antlr-read-value
  383. "Export vocabulary: "))
  384. ("testLiterals" nil ; lexer only
  385. (20600 antlr-read-boolean
  386. "Test each token against literals table? "))
  387. ("defaultErrorHandler" nil ; not for lexer
  388. (20600 antlr-read-boolean
  389. "Generate default exception handler for each rule? "))
  390. ("codeGenMakeSwitchThreshold" nil
  391. (20600 antlr-read-value
  392. "Min number of alternatives for `switch': "))
  393. ("codeGenBitsetTestThreshold" nil
  394. (20600 antlr-read-value
  395. "Min size of lookahead set for bitset test: "))
  396. ("analyzerDebug" nil
  397. (20600 antlr-read-boolean
  398. "Display debugging info during grammar analysis? "))
  399. ("codeGenDebug" nil
  400. (20600 antlr-read-boolean
  401. "Display debugging info during code generation? "))
  402. ("buildAST" nil ; not for lexer
  403. (20600 antlr-read-boolean
  404. "Use automatic AST construction/transformation? "))
  405. ("ASTLabelType" nil ; not for lexer
  406. (20600 antlr-read-value
  407. "Class of user-defined AST node: " t))
  408. ("charVocabulary" nil ; lexer only
  409. (20600 nil
  410. "Insert character vocabulary"))
  411. ("interactive" nil
  412. (20600 antlr-read-boolean
  413. "Generate interactive lexer/parser? "))
  414. ("caseSensitive" nil ; lexer only
  415. (20600 antlr-read-boolean
  416. "Case significant when matching characters? "))
  417. ("caseSensitiveLiterals" nil ; lexer only
  418. (20600 antlr-read-boolean
  419. "Case significant when testing literals table? "))
  420. ("classHeaderSuffix" nil
  421. (20600 nil
  422. "Additional string for grammar class definition"))
  423. ("filter" nil ; lexer only
  424. (20600 antlr-read-boolean
  425. "Skip rule (the name, true or false): "
  426. antlr-grammar-tokens))
  427. ("namespace" antlr-c++-mode-extra
  428. (20700 antlr-read-value
  429. "Wrap generated C++ code for grammar in namespace: " t))
  430. ("namespaceStd" antlr-c++-mode-extra
  431. (20701 antlr-read-value
  432. "Replace ANTLR_USE_NAMESPACE(std) by: " t))
  433. ("namespaceAntlr" antlr-c++-mode-extra
  434. (20701 antlr-read-value
  435. "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
  436. ("genHashLines" antlr-c++-mode-extra
  437. (20701 antlr-read-boolean
  438. "Include #line in generated C++ code? "))
  439. ;;; ("autoTokenDef" nil ; parser only
  440. ;;; (80000 antlr-read-boolean ; default: true
  441. ;;; "Automatically define referenced token? "))
  442. ;;; ("keywordsMeltTo" nil ; parser only
  443. ;;; (80000 antlr-read-value
  444. ;;; "Change non-matching keywords to token type: "))
  445. )
  446. ;; rule options ----------------------------------------------------------
  447. (("testLiterals" nil ; lexer only
  448. (20600 antlr-read-boolean
  449. "Test this token against literals table? "))
  450. ("defaultErrorHandler" nil ; not for lexer
  451. (20600 antlr-read-boolean
  452. "Generate default exception handler for this rule? "))
  453. ("ignore" nil ; lexer only
  454. (20600 antlr-read-value
  455. "In this rule, ignore tokens of type: " nil
  456. antlr-grammar-tokens))
  457. ("paraphrase" nil ; lexer only
  458. (20600 antlr-read-value
  459. "In messages, replace name of this token by: " t))
  460. )
  461. ;; subrule options -------------------------------------------------------
  462. (("warnWhenFollowAmbig" nil
  463. (20600 antlr-read-boolean
  464. "Display warnings for ambiguities with FOLLOW? "))
  465. ("generateAmbigWarnings" nil
  466. (20600 antlr-read-boolean
  467. "Display warnings for ambiguities? "))
  468. ("greedy" nil
  469. (20700 antlr-read-boolean
  470. "Make this optional/loop subrule greedy? "))
  471. ))
  472. "Definitions for Antlr's options of all four different kinds.
  473. The value looks like \(FILE GRAMMAR RULE SUBRULE) where each FILE,
  474. GRAMMAR, RULE, and SUBRULE is a list of option definitions of the
  475. corresponding kind, i.e., looks like \(OPTION-DEF...).
  476. Each OPTION-DEF looks like \(OPTION-NAME EXTRA-FN VALUE-SPEC...) which
  477. defines a file/grammar/rule/subrule option with name OPTION-NAME. The
  478. OPTION-NAMEs are used for the creation of the \"Insert XXX Option\"
  479. submenus, see `antlr-options-use-submenus', and to allow to insert the
  480. option name with completion when using \\[antlr-insert-option].
  481. If EXTRA-FN is a function, it is called at different phases of the
  482. insertion with arguments \(PHASE OPTION-NAME). PHASE can have the
  483. values `before-input' or `after-insertion', additional phases might be
  484. defined in future versions of this mode. The phase `before-input'
  485. occurs before the user is asked to insert a value. The phase
  486. `after-insertion' occurs after the option value has been inserted.
  487. EXTRA-FN might be called with additional arguments in future versions of
  488. this mode.
  489. Each specification VALUE-SPEC looks like \(VERSION READ-FN ARG...). The
  490. last VALUE-SPEC in an OPTION-DEF whose VERSION is smaller or equal to
  491. `antlr-tool-version' specifies how the user is asked for the value of
  492. the option.
  493. If READ-FN is nil, the only ARG is a string which is printed at the echo
  494. area to guide the user what to insert at point. Otherwise, READ-FN is
  495. called with arguments \(INIT-VALUE ARG...) to get the new value of the
  496. option. INIT-VALUE is the old value of the option or nil.
  497. The standard value contains the following functions as READ-FN:
  498. `antlr-read-value' with ARGs = \(PROMPT AS-STRING TABLE) which reads a
  499. general value, or `antlr-read-boolean' with ARGs = \(PROMPT TABLE) which
  500. reads a boolean value or a member of TABLE. PROMPT is the prompt when
  501. asking for a new value. If non-nil, TABLE is a table for completion or
  502. a function evaluating to such a table. The return value is quoted if
  503. AS-STRING is non-nil and is either t or a symbol which is a member of
  504. `antlr-options-style'.")
  505. ;;;===========================================================================
  506. ;;; Run tool, create Makefile dependencies
  507. ;;;===========================================================================
  508. (defcustom antlr-tool-command "java antlr.Tool"
  509. "Command used in \\[antlr-run-tool] to run the Antlr tool.
  510. This variable should include all options passed to Antlr except the
  511. option \"-glib\" which is automatically suggested if necessary."
  512. :group 'antlr
  513. :type 'string)
  514. (defcustom antlr-ask-about-save t
  515. "If not nil, \\[antlr-run-tool] asks which buffers to save.
  516. Otherwise, it saves all modified buffers before running without asking."
  517. :group 'antlr
  518. :type 'boolean)
  519. (defcustom antlr-makefile-specification
  520. '("\n" ("GENS" "GENS%d" " \\\n\t") "$(ANTLR)")
  521. "Variable to specify the appearance of the generated makefile rules.
  522. This variable influences the output of \\[antlr-show-makefile-rules].
  523. It looks like \(RULE-SEP GEN-VAR-SPEC COMMAND).
  524. RULE-SEP is the string to separate different makefile rules. COMMAND is
  525. a string with the command which runs the Antlr tool, it should include
  526. all options except the option \"-glib\" which is automatically added
  527. if necessary.
  528. If GEN-VAR-SPEC is nil, each target directly consists of a list of
  529. files. If GEN-VAR-SPEC looks like \(GEN-VAR GEN-VAR-FORMAT GEN-SEP), a
  530. Makefile variable is created for each rule target.
  531. Then, GEN-VAR is a string with the name of the variable which contains
  532. the file names of all makefile rules. GEN-VAR-FORMAT is a format string
  533. producing the variable of each target with substitution COUNT/%d where
  534. COUNT starts with 1. GEN-SEP is used to separate long variable values."
  535. :group 'antlr
  536. :type '(list (string :tag "Rule separator")
  537. (choice
  538. (const :tag "Direct targets" nil)
  539. (list :tag "Variables for targets"
  540. (string :tag "Variable for all targets")
  541. (string :tag "Format for each target variable")
  542. (string :tag "Variable separator")))
  543. (string :tag "ANTLR command")))
  544. (defvar antlr-file-formats-alist
  545. '((java-mode ("%sTokenTypes.java") ("%s.java"))
  546. (c++-mode ("%sTokenTypes.hpp") ("%s.cpp" "%s.hpp")))
  547. "Language dependent formats which specify generated files.
  548. Each element in this list looks looks like
  549. (MAJOR-MODE (VOCAB-FILE-FORMAT...) (CLASS-FILE-FORMAT...)).
  550. The element whose MAJOR-MODE is equal to `antlr-language' is used to
  551. specify the generated files which are language dependent. See variable
  552. `antlr-special-file-formats' for language independent files.
  553. VOCAB-FILE-FORMAT is a format string, it specifies with substitution
  554. VOCAB/%s the generated file for each export vocabulary VOCAB.
  555. CLASS-FILE-FORMAT is a format string, it specifies with substitution
  556. CLASS/%s the generated file for each grammar class CLASS.")
  557. (defvar antlr-special-file-formats '("%sTokenTypes.txt" "expanded%s.g")
  558. "Language independent formats which specify generated files.
  559. The value looks like \(VOCAB-FILE-FORMAT EXPANDED-GRAMMAR-FORMAT).
  560. VOCAB-FILE-FORMAT is a format string, it specifies with substitution
  561. VOCAB/%s the generated or input file for each export or import
  562. vocabulary VOCAB, respectively. EXPANDED-GRAMMAR-FORMAT is a format
  563. string, it specifies with substitution GRAMMAR/%s the constructed
  564. grammar file if the file GRAMMAR.g contains a grammar class which
  565. extends a class other than \"Lexer\", \"Parser\" or \"TreeParser\".
  566. See variable `antlr-file-formats-alist' for language dependent
  567. formats.")
  568. (defvar antlr-unknown-file-formats '("?%s?.g" "?%s?")
  569. "Formats which specify the names of unknown files.
  570. The value looks like \(SUPER-GRAMMAR-FILE-FORMAT SUPER-EVOCAB-FORMAT).
  571. SUPER-GRAMMAR-FORMAT is a format string, it specifies with substitution
  572. SUPER/%s the name of a grammar file for Antlr's option \"-glib\" if no
  573. grammar file in the current directory defines the class SUPER or if it
  574. is defined more than once. SUPER-EVOCAB-FORMAT is a format string, it
  575. specifies with substitution SUPER/%s the name for the export vocabulary
  576. of above mentioned class SUPER.")
  577. (defvar antlr-help-unknown-file-text
  578. "## The following rules contain filenames of the form
  579. ## \"?SUPERCLASS?.g\" (and \"?SUPERCLASS?TokenTypes.txt\")
  580. ## where SUPERCLASS is not found to be defined in any grammar file of
  581. ## the current directory or is defined more than once. Please replace
  582. ## these filenames by the grammar files (and their exportVocab).\n\n"
  583. "String indicating the existence of unknown files in the Makefile.
  584. See \\[antlr-show-makefile-rules] and `antlr-unknown-file-formats'.")
  585. (defvar antlr-help-rules-intro
  586. "The following Makefile rules define the dependencies for all (non-
  587. expanded) grammars in directory \"%s\".\n
  588. They are stored in the kill-ring, i.e., you can insert them with C-y
  589. into your Makefile. You can also invoke M-x antlr-show-makefile-rules
  590. from within a Makefile to insert them directly.\n\n\n"
  591. "Introduction to use with \\[antlr-show-makefile-rules].
  592. It is a format string and used with substitution DIRECTORY/%s where
  593. DIRECTORY is the name of the current directory.")
  594. ;;;===========================================================================
  595. ;;; Menu
  596. ;;;===========================================================================
  597. (defcustom antlr-imenu-name t ; (featurep 'xemacs) ; TODO: Emacs-21 bug?
  598. "Non-nil, if a \"Index\" menu should be added to the menubar.
  599. If it is a string, it is used instead \"Index\". Requires package
  600. imenu."
  601. :group 'antlr
  602. :type '(choice (const :tag "No menu" nil)
  603. (const :tag "Index menu" t)
  604. (string :tag "Other menu name")))
  605. (defvar antlr-mode-map
  606. (let ((map (make-sparse-keymap)))
  607. (define-key map "\t" 'antlr-indent-command)
  608. (define-key map "\e\C-a" 'antlr-beginning-of-rule)
  609. (define-key map "\e\C-e" 'antlr-end-of-rule)
  610. (define-key map "\C-c\C-a" 'antlr-beginning-of-body)
  611. (define-key map "\C-c\C-e" 'antlr-end-of-body)
  612. (define-key map "\C-c\C-f" 'c-forward-into-nomenclature)
  613. (define-key map "\C-c\C-b" 'c-backward-into-nomenclature)
  614. (define-key map "\C-c\C-c" 'comment-region)
  615. (define-key map "\C-c\C-v" 'antlr-hide-actions)
  616. (define-key map "\C-c\C-r" 'antlr-run-tool)
  617. (define-key map "\C-c\C-o" 'antlr-insert-option)
  618. ;; I'm too lazy to define my own:
  619. (define-key map "\ea" 'c-beginning-of-statement)
  620. (define-key map "\ee" 'c-end-of-statement)
  621. ;; electric keys:
  622. (define-key map ":" 'antlr-electric-character)
  623. (define-key map ";" 'antlr-electric-character)
  624. (define-key map "|" 'antlr-electric-character)
  625. (define-key map "&" 'antlr-electric-character)
  626. (define-key map "(" 'antlr-electric-character)
  627. (define-key map ")" 'antlr-electric-character)
  628. (define-key map "{" 'antlr-electric-character)
  629. (define-key map "}" 'antlr-electric-character)
  630. map)
  631. "Keymap used in `antlr-mode' buffers.")
  632. (easy-menu-define antlr-mode-menu antlr-mode-map
  633. "Major mode menu."
  634. `("Antlr"
  635. ,@(if (cond-emacs-xemacs
  636. :EMACS (and antlr-options-use-submenus
  637. (>= emacs-major-version 21))
  638. :XEMACS antlr-options-use-submenus)
  639. `(("Insert File Option"
  640. :filter ,(lambda (x) (antlr-options-menu-filter 1 x)))
  641. ("Insert Grammar Option"
  642. :filter ,(lambda (x) (antlr-options-menu-filter 2 x)))
  643. ("Insert Rule Option"
  644. :filter ,(lambda (x) (antlr-options-menu-filter 3 x)))
  645. ("Insert Subrule Option"
  646. :filter ,(lambda (x) (antlr-options-menu-filter 4 x)))
  647. "---")
  648. '(["Insert Option" antlr-insert-option
  649. :active (not buffer-read-only)]))
  650. ("Forward/Backward"
  651. ["Backward Rule" antlr-beginning-of-rule t]
  652. ["Forward Rule" antlr-end-of-rule t]
  653. ["Start of Rule Body" antlr-beginning-of-body
  654. :active (antlr-inside-rule-p)]
  655. ["End of Rule Body" antlr-end-of-body
  656. :active (antlr-inside-rule-p)]
  657. "---"
  658. ["Backward Statement" c-beginning-of-statement t]
  659. ["Forward Statement" c-end-of-statement t]
  660. ["Backward Into Nomencl." c-backward-into-nomenclature t]
  661. ["Forward Into Nomencl." c-forward-into-nomenclature t])
  662. ["Indent Region" indent-region
  663. :active (and (not buffer-read-only) (c-region-is-active-p))]
  664. ["Comment Out Region" comment-region
  665. :active (and (not buffer-read-only) (c-region-is-active-p))]
  666. ["Uncomment Region"
  667. (comment-region (region-beginning) (region-end) '(4))
  668. :active (and (not buffer-read-only) (c-region-is-active-p))]
  669. "---"
  670. ["Hide Actions (incl. Args)" antlr-hide-actions t]
  671. ["Hide Actions (excl. Args)" (antlr-hide-actions 2) t]
  672. ["Unhide All Actions" (antlr-hide-actions 0) t]
  673. "---"
  674. ["Run Tool on Grammar" antlr-run-tool t]
  675. ["Show Makefile Rules" antlr-show-makefile-rules t]
  676. "---"
  677. ["Customize Antlr" (customize-group 'antlr) t]))
  678. ;;;===========================================================================
  679. ;;; font-lock
  680. ;;;===========================================================================
  681. (defcustom antlr-font-lock-maximum-decoration 'inherit
  682. "The maximum decoration level for fontifying actions.
  683. Value `none' means, do not fontify actions, just normal grammar code
  684. according to `antlr-font-lock-additional-keywords'. Value `inherit'
  685. means, use value of `font-lock-maximum-decoration'. Any other value is
  686. interpreted as in `font-lock-maximum-decoration' with no level-0
  687. fontification, see `antlr-font-lock-keywords-alist'.
  688. While calculating the decoration level for actions, `major-mode' is
  689. bound to `antlr-language'. For example, with value
  690. ((java-mode . 2) (c++-mode . 0))
  691. Java actions are fontified with level 2 and C++ actions are not
  692. fontified at all."
  693. :group 'antlr
  694. :type '(choice (const :tag "None" none)
  695. (const :tag "Inherit" inherit)
  696. (const :tag "Default" nil)
  697. (const :tag "Maximum" t)
  698. (integer :tag "Level" 1)
  699. (repeat :menu-tag "Mode specific" :tag "Mode specific"
  700. :value ((t . t))
  701. (cons :tag "Instance"
  702. (radio :tag "Mode"
  703. (const :tag "All" t)
  704. (symbol :tag "Name"))
  705. (radio :tag "Decoration"
  706. (const :tag "Default" nil)
  707. (const :tag "Maximum" t)
  708. (integer :tag "Level" 1))))))
  709. (defconst antlr-no-action-keywords nil
  710. ;; Using nil directly won't work (would use highest level, see
  711. ;; `font-lock-choose-keywords'), but a non-symbol, i.e., (list), at `car'
  712. ;; would break Emacs-21.0:
  713. "Empty font-lock keywords for actions.
  714. Do not change the value of this constant.")
  715. (defvar antlr-font-lock-keywords-alist
  716. '((java-mode
  717. antlr-no-action-keywords
  718. java-font-lock-keywords-1 java-font-lock-keywords-2
  719. java-font-lock-keywords-3)
  720. (c++-mode
  721. antlr-no-action-keywords
  722. c++-font-lock-keywords-1 c++-font-lock-keywords-2
  723. c++-font-lock-keywords-3))
  724. "List of font-lock keywords for actions in the grammar.
  725. Each element in this list looks like
  726. (MAJOR-MODE KEYWORD...)
  727. If `antlr-language' is equal to MAJOR-MODE, the KEYWORDs are the
  728. font-lock keywords according to `font-lock-defaults' used for the code
  729. in the grammar's actions and semantic predicates, see
  730. `antlr-font-lock-maximum-decoration'.")
  731. (defvar antlr-default-face 'antlr-default)
  732. (defface antlr-default '((t nil))
  733. "Face to prevent strings from language dependent highlighting.
  734. Do not change."
  735. :group 'antlr)
  736. ;; backward-compatibility alias
  737. (put 'antlr-font-lock-default-face 'face-alias 'antlr-default)
  738. (put 'antlr-font-lock-default-face 'obsolete-face "22.1")
  739. (defvar antlr-keyword-face 'antlr-keyword)
  740. (defface antlr-keyword
  741. (cond-emacs-xemacs
  742. '((((class color) (background light))
  743. (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
  744. (t :inherit font-lock-keyword-face)))
  745. "ANTLR keywords."
  746. :group 'antlr)
  747. ;; backward-compatibility alias
  748. (put 'antlr-font-lock-keyword-face 'face-alias 'antlr-keyword)
  749. (put 'antlr-font-lock-keyword-face 'obsolete-face "22.1")
  750. (defvar antlr-syntax-face 'antlr-keyword)
  751. (defface antlr-syntax
  752. (cond-emacs-xemacs
  753. '((((class color) (background light))
  754. (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
  755. (t :inherit font-lock-constant-face)))
  756. "ANTLR syntax symbols like :, |, (, ), ...."
  757. :group 'antlr)
  758. ;; backward-compatibility alias
  759. (put 'antlr-font-lock-syntax-face 'face-alias 'antlr-syntax)
  760. (put 'antlr-font-lock-syntax-face 'obsolete-face "22.1")
  761. (defvar antlr-ruledef-face 'antlr-ruledef)
  762. (defface antlr-ruledef
  763. (cond-emacs-xemacs
  764. '((((class color) (background light))
  765. (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
  766. (t :inherit font-lock-function-name-face)))
  767. "ANTLR rule references (definition)."
  768. :group 'antlr)
  769. ;; backward-compatibility alias
  770. (put 'antlr-font-lock-ruledef-face 'face-alias 'antlr-ruledef)
  771. (put 'antlr-font-lock-ruledef-face 'obsolete-face "22.1")
  772. (defvar antlr-tokendef-face 'antlr-tokendef)
  773. (defface antlr-tokendef
  774. (cond-emacs-xemacs
  775. '((((class color) (background light))
  776. (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
  777. (t :inherit font-lock-function-name-face)))
  778. "ANTLR token references (definition)."
  779. :group 'antlr)
  780. ;; backward-compatibility alias
  781. (put 'antlr-font-lock-tokendef-face 'face-alias 'antlr-tokendef)
  782. (put 'antlr-font-lock-tokendef-face 'obsolete-face "22.1")
  783. (defvar antlr-ruleref-face 'antlr-ruleref)
  784. (defface antlr-ruleref
  785. '((((class color) (background light)) (:foreground "blue4"))
  786. (t :inherit font-lock-type-face))
  787. "ANTLR rule references (usage)."
  788. :group 'antlr)
  789. ;; backward-compatibility alias
  790. (put 'antlr-font-lock-ruleref-face 'face-alias 'antlr-ruleref)
  791. (put 'antlr-font-lock-ruleref-face 'obsolete-face "22.1")
  792. (defvar antlr-tokenref-face 'antlr-tokenref)
  793. (defface antlr-tokenref
  794. '((((class color) (background light)) (:foreground "orange4"))
  795. (t :inherit font-lock-type-face))
  796. "ANTLR token references (usage)."
  797. :group 'antlr)
  798. ;; backward-compatibility alias
  799. (put 'antlr-font-lock-tokenref-face 'face-alias 'antlr-tokenref)
  800. (put 'antlr-font-lock-tokenref-face 'obsolete-face "22.1")
  801. (defvar antlr-literal-face 'antlr-literal)
  802. (defface antlr-literal
  803. (cond-emacs-xemacs
  804. '((((class color) (background light))
  805. (:foreground "brown4" :EMACS :weight bold :XEMACS :bold t))
  806. (t :inherit font-lock-string-face)))
  807. "ANTLR special literal tokens.
  808. It is used to highlight strings matched by the first regexp group of
  809. `antlr-font-lock-literal-regexp'."
  810. :group 'antlr)
  811. ;; backward-compatibility alias
  812. (put 'antlr-font-lock-literal-face 'face-alias 'antlr-literal)
  813. (put 'antlr-font-lock-literal-face 'obsolete-face "22.1")
  814. (defcustom antlr-font-lock-literal-regexp "\"\\(\\sw\\(\\sw\\|-\\)*\\)\""
  815. "Regexp matching literals with special syntax highlighting, or nil.
  816. If nil, there is no special syntax highlighting for some literals.
  817. Otherwise, it should be a regular expression which must contain a regexp
  818. group. The string matched by the first group is highlighted with
  819. `antlr-font-lock-literal-face'."
  820. :group 'antlr
  821. :type '(choice (const :tag "None" nil) regexp))
  822. (defvar antlr-class-header-regexp
  823. "\\(class\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;"
  824. "Regexp matching class headers.")
  825. (defvar antlr-font-lock-additional-keywords
  826. (cond-emacs-xemacs
  827. `((antlr-invalidate-context-cache)
  828. ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))"
  829. (1 antlr-tokendef-face))
  830. ("\\$\\sw+" (0 antlr-keyword-face))
  831. ;; the tokens are already fontified as string/docstrings:
  832. (,(lambda (limit)
  833. (if antlr-font-lock-literal-regexp
  834. (antlr-re-search-forward antlr-font-lock-literal-regexp limit)))
  835. (1 antlr-literal-face t)
  836. :XEMACS (0 nil)) ; XEmacs bug workaround
  837. (,(lambda (limit)
  838. (antlr-re-search-forward antlr-class-header-regexp limit))
  839. (1 antlr-keyword-face)
  840. (2 antlr-ruledef-face)
  841. (3 antlr-keyword-face)
  842. (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser"))
  843. antlr-keyword-face
  844. font-lock-type-face)))
  845. (,(lambda (limit)
  846. (antlr-re-search-forward
  847. "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>"
  848. limit))
  849. (1 antlr-keyword-face))
  850. (,(lambda (limit)
  851. (antlr-re-search-forward
  852. "^\\(private\\|public\\|protected\\)\\>[ \t]*\\(\\(\\sw+[ \t]*\\(:\\)?\\)\\)?"
  853. limit))
  854. (1 font-lock-type-face) ; not XEmacs's java level-3 fruit salad
  855. (3 (if (antlr-upcase-p (char-after (match-beginning 3)))
  856. antlr-tokendef-face
  857. antlr-ruledef-face) nil t)
  858. (4 antlr-syntax-face nil t))
  859. (,(lambda (limit)
  860. (antlr-re-search-forward "^\\(\\sw+\\)[ \t]*\\(:\\)?" limit))
  861. (1 (if (antlr-upcase-p (char-after (match-beginning 0)))
  862. antlr-tokendef-face
  863. antlr-ruledef-face) nil t)
  864. (2 antlr-syntax-face nil t))
  865. (,(lambda (limit)
  866. ;; v:ruleref and v:"literal" is allowed...
  867. (antlr-re-search-forward "\\(\\sw+\\)[ \t]*\\([=:]\\)?" limit))
  868. (1 (if (match-beginning 2)
  869. (if (eq (char-after (match-beginning 2)) ?=)
  870. antlr-default-face
  871. font-lock-variable-name-face)
  872. (if (antlr-upcase-p (char-after (match-beginning 1)))
  873. antlr-tokenref-face
  874. antlr-ruleref-face)))
  875. (2 antlr-default-face nil t))
  876. (,(lambda (limit)
  877. (antlr-re-search-forward "[|&:;(~]\\|)\\([*+?]\\|=>\\)?" limit))
  878. (0 antlr-syntax-face))))
  879. "Font-lock keywords for ANTLR's normal grammar code.
  880. See `antlr-font-lock-keywords-alist' for the keywords of actions.")
  881. (defvar antlr-font-lock-defaults
  882. '(antlr-font-lock-keywords
  883. nil nil ((?_ . "w") (?\( . ".") (?\) . ".")) beginning-of-defun)
  884. "Font-lock defaults used for ANTLR syntax highlighting.
  885. The SYNTAX-ALIST element is also used to initialize
  886. `antlr-action-syntax-table'.")
  887. ;;;===========================================================================
  888. ;;; Internal variables
  889. ;;;===========================================================================
  890. (defvar antlr-mode-hook nil
  891. "Hook called by `antlr-mode'.")
  892. (defvar antlr-mode-syntax-table
  893. (let ((st (make-syntax-table)))
  894. (c-populate-syntax-table st)
  895. st)
  896. "Syntax table used in `antlr-mode' buffers.
  897. If non-nil, it will be initialized in `antlr-mode'.")
  898. ;; used for "in Java/C++ code" = syntactic-depth>0
  899. (defvar antlr-action-syntax-table
  900. (let ((st (copy-syntax-table antlr-mode-syntax-table))
  901. (slist (nth 3 antlr-font-lock-defaults)))
  902. (while slist
  903. (modify-syntax-entry (caar slist) (cdar slist) st)
  904. (setq slist (cdr slist)))
  905. st)
  906. "Syntax table used for ANTLR action parsing.
  907. Initialized by `antlr-mode-syntax-table', changed by SYNTAX-ALIST in
  908. `antlr-font-lock-defaults'. This table should be selected if you use
  909. `buffer-syntactic-context' and `buffer-syntactic-context-depth' in order
  910. not to confuse their context_cache.")
  911. (defvar antlr-mode-abbrev-table nil
  912. "Abbreviation table used in `antlr-mode' buffers.")
  913. (define-abbrev-table 'antlr-mode-abbrev-table ())
  914. (defvar antlr-slow-cache-enabling-symbol 'loudly
  915. ;; Emacs's font-lock changes buffer's tick counter, therefore this value should
  916. ;; be a parameter of a font-lock function, but not any other variable of
  917. ;; functions which call `antlr-slow-syntactic-context'.
  918. "If value is a bound symbol, cache will be used even with text changes.
  919. This is no user option. Used for `antlr-slow-syntactic-context'.")
  920. (defvar antlr-slow-cache-diff-threshold 5000
  921. "Maximum distance between `point' and cache position for cache use.
  922. Used for `antlr-slow-syntactic-context'.")
  923. ;;;;##########################################################################
  924. ;;;; The Code
  925. ;;;;##########################################################################
  926. ;;;===========================================================================
  927. ;;; Syntax functions -- Emacs vs XEmacs dependent, part 1
  928. ;;;===========================================================================
  929. ;; From help.el (XEmacs-21.1), without `copy-syntax-table'
  930. (defmacro antlr-with-syntax-table (syntab &rest body)
  931. "Evaluate BODY with the syntax table SYNTAB."
  932. `(let ((stab (syntax-table)))
  933. (unwind-protect
  934. (progn (set-syntax-table ,syntab) ,@body)
  935. (set-syntax-table stab))))
  936. (put 'antlr-with-syntax-table 'lisp-indent-function 1)
  937. (put 'antlr-with-syntax-table 'edebug-form-spec '(form body))
  938. (defunx antlr-default-directory ()
  939. :xemacs-and-try default-directory
  940. "Return `default-directory'."
  941. default-directory)
  942. ;; Check Emacs-21.1 simple.el, `shell-command'.
  943. (defunx antlr-read-shell-command (prompt &optional initial-input history)
  944. :xemacs-and-try read-shell-command
  945. "Read a string from the minibuffer, using `shell-command-history'."
  946. (read-from-minibuffer prompt initial-input nil nil
  947. (or history 'shell-command-history)))
  948. (defunx antlr-with-displaying-help-buffer (thunk &optional _name)
  949. :xemacs-and-try with-displaying-help-buffer
  950. "Make a help buffer and call `thunk' there."
  951. (with-output-to-temp-buffer "*Help*"
  952. (save-excursion (funcall thunk))))
  953. ;;;===========================================================================
  954. ;;; Context cache
  955. ;;;===========================================================================
  956. (defvar antlr-slow-context-cache nil "Internal.")
  957. ;;;(defvar antlr-statistics-full-neg 0)
  958. ;;;(defvar antlr-statistics-full-diff 0)
  959. ;;;(defvar antlr-statistics-full-other 0)
  960. ;;;(defvar antlr-statistics-cache 0)
  961. ;;;(defvar antlr-statistics-inval 0)
  962. (defunx antlr-invalidate-context-cache (&rest _dummies)
  963. ;; checkdoc-params: (dummies)
  964. "Invalidate context cache for syntactical context information."
  965. :XEMACS ; XEmacs bug workaround
  966. (with-current-buffer (get-buffer-create " ANTLR XEmacs bug workaround")
  967. (buffer-syntactic-context-depth)
  968. nil)
  969. :EMACS
  970. ;;; (incf antlr-statistics-inval)
  971. (setq antlr-slow-context-cache nil))
  972. (defunx antlr-syntactic-context ()
  973. "Return some syntactic context information.
  974. Return `string' if point is within a string, `block-comment' or
  975. `comment' is point is within a comment or the depth within all
  976. parenthesis-syntax delimiters at point otherwise.
  977. WARNING: this may alter `match-data'."
  978. :XEMACS
  979. (or (buffer-syntactic-context) (buffer-syntactic-context-depth))
  980. :EMACS
  981. (let ((orig (point)) diff state
  982. ;; Arg, Emacs's (buffer-modified-tick) changes with font-lock. Use
  983. ;; hack that `loudly' is bound during font-locking => cache use will
  984. ;; increase from 7% to 99.99% during font-locking.
  985. (tick (or (boundp antlr-slow-cache-enabling-symbol)
  986. (buffer-modified-tick))))
  987. (if (and (cdr antlr-slow-context-cache)
  988. (>= (setq diff (- orig (cadr antlr-slow-context-cache))) 0)
  989. (< diff antlr-slow-cache-diff-threshold)
  990. (eq (current-buffer) (caar antlr-slow-context-cache))
  991. (eq tick (cdar antlr-slow-context-cache)))
  992. ;; (setq antlr-statistics-cache (1+ antlr-statistics-cache) ...)
  993. (setq state (parse-partial-sexp (cadr antlr-slow-context-cache) orig
  994. nil nil
  995. (cddr antlr-slow-context-cache)))
  996. (if (>= orig antlr-slow-cache-diff-threshold)
  997. (beginning-of-defun)
  998. (goto-char (point-min)))
  999. ;;; (cond ((and diff (< diff 0)) (incf antlr-statistics-full-neg))
  1000. ;;; ((and diff (>= diff 3000)) (incf antlr-statistics-full-diff))
  1001. ;;; (t (incf antlr-statistics-full-other)))
  1002. (setq state (parse-partial-sexp (point) orig)))
  1003. (goto-char orig)
  1004. (if antlr-slow-context-cache
  1005. (setcdr antlr-slow-context-cache (cons orig state))
  1006. (setq antlr-slow-context-cache
  1007. (cons (cons (current-buffer) tick)
  1008. (cons orig state))))
  1009. (cond ((nth 3 state) 'string)
  1010. ((nth 4 state) 'comment) ; block-comment? -- we don't care
  1011. (t (car state)))))
  1012. ;;; (incf (aref antlr-statistics 2))
  1013. ;;; (unless (and (eq (current-buffer)
  1014. ;;; (caar antlr-slow-context-cache))
  1015. ;;; (eq (buffer-modified-tick)
  1016. ;;; (cdar antlr-slow-context-cache)))
  1017. ;;; (incf (aref antlr-statistics 1))
  1018. ;;; (setq antlr-slow-context-cache nil))
  1019. ;;; (let* ((orig (point))
  1020. ;;; (base (cadr antlr-slow-context-cache))
  1021. ;;; (curr (cddr antlr-slow-context-cache))
  1022. ;;; (state (cond ((eq orig (car curr)) (cdr curr))
  1023. ;;; ((eq orig (car base)) (cdr base))))
  1024. ;;; diff diff2)
  1025. ;;; (unless state
  1026. ;;; (incf (aref antlr-statistics 3))
  1027. ;;; (when curr
  1028. ;;; (if (< (setq diff (abs (- orig (car curr))))
  1029. ;;; (setq diff2 (abs (- orig (car base)))))
  1030. ;;; (setq state curr)
  1031. ;;; (setq state base
  1032. ;;; diff diff2))
  1033. ;;; (if (or (>= (1+ diff) (point)) (>= diff 3000))
  1034. ;;; (setq state nil))) ; start from bod/bob
  1035. ;;; (if state
  1036. ;;; (setq state
  1037. ;;; (parse-partial-sexp (car state) orig nil nil (cdr state)))
  1038. ;;; (if (>= orig 3000) (beginning-of-defun) (goto-char (point-min)))
  1039. ;;; (incf (aref antlr-statistics 4))
  1040. ;;; (setq cw (list orig (point) base curr))
  1041. ;;; (setq state (parse-partial-sexp (point) orig)))
  1042. ;;; (goto-char orig)
  1043. ;;; (if antlr-slow-context-cache
  1044. ;;; (setcdr (cdr antlr-slow-context-cache) (cons orig state))
  1045. ;;; (setq antlr-slow-context-cache
  1046. ;;; (cons (cons (current-buffer) (buffer-modified-tick))
  1047. ;;; (cons (cons orig state) (cons orig state))))))
  1048. ;;; (cond ((nth 3 state) 'string)
  1049. ;;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
  1050. ;;; (t (car state)))))
  1051. ;;; (beginning-of-defun)
  1052. ;;; (let ((state (parse-partial-sexp (point) orig)))
  1053. ;;; (goto-char orig)
  1054. ;;; (cond ((nth 3 state) 'string)
  1055. ;;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
  1056. ;;; (t (car state))))))
  1057. ;;;===========================================================================
  1058. ;;; Miscellaneous functions
  1059. ;;;===========================================================================
  1060. (defun antlr-upcase-p (char)
  1061. "Non-nil, if CHAR is an uppercase character (if CHAR was a char)."
  1062. ;; in XEmacs, upcase only works for ASCII
  1063. (or (and (<= ?A char) (<= char ?Z))
  1064. (and (<= ?\300 char) (<= char ?\337)))) ; ?\327 is no letter
  1065. (defun antlr-re-search-forward (regexp bound)
  1066. "Search forward from point for regular expression REGEXP.
  1067. Set point to the end of the occurrence found, and return point. Return
  1068. nil if no occurrence was found. Do not search within comments, strings
  1069. and actions/semantic predicates. BOUND bounds the search; it is a
  1070. buffer position. See also the functions `match-beginning', `match-end'
  1071. and `replace-match'."
  1072. ;; WARNING: Should only be used with `antlr-action-syntax-table'!
  1073. (let ((continue t))
  1074. (while (and (re-search-forward regexp bound 'limit)
  1075. (save-match-data
  1076. (if (eq (antlr-syntactic-context) 0)
  1077. (setq continue nil)
  1078. t))))
  1079. (if continue nil (point))))
  1080. (defun antlr-search-forward (string)
  1081. "Search forward from point for STRING.
  1082. Set point to the end of the occurrence found, and return point. Return
  1083. nil if no occurrence was found. Do not search within comments, strings
  1084. and actions/semantic predicates."
  1085. ;; WARNING: Should only be used with `antlr-action-syntax-table'!
  1086. (let ((continue t))
  1087. (while (and (search-forward string nil 'limit)
  1088. (if (eq (antlr-syntactic-context) 0) (setq continue nil) t)))
  1089. (if continue nil (point))))
  1090. (defun antlr-search-backward (string)
  1091. "Search backward from point for STRING.
  1092. Set point to the beginning of the occurrence found, and return point.
  1093. Return nil if no occurrence was found. Do not search within comments,
  1094. strings and actions/semantic predicates."
  1095. ;; WARNING: Should only be used with `antlr-action-syntax-table'!
  1096. (let ((continue t))
  1097. (while (and (search-backward string nil 'limit)
  1098. (if (eq (antlr-syntactic-context) 0) (setq continue nil) t)))
  1099. (if continue nil (point))))
  1100. (defsubst antlr-skip-sexps (count)
  1101. "Skip the next COUNT balanced expressions and the comments after it.
  1102. Return position before the comments after the last expression."
  1103. (goto-char (or (ignore-errors-x (scan-sexps (point) count)) (point-max)))
  1104. (prog1 (point)
  1105. (antlr-c-forward-sws)))
  1106. ;;;===========================================================================
  1107. ;;; font-lock
  1108. ;;;===========================================================================
  1109. (defun antlr-font-lock-keywords ()
  1110. "Return font-lock keywords for current buffer.
  1111. See `antlr-font-lock-additional-keywords', `antlr-language' and
  1112. `antlr-font-lock-maximum-decoration'."
  1113. (if (eq antlr-font-lock-maximum-decoration 'none)
  1114. antlr-font-lock-additional-keywords
  1115. (append antlr-font-lock-additional-keywords
  1116. (eval (let ((major-mode antlr-language)) ; dynamic
  1117. (font-lock-choose-keywords
  1118. (cdr (assq antlr-language
  1119. antlr-font-lock-keywords-alist))
  1120. (if (eq antlr-font-lock-maximum-decoration 'inherit)
  1121. font-lock-maximum-decoration
  1122. antlr-font-lock-maximum-decoration)))))))
  1123. ;;;===========================================================================
  1124. ;;; imenu support
  1125. ;;;===========================================================================
  1126. (defun antlr-grammar-tokens ()
  1127. "Return alist for tokens defined in current buffer."
  1128. (save-excursion (antlr-imenu-create-index-function t)))
  1129. (defun antlr-imenu-create-index-function (&optional tokenrefs-only)
  1130. "Return imenu index-alist for ANTLR grammar files.
  1131. IF TOKENREFS-ONLY is non-nil, just return alist with tokenref names."
  1132. (let ((items nil)
  1133. (classes nil)
  1134. (continue t))
  1135. ;; Using `imenu-progress-message' would require imenu for compilation, but
  1136. ;; nobody is missing these messages. The generic imenu function searches
  1137. ;; backward, which is slower and more likely not to work during editing.
  1138. (antlr-with-syntax-table antlr-action-syntax-table
  1139. (antlr-invalidate-context-cache)
  1140. (goto-char (point-min))
  1141. (antlr-skip-file-prelude t)
  1142. (while continue
  1143. (if (looking-at "{") (antlr-skip-sexps 1))
  1144. (if (looking-at antlr-class-header-regexp)
  1145. (or tokenrefs-only
  1146. (push (cons (match-string 2)
  1147. (if imenu-use-markers
  1148. (copy-marker (match-beginning 2))
  1149. (match-beginning 2)))
  1150. classes))
  1151. (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)")
  1152. (antlr-skip-sexps 1))
  1153. (when (looking-at "\\sw+")
  1154. (if tokenrefs-only
  1155. (if (antlr-upcase-p (char-after (point)))
  1156. (push (list (match-string 0)) items))
  1157. (push (cons (match-string 0)
  1158. (if imenu-use-markers
  1159. (copy-marker (match-beginning 0))
  1160. (match-beginning 0)))
  1161. items))))
  1162. (if (setq continue (antlr-search-forward ";"))
  1163. (antlr-skip-exception-part t))))
  1164. (if classes
  1165. (cons (cons "Classes" (nreverse classes)) (nreverse items))
  1166. (nreverse items))))
  1167. ;;;===========================================================================
  1168. ;;; Parse grammar files (internal functions)
  1169. ;;;===========================================================================
  1170. (defun antlr-skip-exception-part (skip-comment)
  1171. "Skip exception part of current rule, i.e., everything after `;'.
  1172. This also includes the options and tokens part of a grammar class
  1173. header. If SKIP-COMMENT is non-nil, also skip the comment after that
  1174. part."
  1175. (let ((pos (point))
  1176. (class nil))
  1177. (antlr-c-forward-sws)
  1178. (while (looking-at "options\\>\\|tokens\\>")
  1179. (setq class t)
  1180. (setq pos (antlr-skip-sexps 2)))
  1181. (if class
  1182. ;; Problem: an action only belongs to a class def, not a normal rule.
  1183. ;; But checking the current rule type is too expensive => only expect
  1184. ;; an action if we have found an option or tokens part.
  1185. (if (looking-at "{") (setq pos (antlr-skip-sexps 1)))
  1186. (while (looking-at "exception\\>")
  1187. (setq pos (antlr-skip-sexps 1))
  1188. (when (looking-at "\\[")
  1189. (setq pos (antlr-skip-sexps 1)))
  1190. (while (looking-at "catch\\>")
  1191. (setq pos (antlr-skip-sexps 3)))))
  1192. (or skip-comment (goto-char pos))))
  1193. (defun antlr-skip-file-prelude (skip-comment)
  1194. "Skip the file prelude: the header and file options.
  1195. If SKIP-COMMENT is non-nil, also skip the comment after that part.
  1196. Return the start position of the file prelude.
  1197. Hack: if SKIP-COMMENT is `header-only' only skip header and return
  1198. position before the comment after the header."
  1199. (let* ((pos (point))
  1200. (pos0 pos))
  1201. (antlr-c-forward-sws)
  1202. (if skip-comment (setq pos0 (point)))
  1203. (while (looking-at "header\\>[ \t]*\\(\"\\)?")
  1204. (setq pos (antlr-skip-sexps (if (match-beginning 1) 3 2))))
  1205. (if (eq skip-comment 'header-only) ; a hack...
  1206. pos
  1207. (when (looking-at "options\\>")
  1208. (setq pos (antlr-skip-sexps 2)))
  1209. (or skip-comment (goto-char pos))
  1210. pos0)))
  1211. (defun antlr-next-rule (arg skip-comment)
  1212. "Move forward to next end of rule. Do it ARG many times.
  1213. A grammar class header and the file prelude are also considered as a
  1214. rule. Negative argument ARG means move back to ARGth preceding end of
  1215. rule. The behavior is not defined when ARG is zero. If SKIP-COMMENT
  1216. is non-nil, move to beginning of the rule."
  1217. ;; WARNING: Should only be used with `antlr-action-syntax-table'!
  1218. ;; PRE: ARG<>0
  1219. (let ((pos (point))
  1220. (beg (point)))
  1221. ;; first look whether point is in exception part
  1222. (if (antlr-search-backward ";")
  1223. (progn
  1224. (setq beg (point))
  1225. (forward-char)
  1226. (antlr-skip-exception-part skip-comment))
  1227. (antlr-skip-file-prelude skip-comment))
  1228. (if (< arg 0)
  1229. (unless (and (< (point) pos) (zerop (incf arg)))
  1230. ;; if we have moved backward, we already moved one defun backward
  1231. (goto-char beg) ; rewind (to ";" / point)
  1232. (while (and arg (<= (incf arg) 0))
  1233. (if (antlr-search-backward ";")
  1234. (setq beg (point))
  1235. (when (>= arg -1)
  1236. ;; try file prelude:
  1237. (setq pos (antlr-skip-file-prelude skip-comment))
  1238. (if (zerop arg)
  1239. (if (>= (point) beg)
  1240. (goto-char (if (>= pos beg) (point-min) pos)))
  1241. (goto-char (if (or (>= (point) beg) (= (point) pos))
  1242. (point-min) pos))))
  1243. (setq arg nil)))
  1244. (when arg ; always found a ";"
  1245. (forward-char)
  1246. (antlr-skip-exception-part skip-comment)))
  1247. (if (<= (point) pos) ; moved backward?
  1248. (goto-char pos) ; rewind
  1249. (decf arg)) ; already moved one defun forward
  1250. (unless (zerop arg)
  1251. (while (>= (decf arg) 0)
  1252. (antlr-search-forward ";"))
  1253. (antlr-skip-exception-part skip-comment)))))
  1254. (defun antlr-outside-rule-p ()
  1255. "Non-nil if point is outside a grammar rule.
  1256. Move to the beginning of the current rule if point is inside a rule."
  1257. ;; WARNING: Should only be used with `antlr-action-syntax-table'!
  1258. (let ((pos (point)))
  1259. (antlr-next-rule -1 nil)
  1260. (let ((between (or (bobp) (< (point) pos))))
  1261. (antlr-c-forward-sws)
  1262. (and between (> (point) pos) (goto-char pos)))))
  1263. ;;;===========================================================================
  1264. ;;; Parse grammar files (commands)
  1265. ;;;===========================================================================
  1266. ;; No (interactive "_") in Emacs... use `zmacs-region-stays'.
  1267. (defun antlr-inside-rule-p ()
  1268. "Non-nil if point is inside a grammar rule.
  1269. A grammar class header and the file prelude are also considered as a
  1270. rule."
  1271. (save-excursion
  1272. (antlr-with-syntax-table antlr-action-syntax-table
  1273. (not (antlr-outside-rule-p)))))
  1274. (defunx antlr-end-of-rule (&optional arg)
  1275. "Move forward to next end of rule. Do it ARG [default: 1] many times.
  1276. A grammar class header and the file prelude are also considered as a
  1277. rule. Negative argument ARG means move back to ARGth preceding end of
  1278. rule. If ARG is zero, run `antlr-end-of-body'."
  1279. (interactive "_p")
  1280. (if (zerop arg)
  1281. (antlr-end-of-body)
  1282. (antlr-with-syntax-table antlr-action-syntax-table
  1283. (antlr-next-rule arg nil))))
  1284. (defunx antlr-beginning-of-rule (&optional arg)
  1285. "Move backward to preceding beginning of rule. Do it ARG many times.
  1286. A grammar class header and the file prelude are also considered as a
  1287. rule. Negative argument ARG means move forward to ARGth next beginning
  1288. of rule. If ARG is zero, run `antlr-beginning-of-body'."
  1289. (interactive "_p")
  1290. (if (zerop arg)
  1291. (antlr-beginning-of-body)
  1292. (antlr-with-syntax-table antlr-action-syntax-table
  1293. (antlr-next-rule (- arg) t))))
  1294. (defunx antlr-end-of-body (&optional msg)
  1295. "Move to position after the `;' of the current rule.
  1296. A grammar class header is also considered as a rule. With optional
  1297. prefix arg MSG, move to `:'."
  1298. (interactive "_")
  1299. (antlr-with-syntax-table antlr-action-syntax-table
  1300. (let ((orig (point)))
  1301. (if (antlr-outside-rule-p)
  1302. (error "Outside an ANTLR rule"))
  1303. (let ((bor (point)))
  1304. (when (< (antlr-skip-file-prelude t) (point))
  1305. ;; Yes, we are in the file prelude
  1306. (goto-char orig)
  1307. (error (or msg "The file prelude is without `;'")))
  1308. (antlr-search-forward ";")
  1309. (when msg
  1310. (when (< (point)
  1311. (progn (goto-char bor)
  1312. (or (antlr-search-forward ":") (point-max))))
  1313. (goto-char orig)
  1314. (error msg))
  1315. (antlr-c-forward-sws))))))
  1316. (defunx antlr-beginning-of-body ()
  1317. "Move to the first element after the `:' of the current rule."
  1318. (interactive "_")
  1319. (antlr-end-of-body "Class headers and the file prelude are without `:'"))
  1320. ;;;===========================================================================
  1321. ;;; Literal normalization, Hide Actions
  1322. ;;;===========================================================================
  1323. (defun antlr-downcase-literals (&optional transform)
  1324. "Convert all literals in buffer to lower case.
  1325. If non-nil, TRANSFORM is used on literals instead of `downcase-region'."
  1326. (interactive)
  1327. (or transform (setq transform 'downcase-region))
  1328. (let ((literals 0))
  1329. (save-excursion
  1330. (goto-char (point-min))
  1331. (antlr-with-syntax-table antlr-action-syntax-table
  1332. (antlr-invalidate-context-cache)
  1333. (while (antlr-re-search-forward "\"\\(\\sw\\(\\sw\\|-\\)*\\)\"" nil)
  1334. (funcall transform (match-beginning 0) (match-end 0))
  1335. (incf literals))))
  1336. (message "Transformed %d literals" literals)))
  1337. (defun antlr-upcase-literals ()
  1338. "Convert all literals in buffer to upper case."
  1339. (interactive)
  1340. (antlr-downcase-literals 'upcase-region))
  1341. (defun antlr-hide-actions (arg &optional silent)
  1342. "Hide or unhide all actions in buffer.
  1343. Hide all actions including arguments in brackets if ARG is 1 or if
  1344. called interactively without prefix argument. Hide all actions
  1345. excluding arguments in brackets if ARG is 2 or higher. Unhide all
  1346. actions if ARG is 0 or negative. See `antlr-action-visibility'.
  1347. Display a message unless optional argument SILENT is non-nil."
  1348. (interactive "p")
  1349. (save-buffer-state-x
  1350. (if (> arg 0)
  1351. (let ((regexp (if (= arg 1) "[]}]" "}"))
  1352. (diff (and antlr-action-visibility
  1353. (+ (max antlr-action-visibility 0) 2))))
  1354. (antlr-hide-actions 0 t)
  1355. (save-excursion
  1356. (goto-char (point-min))
  1357. (antlr-with-syntax-table antlr-action-syntax-table
  1358. (antlr-invalidate-context-cache)
  1359. (while (antlr-re-search-forward regexp nil)
  1360. (let ((beg (ignore-errors-x (scan-sexps (point) -1))))
  1361. (when beg
  1362. (if diff ; braces are visible
  1363. (if (> (point) (+ beg diff))
  1364. (add-text-properties (1+ beg) (1- (point))
  1365. '(invisible t intangible t)))
  1366. ;; if actions is on line(s) of its own, hide WS
  1367. (and (looking-at "[ \t]*$")
  1368. (save-excursion
  1369. (goto-char beg)
  1370. (skip-chars-backward " \t")
  1371. (and (bolp) (setq beg (point))))
  1372. (beginning-of-line 2)) ; beginning of next line
  1373. (add-text-properties beg (point)
  1374. '(invisible t intangible t))))))))
  1375. (or silent
  1376. (message "Hide all actions (%s arguments)...done"
  1377. (if (= arg 1) "including" "excluding"))))
  1378. (remove-text-properties (point-min) (point-max)
  1379. '(invisible nil intangible nil))
  1380. (or silent
  1381. (message "Unhide all actions (including arguments)...done")))))
  1382. ;;;===========================================================================
  1383. ;;; Insert option: command
  1384. ;;;===========================================================================
  1385. (defun antlr-insert-option (level option &optional location)
  1386. "Insert file/grammar/rule/subrule option near point.
  1387. LEVEL determines option kind to insert: 1=file, 2=grammar, 3=rule,
  1388. 4=subrule. OPTION is a string with the name of the option to insert.
  1389. LOCATION can be specified for not calling `antlr-option-kind' twice.
  1390. Inserting an option with this command works as follows:
  1391. 1. When called interactively, LEVEL is determined by the prefix
  1392. argument or automatically deduced without prefix argument.
  1393. 2. Signal an error if no option of that level could be inserted, e.g.,
  1394. if the buffer is read-only, the option area is outside the visible
  1395. part of the buffer or a subrule/rule option should be inserted with
  1396. point outside a subrule/rule.
  1397. 3. When called interactively, OPTION is read from the minibuffer with
  1398. completion over the known options of the given LEVEL.
  1399. 4. Ask user for confirmation if the given OPTION does not seem to be a
  1400. valid option to insert into the current file.
  1401. 5. Find a correct position to insert the option.
  1402. 6. Depending on the option, insert it the following way (inserting an
  1403. option also means inserting the option section if necessary):
  1404. - Insert the option and let user insert the value at point.
  1405. - Read a value (with completion) from the minibuffer, using a
  1406. previous value as initial contents, and insert option with value.
  1407. 7. Final action depending on the option. For example, set the language
  1408. according to a newly inserted language option.
  1409. The name of all options with a specification for their values are stored
  1410. in `antlr-options-alists'. The used specification also depends on the
  1411. value of `antlr-tool-version', i.e., step 4 will warn you if you use an
  1412. option that has been introduced in newer version of ANTLR, and step 5
  1413. will offer completion using version-correct values.
  1414. If the option already exists inside the visible part of the buffer, this
  1415. command can be used to change the value of that option. Otherwise, find
  1416. a correct position where the option can be inserted near point.
  1417. The search for a correct position is as follows:
  1418. * If search is within an area where options can be inserted, use the
  1419. position of point. Inside the options section and if point is in
  1420. the middle of a option definition, skip the rest of it.
  1421. * If an options section already exists, insert the options at the end.
  1422. If only the beginning of the area is visible, insert at the
  1423. beginning.
  1424. * Otherwise, find the position where an options section can be
  1425. inserted and insert a new section before any comments. If the
  1426. position before the comments is not visible, insert the new section
  1427. after the comments.
  1428. This function also inserts \"options {...}\" and the \":\" if necessary,
  1429. see `antlr-options-auto-colon'. See also `antlr-options-assign-string'.
  1430. This command might also set the mark like \\[set-mark-command] does, see
  1431. `antlr-options-push-mark'."
  1432. (interactive (antlr-insert-option-interactive current-prefix-arg))
  1433. (barf-if-buffer-read-only)
  1434. (or location (setq location (cdr (antlr-option-kind level))))
  1435. (cond ((null level)
  1436. (error "Cannot deduce what kind of option to insert"))
  1437. ((atom location)
  1438. (error "Cannot insert any %s options around here"
  1439. (elt antlr-options-headings (1- level)))))
  1440. (let ((area (car location))
  1441. (place (cdr location)))
  1442. (cond ((null place) ; invisible
  1443. (error (if area
  1444. "Invisible %s options, use %s to make them visible"
  1445. "Invisible area for %s options, use %s to make it visible")
  1446. (elt antlr-options-headings (1- level))
  1447. (substitute-command-keys "\\[widen]")))
  1448. ((null area) ; without option part
  1449. (antlr-insert-option-do level option nil
  1450. (null (cdr place))
  1451. (car place)))
  1452. ((save-excursion ; with option part, option visible
  1453. (goto-char (max (point-min) (car area)))
  1454. (re-search-forward (concat "\\(^\\|;\\)[ \t]*\\(\\<"
  1455. (regexp-quote option)
  1456. "\\>\\)[ \t\n]*\\(\\(=[ \t]?\\)[ \t]*\\(\\(\\sw\\|\\s_\\)+\\|\"\\([^\n\"\\]\\|[\\][^\n]\\)*\"\\)?\\)?")
  1457. ;; 2=name, 3=4+5, 4="=", 5=value
  1458. (min (point-max) (cdr area))
  1459. t))
  1460. (antlr-insert-option-do level option
  1461. (cons (or (match-beginning 5)
  1462. (match-beginning 3))
  1463. (match-end 5))
  1464. (and (null (cdr place)) area)
  1465. (or (match-beginning 5)
  1466. (match-end 4)
  1467. (match-end 2))))
  1468. (t ; with option part, option not yet
  1469. (antlr-insert-option-do level option t
  1470. (and (null (cdr place)) area)
  1471. (car place))))))
  1472. (defun antlr-insert-option-interactive (arg)
  1473. "Interactive specification for `antlr-insert-option'.
  1474. Return \(LEVEL OPTION LOCATION)."
  1475. (barf-if-buffer-read-only)
  1476. (if arg (setq arg (prefix-numeric-value arg)))
  1477. (unless (memq arg '(nil 1 2 3 4))
  1478. (error "Valid prefix args: no=auto, 1=file, 2=grammar, 3=rule, 4=subrule"))
  1479. (let* ((kind (antlr-option-kind arg))
  1480. (level (car kind)))
  1481. (if (atom (cdr kind))
  1482. (list level nil (cdr kind))
  1483. (let* ((table (elt antlr-options-alists (1- level)))
  1484. (completion-ignore-case t) ;dynamic
  1485. (input (completing-read (format "Insert %s option: "
  1486. (elt antlr-options-headings
  1487. (1- level)))
  1488. table)))
  1489. (list level input (cdr kind))))))
  1490. (defun antlr-options-menu-filter (level _menu-items)
  1491. "Return items for options submenu of level LEVEL."
  1492. ;; checkdoc-params: (menu-items)
  1493. (let ((active (if buffer-read-only
  1494. nil
  1495. (consp (cdr-safe (cdr (antlr-option-kind level)))))))
  1496. (mapcar (lambda (option)
  1497. (vector option
  1498. (list 'antlr-insert-option level option)
  1499. :active active))
  1500. (sort (mapcar 'car (elt antlr-options-alists (1- level)))
  1501. 'string-lessp))))
  1502. ;;;===========================================================================
  1503. ;;; Insert option: determine section-kind
  1504. ;;;===========================================================================
  1505. (defun antlr-option-kind (requested)
  1506. "Return level and location for option to insert near point.
  1507. Call function `antlr-option-level' with argument REQUESTED. If the
  1508. result is nil, return \(REQUESTED . error). If the result has the
  1509. non-nil value LEVEL, return \(LEVEL . LOCATION) where LOCATION looks
  1510. like \(AREA . PLACE), see `antlr-option-location'."
  1511. (save-excursion
  1512. (save-restriction
  1513. (let ((min0 (point-min)) ; before `widen'!
  1514. (max0 (point-max))
  1515. (orig (point))
  1516. (level (antlr-option-level requested)) ; calls `widen'!
  1517. pos)
  1518. (cond ((null level)
  1519. (setq level requested))
  1520. ((eq level 1) ; file options
  1521. (goto-char (point-min))
  1522. (setq pos (antlr-skip-file-prelude 'header-only)))
  1523. ((not (eq level 3)) ; grammar or subrule options
  1524. (setq pos (point))
  1525. (antlr-c-forward-sws))
  1526. ((looking-at "^\\(private[ \t\n]\\|public[ \t\n]\\|protected[ \t\n]\\)?[ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)[ \t\n]*\\(!\\)?[ \t\n]*\\(\\[\\)?")
  1527. ;; rule options, with complete rule header
  1528. (goto-char (or (match-end 4) (match-end 3)))
  1529. (setq pos (antlr-skip-sexps (if (match-end 5) 1 0)))
  1530. (when (looking-at "returns[ \t\n]*\\[")
  1531. (goto-char (1- (match-end 0)))
  1532. (setq pos (antlr-skip-sexps 1)))))
  1533. (cons level
  1534. (cond ((null pos) 'error)
  1535. ((looking-at "options[ \t\n]*{")
  1536. (goto-char (match-end 0))
  1537. (setq pos (ignore-errors-x (scan-lists (point) 1 1)))
  1538. (antlr-option-location orig min0 max0
  1539. (point)
  1540. (if pos (1- pos) (point-max))
  1541. t))
  1542. (t
  1543. (antlr-option-location orig min0 max0
  1544. pos (point)
  1545. nil))))))))
  1546. (defun antlr-option-level (requested)
  1547. "Return level for option to insert near point.
  1548. Remove any restrictions from current buffer and return level for the
  1549. option to insert near point, i.e., 1, 2, 3, 4, or nil if no such option
  1550. can be inserted. If REQUESTED is non-nil, it is the only possible value
  1551. to return except nil. If REQUESTED is nil, return level for the nearest
  1552. option kind, i.e., the highest number possible.
  1553. If the result is 2, point is at the beginning of the class after the
  1554. class definition. If the result is 3 or 4, point is at the beginning of
  1555. the rule/subrule after the init action. Otherwise, the point position
  1556. is undefined."
  1557. (widen)
  1558. (if (eq requested 1)
  1559. 1
  1560. (antlr-with-syntax-table antlr-action-syntax-table
  1561. (antlr-invalidate-context-cache)
  1562. (let* ((orig (point))
  1563. (outsidep (antlr-outside-rule-p))
  1564. bor depth)
  1565. (if (eq (char-after) ?\{) (antlr-skip-sexps 1))
  1566. (setq bor (point)) ; beginning of rule (after init action)
  1567. (cond ((eq requested 2) ; grammar options required?
  1568. (let (boc) ; beginning of class
  1569. (goto-char (point-min))
  1570. (while (and (<= (point) bor)
  1571. (antlr-re-search-forward antlr-class-header-regexp
  1572. nil))
  1573. (if (<= (match-beginning 0) bor)
  1574. (setq boc (match-end 0))))
  1575. (when boc
  1576. (goto-char boc)
  1577. 2)))
  1578. ((save-excursion ; in region of file options?
  1579. (goto-char (point-min))
  1580. (antlr-skip-file-prelude t) ; ws/comment after: OK
  1581. (< orig (point)))
  1582. (and (null requested) 1))
  1583. (outsidep ; outside rule not OK
  1584. nil)
  1585. ((looking-at antlr-class-header-regexp) ; rule = class def?
  1586. (goto-char (match-end 0))
  1587. (and (null requested) 2))
  1588. ((eq requested 3) ; rule options required?
  1589. (goto-char bor)
  1590. 3)
  1591. ((setq depth (antlr-syntactic-grammar-depth orig bor))
  1592. (if (> depth 0) ; move out of actions
  1593. (goto-char (scan-lists (point) -1 depth)))
  1594. (set-syntax-table antlr-mode-syntax-table)
  1595. (antlr-invalidate-context-cache)
  1596. (if (eq (antlr-syntactic-context) 0) ; not in subrule?
  1597. (unless (eq requested 4)
  1598. (goto-char bor)
  1599. 3)
  1600. (goto-char (1+ (scan-lists (point) -1 1)))
  1601. 4)))))))
  1602. (defun antlr-option-location (orig min-vis max-vis min-area max-area withp)
  1603. "Return location for the options area.
  1604. ORIG is the original position of `point', MIN-VIS is `point-min' and
  1605. MAX-VIS is `point-max'. If WITHP is non-nil, there exists an option
  1606. specification and it starts after the brace at MIN-AREA and stops at
  1607. MAX-AREA. If WITHP is nil, there is no area and the region where it
  1608. could be inserted starts at MIN-AREA and stops at MAX-AREA.
  1609. The result has the form (AREA . PLACE). AREA is (MIN-AREA . MAX-AREA)
  1610. if WITHP is non-nil, and nil otherwise. PLACE is nil if the area is
  1611. invisible, (ORIG) if ORIG is inside the area, (MIN-AREA . beginning) for
  1612. a visible start position and (MAX-AREA . end) for a visible end position
  1613. where the beginning is preferred if WITHP is nil and the end if WITHP is
  1614. non-nil."
  1615. (cons (and withp (cons min-area max-area))
  1616. (cond ((and (<= min-area orig) (<= orig max-area)
  1617. (save-excursion
  1618. (goto-char orig)
  1619. (not (memq (antlr-syntactic-context)
  1620. '(comment block-comment)))))
  1621. ;; point in options area and not in comment
  1622. (list orig))
  1623. ((and (null withp) (<= min-vis min-area) (<= min-area max-vis))
  1624. ;; use start of options area (only if not `withp')
  1625. (cons min-area 'beginning))
  1626. ((and (<= min-vis max-area) (<= max-area max-vis))
  1627. ;; use end of options area
  1628. (cons max-area 'end))
  1629. ((and withp (<= min-vis min-area) (<= min-area max-vis))
  1630. ;; use start of options area (only if `withp')
  1631. (cons min-area 'beginning)))))
  1632. (defun antlr-syntactic-grammar-depth (pos beg)
  1633. "Return syntactic context depth at POS.
  1634. Move to POS and from there on to the beginning of the string or comment
  1635. if POS is inside such a construct. Then, return the syntactic context
  1636. depth at point if the point position is smaller than BEG.
  1637. WARNING: this may alter `match-data'."
  1638. (goto-char pos)
  1639. (let ((context (or (antlr-syntactic-context) 0)))
  1640. (while (and context (not (integerp context)))
  1641. (cond ((eq context 'string)
  1642. (setq context
  1643. (and (search-backward "\"" nil t)
  1644. (>= (point) beg)
  1645. (or (antlr-syntactic-context) 0))))
  1646. ((memq context '(comment block-comment))
  1647. (setq context
  1648. (and (re-search-backward "/[/*]" nil t)
  1649. (>= (point) beg)
  1650. (or (antlr-syntactic-context) 0))))))
  1651. context))
  1652. ;;;===========================================================================
  1653. ;;; Insert options: do the insertion
  1654. ;;;===========================================================================
  1655. (defun antlr-insert-option-do (level option old area pos)
  1656. "Insert option into buffer at position POS.
  1657. Insert option of level LEVEL and name OPTION. If OLD is non-nil, an
  1658. options area is already exists. If OLD looks like \(BEG . END), the
  1659. option already exists. Then, BEG is the start position of the option
  1660. value, the position of the `=' or nil, and END is the end position of
  1661. the option value or nil.
  1662. If the original point position was outside an options area, AREA is nil.
  1663. Otherwise, and if an option specification already exists, AREA is a cons
  1664. cell where the two values determine the area inside the braces."
  1665. (let* ((spec (cdr (assoc option (elt antlr-options-alists (1- level)))))
  1666. (value (antlr-option-spec level option (cdr spec) (consp old))))
  1667. (if (fboundp (car spec)) (funcall (car spec) 'before-input option))
  1668. ;; set mark (unless point was inside options area before)
  1669. (if (cond (area (eq antlr-options-push-mark t))
  1670. ((numberp antlr-options-push-mark)
  1671. (> (count-lines (min (point) pos) (max (point) pos))
  1672. antlr-options-push-mark))
  1673. (antlr-options-push-mark))
  1674. (push-mark))
  1675. ;; read option value -----------------------------------------------------
  1676. (goto-char pos)
  1677. (if (null value)
  1678. ;; no option specification found
  1679. (if (y-or-n-p (format "Insert unknown %s option %s? "
  1680. (elt antlr-options-headings (1- level))
  1681. option))
  1682. (message "Insert value for %s option %s"
  1683. (elt antlr-options-headings (1- level))
  1684. option)
  1685. (error "Didn't insert unknown %s option %s"
  1686. (elt antlr-options-headings (1- level))
  1687. option))
  1688. ;; option specification found
  1689. (setq value (cdr value))
  1690. (if (car value)
  1691. (let ((initial (and (consp old) (cdr old)
  1692. (buffer-substring (car old) (cdr old)))))
  1693. (setq value (apply (car value)
  1694. (and initial
  1695. (if (eq (aref initial 0) ?\")
  1696. (read initial)
  1697. initial))
  1698. (cdr value))))
  1699. (message "%s" (or (cadr value) ""))
  1700. (setq value nil)))
  1701. ;; insert value ----------------------------------------------------------
  1702. (if (consp old)
  1703. (antlr-insert-option-existing old value)
  1704. (if (consp area)
  1705. ;; Move outside string/comment if point is inside option spec
  1706. (antlr-syntactic-grammar-depth (point) (car area)))
  1707. (antlr-insert-option-space area old)
  1708. (or old (antlr-insert-option-area level))
  1709. (insert option " = ;")
  1710. (backward-char)
  1711. (if value (insert value)))
  1712. ;; final -----------------------------------------------------------------
  1713. (if (fboundp (car spec)) (funcall (car spec) 'after-insertion option))))
  1714. (defun antlr-option-spec (level option specs existsp)
  1715. "Return version correct option value specification.
  1716. Return specification for option OPTION of kind level LEVEL. SPECS
  1717. should correspond to the VALUE-SPEC... in `antlr-option-alists'.
  1718. EXISTSP determines whether the option already exists."
  1719. (let (value)
  1720. (while (and specs (>= antlr-tool-version (caar specs)))
  1721. (setq value (pop specs)))
  1722. (cond (value) ; found correct spec
  1723. ((null specs) nil) ; didn't find any specs
  1724. (existsp (car specs)) ; wrong version, but already present
  1725. ((y-or-n-p (format "Insert v%s %s option %s in v%s? "
  1726. (antlr-version-string (caar specs))
  1727. (elt antlr-options-headings (1- level))
  1728. option
  1729. (antlr-version-string antlr-tool-version)))
  1730. (car specs))
  1731. (t
  1732. (error "Didn't insert v%s %s option %s in v%s"
  1733. (antlr-version-string (caar specs))
  1734. (elt antlr-options-headings (1- level))
  1735. option
  1736. (antlr-version-string antlr-tool-version))))))
  1737. (defun antlr-version-string (version)
  1738. "Format the Antlr version number VERSION, see `antlr-tool-version'."
  1739. (let ((version100 (/ version 100)))
  1740. (format "%d.%d.%d"
  1741. (/ version100 100) (mod version100 100) (mod version 100))))
  1742. ;;;===========================================================================
  1743. ;;; Insert options: the details (used by `antlr-insert-option-do')
  1744. ;;;===========================================================================
  1745. (defun antlr-insert-option-existing (old value)
  1746. "Insert option value VALUE at point for existing option.
  1747. For OLD, see `antlr-insert-option-do'."
  1748. ;; no = => insert =
  1749. (unless (car old) (insert antlr-options-assign-string))
  1750. ;; with user input => insert if necessary
  1751. (when value
  1752. (if (cdr old) ; with value
  1753. (if (string-equal value (buffer-substring (car old) (cdr old)))
  1754. (goto-char (cdr old))
  1755. (delete-region (car old) (cdr old))
  1756. (insert value))
  1757. (insert value)))
  1758. (unless (looking-at "\\([^\n=;{}/'\"]\\|'\\([^\n'\\]\\|\\\\.\\)*'\\|\"\\([^\n\"\\]\\|\\\\.\\)*\"\\)*;")
  1759. ;; stuff (no =, {, } or /) at point is not followed by ";"
  1760. (insert ";")
  1761. (backward-char)))
  1762. (defun antlr-insert-option-space (area old)
  1763. "Find appropriate place to insert option, insert newlines/spaces.
  1764. For AREA and OLD, see `antlr-insert-option-do'."
  1765. (let ((orig (point))
  1766. (open t))
  1767. (skip-chars-backward " \t")
  1768. (unless (bolp)
  1769. (let ((before (char-after (1- (point)))))
  1770. (goto-char orig)
  1771. (and old ; with existing options area
  1772. (consp area) ; if point inside existing area
  1773. (not (eq before ?\;)) ; if not at beginning of option
  1774. ; => skip to end of option
  1775. (if (and (search-forward ";" (cdr area) t)
  1776. (let ((context (antlr-syntactic-context)))
  1777. (or (null context) (numberp context))))
  1778. (setq orig (point))
  1779. (goto-char orig)))
  1780. (skip-chars-forward " \t")
  1781. (if (looking-at "$\\|//")
  1782. ;; just comment after point => skip (+ lines w/ same col comment)
  1783. (let ((same (if (> (match-end 0) (match-beginning 0))
  1784. (current-column))))
  1785. (beginning-of-line 2)
  1786. (or (bolp) (insert "\n"))
  1787. (when (and same (null area)) ; or (consp area)?
  1788. (while (and (looking-at "[ \t]*\\(//\\)")
  1789. (goto-char (match-beginning 1))
  1790. (= (current-column) same))
  1791. (beginning-of-line 2)
  1792. (or (bolp) (insert "\n")))))
  1793. (goto-char orig)
  1794. (if (null old)
  1795. (progn (insert "\n") (antlr-indent-line))
  1796. (unless (eq (char-after (1- (point))) ?\ )
  1797. (insert " "))
  1798. (unless (eq (char-after (point)) ?\ )
  1799. (insert " ")
  1800. (backward-char))
  1801. (setq open nil)))))
  1802. (when open
  1803. (beginning-of-line 1)
  1804. (insert "\n")
  1805. (backward-char)
  1806. (antlr-indent-line))))
  1807. (defun antlr-insert-option-area (level)
  1808. "Insert new options area for options of level LEVEL.
  1809. Used by `antlr-insert-option-do'."
  1810. (insert "options {\n\n}")
  1811. (when (and antlr-options-auto-colon
  1812. (memq level '(3 4))
  1813. (save-excursion
  1814. (antlr-c-forward-sws)
  1815. (if (eq (char-after (point)) ?\{) (antlr-skip-sexps 1))
  1816. (not (eq (char-after (point)) ?\:))))
  1817. (insert "\n:")
  1818. (antlr-indent-line)
  1819. (end-of-line 0))
  1820. (backward-char 1)
  1821. (antlr-indent-line)
  1822. (beginning-of-line 0)
  1823. (antlr-indent-line))
  1824. ;;;===========================================================================
  1825. ;;; Insert options: in `antlr-options-alists'
  1826. ;;;===========================================================================
  1827. (defun antlr-read-value (initial-contents prompt
  1828. &optional as-string table table-x)
  1829. "Read a string from the minibuffer, possibly with completion.
  1830. If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
  1831. PROMPT is a string to prompt with, normally it ends in a colon and a
  1832. space. If AS-STRING is t or is a member \(comparison done with `eq') of
  1833. `antlr-options-style', return printed representation of the user input,
  1834. otherwise return the user input directly.
  1835. If TABLE or TABLE-X is non-nil, read with completion. The completion
  1836. table is the resulting alist of TABLE-X concatenated with TABLE where
  1837. TABLE can also be a function evaluation to an alist.
  1838. Used inside `antlr-options-alists'."
  1839. (let* ((completion-ignore-case t) ; dynamic
  1840. (table0 (and (or table table-x)
  1841. (append table-x
  1842. (if (functionp table) (funcall table) table))))
  1843. (input (if table0
  1844. (completing-read prompt table0 nil nil initial-contents)
  1845. (read-from-minibuffer prompt initial-contents))))
  1846. (if (and as-string
  1847. (or (eq as-string t)
  1848. (cdr (assq as-string antlr-options-style))))
  1849. (format "%S" input)
  1850. input)))
  1851. (defun antlr-read-boolean (initial-contents prompt &optional table)
  1852. "Read a boolean value from the minibuffer, with completion.
  1853. If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
  1854. PROMPT is a string to prompt with, normally it ends in a question mark
  1855. and a space. \"(true or false) \" is appended if TABLE is nil.
  1856. Read with completion over \"true\", \"false\" and the keys in TABLE, see
  1857. also `antlr-read-value'.
  1858. Used inside `antlr-options-alists'."
  1859. (antlr-read-value initial-contents
  1860. (if table prompt (concat prompt "(true or false) "))
  1861. nil
  1862. table '(("false") ("true"))))
  1863. (defun antlr-language-option-extra (phase &rest _dummies)
  1864. ;; checkdoc-params: (dummies)
  1865. "Change language according to the new value of the \"language\" option.
  1866. Call `antlr-mode' if the new language would be different from the value
  1867. of `antlr-language', keeping the value of variable `font-lock-mode'.
  1868. Called in PHASE `after-insertion', see `antlr-options-alists'."
  1869. (when (eq phase 'after-insertion)
  1870. (let ((new-language (antlr-language-option t)))
  1871. (or (null new-language)
  1872. (eq new-language antlr-language)
  1873. (let ((font-lock (and (boundp 'font-lock-mode) font-lock-mode)))
  1874. (if font-lock (font-lock-mode 0))
  1875. (antlr-mode)
  1876. (and font-lock (null font-lock-mode) (font-lock-mode 1)))))))
  1877. (defun antlr-c++-mode-extra (phase option &rest _dummies)
  1878. ;; checkdoc-params: (option dummies)
  1879. "Warn if C++ option is used with the wrong language.
  1880. Ask user \(\"y or n\"), if a C++ only option is going to be inserted but
  1881. `antlr-language' has not the value `c++-mode'.
  1882. Called in PHASE `before-input', see `antlr-options-alists'."
  1883. (and (eq phase 'before-input)
  1884. (not (eq antlr-language 'c++-mode))
  1885. (not (y-or-n-p (format "Insert C++ %s option? " option)))
  1886. (error "Didn't insert C++ %s option with language %s"
  1887. option (cadr (assq antlr-language antlr-language-alist)))))
  1888. ;;;===========================================================================
  1889. ;;; Compute dependencies
  1890. ;;;===========================================================================
  1891. (defun antlr-file-dependencies ()
  1892. "Return dependencies for grammar in current buffer.
  1893. The result looks like \(FILE \(CLASSES . SUPERS) VOCABS . LANGUAGE)
  1894. where CLASSES = ((CLASS . CLASS-EVOCAB) ...),
  1895. SUPERS = ((SUPER . USE-EVOCAB-P) ...), and
  1896. VOCABS = ((EVOCAB ...) . (IVOCAB ...))
  1897. FILE is the current buffer's file-name without directory part and
  1898. LANGUAGE is the value of `antlr-language' in the current buffer. Each
  1899. EVOCAB is an export vocabulary and each IVOCAB is an import vocabulary.
  1900. Each CLASS is a grammar class with its export vocabulary CLASS-EVOCAB.
  1901. Each SUPER is a super-grammar class where USE-EVOCAB-P indicates whether
  1902. its export vocabulary is used as an import vocabulary."
  1903. (unless buffer-file-name
  1904. (error "Grammar buffer does not visit a file"))
  1905. (let (classes export-vocabs import-vocabs superclasses default-vocab)
  1906. (antlr-with-syntax-table antlr-action-syntax-table
  1907. (goto-char (point-min))
  1908. (while (antlr-re-search-forward antlr-class-header-regexp nil)
  1909. ;; parse class definition --------------------------------------------
  1910. (let* ((class (match-string 2))
  1911. (sclass (match-string 4))
  1912. ;; export vocab defaults to class name (first grammar in file)
  1913. ;; or to the export vocab of the first grammar in file:
  1914. (evocab (or default-vocab class))
  1915. (ivocab nil))
  1916. (goto-char (match-end 0))
  1917. (antlr-c-forward-sws)
  1918. (while (looking-at "options\\>\\|\\(tokens\\)\\>")
  1919. (if (match-beginning 1)
  1920. (antlr-skip-sexps 2)
  1921. (goto-char (match-end 0))
  1922. (antlr-c-forward-sws)
  1923. ;; parse grammar option sections -------------------------------
  1924. (when (eq (char-after (point)) ?\{)
  1925. (let* ((beg (1+ (point)))
  1926. (end (1- (antlr-skip-sexps 1)))
  1927. (cont (point)))
  1928. (goto-char beg)
  1929. (if (re-search-forward "\\<exportVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t)
  1930. (setq evocab (match-string 1)))
  1931. (goto-char beg)
  1932. (if (re-search-forward "\\<importVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t)
  1933. (setq ivocab (match-string 1)))
  1934. (goto-char cont)))))
  1935. (unless (member sclass '("Parser" "Lexer" "TreeParser"))
  1936. (let ((super (assoc sclass superclasses)))
  1937. (if super
  1938. (or ivocab (setcdr super t))
  1939. (push (cons sclass (null ivocab)) superclasses))))
  1940. ;; remember class with export vocabulary:
  1941. (push (cons class evocab) classes)
  1942. ;; default export vocab is export vocab of first grammar in file:
  1943. (or default-vocab (setq default-vocab evocab))
  1944. (or (member evocab export-vocabs) (push evocab export-vocabs))
  1945. (or (null ivocab)
  1946. (member ivocab import-vocabs) (push ivocab import-vocabs)))))
  1947. (if classes
  1948. (list* (file-name-nondirectory buffer-file-name)
  1949. (cons (nreverse classes) (nreverse superclasses))
  1950. (cons (nreverse export-vocabs) (nreverse import-vocabs))
  1951. antlr-language))))
  1952. (defun antlr-directory-dependencies (dirname)
  1953. "Return dependencies for all grammar files in directory DIRNAME.
  1954. The result looks like \((CLASS-SPEC ...) . \(FILE-DEP ...))
  1955. where CLASS-SPEC = (CLASS (FILE . EVOCAB) ...).
  1956. FILE-DEP are the dependencies for each grammar file in DIRNAME, see
  1957. `antlr-file-dependencies'. For each grammar class CLASS, FILE is a
  1958. grammar file in which CLASS is defined and EVOCAB is the name of the
  1959. export vocabulary specified in that file."
  1960. (let ((grammar (directory-files dirname t "\\.g\\'")))
  1961. (when grammar
  1962. (let ((antlr-imenu-name nil) ; dynamic-let: no imenu
  1963. (expanded-regexp
  1964. (concat (format (regexp-quote
  1965. (cadr antlr-special-file-formats))
  1966. ".+")
  1967. "\\'"))
  1968. classes dependencies)
  1969. (with-temp-buffer
  1970. (dolist (file grammar)
  1971. (when (and (file-regular-p file)
  1972. (null (string-match expanded-regexp file)))
  1973. (insert-file-contents file t nil nil t)
  1974. (normal-mode t) ; necessary for major-mode, syntax
  1975. ; table and `antlr-language'
  1976. (when (derived-mode-p 'antlr-mode)
  1977. (let* ((file-deps (antlr-file-dependencies))
  1978. (file (car file-deps)))
  1979. (when file-deps
  1980. (dolist (class-def (caadr file-deps))
  1981. (let ((file-evocab (cons file (cdr class-def)))
  1982. (class-spec (assoc (car class-def) classes)))
  1983. (if class-spec
  1984. (nconc (cdr class-spec) (list file-evocab))
  1985. (push (list (car class-def) file-evocab)
  1986. classes))))
  1987. (push file-deps dependencies)))))))
  1988. (cons (nreverse classes) (nreverse dependencies))))))
  1989. ;;;===========================================================================
  1990. ;;; Compilation: run ANTLR tool
  1991. ;;;===========================================================================
  1992. (defun antlr-superclasses-glibs (supers classes)
  1993. "Compute the grammar lib option for the super grammars SUPERS.
  1994. Look in CLASSES for the right grammar lib files for SUPERS. SUPERS is
  1995. part SUPER in the result of `antlr-file-dependencies'. CLASSES is the
  1996. part \(CLASS-SPEC ...) in the result of `antlr-directory-dependencies'.
  1997. The result looks like \(OPTION WITH-UNKNOWN GLIB ...). OPTION is the
  1998. complete \"-glib\" option. WITH-UNKNOWN is t if there is none or more
  1999. than one grammar file for at least one super grammar.
  2000. Each GLIB looks like \(GRAMMAR-FILE . EVOCAB). GRAMMAR-FILE is a file
  2001. in which a super-grammar is defined. EVOCAB is the value of the export
  2002. vocabulary of the super-grammar or nil if it is not needed."
  2003. ;; If the superclass is defined in the same file, that file will be included
  2004. ;; with -glib again. This will lead to a redefinition. But defining a
  2005. ;; analyzer of the same class twice in a file will lead to an error anyway...
  2006. (let (glibs unknown)
  2007. (while supers
  2008. (let* ((super (pop supers))
  2009. (sup-files (cdr (assoc (car super) classes)))
  2010. (file (and sup-files (null (cdr sup-files)) (car sup-files))))
  2011. (or file (setq unknown t)) ; not exactly one file
  2012. (push (cons (or (car file)
  2013. (format (car antlr-unknown-file-formats)
  2014. (car super)))
  2015. (and (cdr super)
  2016. (or (cdr file)
  2017. (format (cadr antlr-unknown-file-formats)
  2018. (car super)))))
  2019. glibs)))
  2020. (cons (if glibs (concat " -glib " (mapconcat 'car glibs ";")) "")
  2021. (cons unknown glibs))))
  2022. (defun antlr-run-tool (command file &optional saved)
  2023. "Run Antlr took COMMAND on grammar FILE.
  2024. When called interactively, COMMAND is read from the minibuffer and
  2025. defaults to `antlr-tool-command' with a computed \"-glib\" option if
  2026. necessary.
  2027. Save all buffers first unless optional value SAVED is non-nil. When
  2028. called interactively, the buffers are always saved, see also variable
  2029. `antlr-ask-about-save'."
  2030. (interactive (antlr-run-tool-interactive))
  2031. (or saved (save-some-buffers (not antlr-ask-about-save)))
  2032. (let ((default-directory (file-name-directory file)))
  2033. (compilation-start (concat command " " (file-name-nondirectory file))
  2034. nil (lambda (_mode-name) "*Antlr-Run*"))))
  2035. (defun antlr-run-tool-interactive ()
  2036. ;; code in `interactive' is not compiled
  2037. "Interactive specification for `antlr-run-tool'.
  2038. Use prefix argument ARG to return \(COMMAND FILE SAVED)."
  2039. (let* ((supers (cdadr (save-excursion
  2040. (save-restriction
  2041. (widen)
  2042. (antlr-file-dependencies)))))
  2043. (glibs ""))
  2044. (when supers
  2045. (save-some-buffers (not antlr-ask-about-save) nil)
  2046. (setq glibs (car (antlr-superclasses-glibs
  2047. supers
  2048. (car (antlr-directory-dependencies
  2049. (antlr-default-directory)))))))
  2050. (list (antlr-read-shell-command "Run Antlr on current file with: "
  2051. (concat antlr-tool-command glibs " "))
  2052. buffer-file-name
  2053. supers)))
  2054. ;;;===========================================================================
  2055. ;;; Makefile creation
  2056. ;;;===========================================================================
  2057. (defun antlr-makefile-insert-variable (number pre post)
  2058. "Insert Makefile variable numbered NUMBER according to specification.
  2059. Also insert strings PRE and POST before and after the variable."
  2060. (let ((spec (cadr antlr-makefile-specification)))
  2061. (when spec
  2062. (insert pre
  2063. (if number (format (cadr spec) number) (car spec))
  2064. post))))
  2065. (defun antlr-insert-makefile-rules (&optional in-makefile)
  2066. "Insert Makefile rules in the current buffer at point.
  2067. IN-MAKEFILE is non-nil, if the current buffer is the Makefile. See
  2068. command `antlr-show-makefile-rules' for detail."
  2069. (let* ((dirname (antlr-default-directory))
  2070. (deps0 (antlr-directory-dependencies dirname))
  2071. (classes (car deps0)) ; CLASS -> (FILE . EVOCAB) ...
  2072. (deps (cdr deps0)) ; FILE -> (c . s) (ev . iv) . LANGUAGE
  2073. (with-error nil)
  2074. (gen-sep (or (caddr (cadr antlr-makefile-specification)) " "))
  2075. (n (and (cdr deps) (cadr antlr-makefile-specification) 0)))
  2076. (or in-makefile (set-buffer standard-output))
  2077. (dolist (dep deps)
  2078. (let ((supers (cdadr dep))
  2079. (lang (cdr (assoc (cdddr dep) antlr-file-formats-alist))))
  2080. (if n (incf n))
  2081. (antlr-makefile-insert-variable n "" " =")
  2082. (if supers
  2083. (insert " "
  2084. (format (cadr antlr-special-file-formats)
  2085. (file-name-sans-extension (car dep)))))
  2086. (dolist (class-def (caadr dep))
  2087. (let ((sep gen-sep))
  2088. (dolist (class-file (cadr lang))
  2089. (insert sep (format class-file (car class-def)))
  2090. (setq sep " "))))
  2091. (dolist (evocab (caaddr dep))
  2092. (let ((sep gen-sep))
  2093. (dolist (vocab-file (cons (car antlr-special-file-formats)
  2094. (car lang)))
  2095. (insert sep (format vocab-file evocab))
  2096. (setq sep " "))))
  2097. (antlr-makefile-insert-variable n "\n$(" ")")
  2098. (insert ": " (car dep))
  2099. (dolist (ivocab (cdaddr dep))
  2100. (insert " " (format (car antlr-special-file-formats) ivocab)))
  2101. (let ((glibs (antlr-superclasses-glibs supers classes)))
  2102. (if (cadr glibs) (setq with-error t))
  2103. (dolist (super (cddr glibs))
  2104. (insert " " (car super))
  2105. (if (cdr super)
  2106. (insert " " (format (car antlr-special-file-formats)
  2107. (cdr super)))))
  2108. (insert "\n\t"
  2109. (caddr antlr-makefile-specification)
  2110. (car glibs)
  2111. " $<\n"
  2112. (car antlr-makefile-specification)))))
  2113. (if n
  2114. (let ((i 0))
  2115. (antlr-makefile-insert-variable nil "" " =")
  2116. (while (<= (incf i) n)
  2117. (antlr-makefile-insert-variable i " $(" ")"))
  2118. (insert "\n" (car antlr-makefile-specification))))
  2119. (if (string-equal (car antlr-makefile-specification) "\n")
  2120. (backward-delete-char 1))
  2121. (when with-error
  2122. (goto-char (point-min))
  2123. (insert antlr-help-unknown-file-text))
  2124. (unless in-makefile
  2125. (copy-region-as-kill (point-min) (point-max))
  2126. (goto-char (point-min))
  2127. (insert (format antlr-help-rules-intro dirname)))))
  2128. ;;;###autoload
  2129. (defun antlr-show-makefile-rules ()
  2130. "Show Makefile rules for all grammar files in the current directory.
  2131. If the `major-mode' of the current buffer has the value `makefile-mode',
  2132. the rules are directory inserted at point. Otherwise, a *Help* buffer
  2133. is shown with the rules which are also put into the `kill-ring' for
  2134. \\[yank].
  2135. This command considers import/export vocabularies and grammar
  2136. inheritance and provides a value for the \"-glib\" option if necessary.
  2137. Customize variable `antlr-makefile-specification' for the appearance of
  2138. the rules.
  2139. If the file for a super-grammar cannot be determined, special file names
  2140. are used according to variable `antlr-unknown-file-formats' and a
  2141. commentary with value `antlr-help-unknown-file-text' is added. The
  2142. *Help* buffer always starts with the text in `antlr-help-rules-intro'."
  2143. (interactive)
  2144. (if (null (derived-mode-p 'makefile-mode))
  2145. (antlr-with-displaying-help-buffer 'antlr-insert-makefile-rules)
  2146. (push-mark)
  2147. (antlr-insert-makefile-rules t)))
  2148. ;;;===========================================================================
  2149. ;;; Indentation
  2150. ;;;===========================================================================
  2151. (defun antlr-indent-line ()
  2152. "Indent the current line as ANTLR grammar code.
  2153. The indentation of grammar lines are calculated by `c-basic-offset',
  2154. multiplied by:
  2155. - the level of the paren/brace/bracket depth,
  2156. - plus 0/2/1, depending on the position inside the rule: header, body,
  2157. exception part,
  2158. - minus 1 if `antlr-indent-item-regexp' matches the beginning of the
  2159. line starting from the first non-whitespace.
  2160. Lines inside block comments are indented by `c-indent-line' according to
  2161. `antlr-indent-comment'.
  2162. Lines in actions except top-level actions in a header part or an option
  2163. area are indented by `c-indent-line'.
  2164. Lines in header actions are indented at column 0 if `antlr-language'
  2165. equals to a key in `antlr-indent-at-bol-alist' and the line starting at
  2166. the first non-whitespace is matched by the corresponding value.
  2167. For the initialization of `c-basic-offset', see `antlr-indent-style' and,
  2168. to a lesser extent, `antlr-tab-offset-alist'."
  2169. (save-restriction
  2170. (let ((orig (point))
  2171. (min0 (point-min))
  2172. bol boi indent syntax cc-syntax)
  2173. (widen)
  2174. (beginning-of-line)
  2175. (setq bol (point))
  2176. (if (< bol min0)
  2177. (error "Beginning of current line not visible"))
  2178. (skip-chars-forward " \t")
  2179. (setq boi (point))
  2180. ;; check syntax at beginning of indentation ----------------------------
  2181. (antlr-with-syntax-table antlr-action-syntax-table
  2182. (antlr-invalidate-context-cache)
  2183. (setq syntax (antlr-syntactic-context))
  2184. (cond ((symbolp syntax)
  2185. (setq indent nil)) ; block-comments, strings, (comments)
  2186. ((progn
  2187. (antlr-next-rule -1 t)
  2188. (if (antlr-search-forward ":") (< boi (1- (point))) t))
  2189. (setq indent 0)) ; in rule header
  2190. ((if (antlr-search-forward ";") (< boi (point)) t)
  2191. (setq indent 2)) ; in rule body
  2192. (t
  2193. (forward-char)
  2194. (antlr-skip-exception-part nil)
  2195. (setq indent (if (> (point) boi) 1 0))))) ; in exception part?
  2196. ;; check whether to use indentation engine of cc-mode ------------------
  2197. (antlr-invalidate-context-cache)
  2198. (goto-char boi)
  2199. (when (and indent (> syntax 0))
  2200. (cond ((> syntax 1) ; block in action => use cc-mode
  2201. (setq indent nil))
  2202. ((and (= indent 0)
  2203. (assq antlr-language antlr-indent-at-bol-alist)
  2204. (looking-at (cdr (assq antlr-language
  2205. antlr-indent-at-bol-alist))))
  2206. (setq syntax 'bol))
  2207. ((setq cc-syntax (c-guess-basic-syntax))
  2208. (let ((cc cc-syntax) symbol)
  2209. (while (setq symbol (pop cc))
  2210. (when (cdr symbol)
  2211. (or (memq (car symbol)
  2212. antlr-disabling-cc-syntactic-symbols)
  2213. (setq indent nil))
  2214. (setq cc nil)))))))
  2215. ;;; ((= indent 1) ; exception part => use cc-mode
  2216. ;;; (setq indent nil))
  2217. ;;; ((save-restriction ; not in option part => cc-mode
  2218. ;;; (goto-char (scan-lists (point) -1 1))
  2219. ;;; (skip-chars-backward " \t\n")
  2220. ;;; (narrow-to-region (point-min) (point))
  2221. ;;; (not (re-search-backward "\\<options\\'" nil t)))
  2222. ;;; (setq indent nil)))))
  2223. ;; compute the corresponding indentation and indent --------------------
  2224. (if (null indent)
  2225. ;; Use the indentation engine of cc-mode
  2226. (progn
  2227. (goto-char orig)
  2228. (if (or (numberp syntax)
  2229. (if (eq syntax 'string) nil (eq antlr-indent-comment t)))
  2230. (c-indent-line cc-syntax)))
  2231. ;; do it ourselves
  2232. (goto-char boi)
  2233. (unless (symbolp syntax) ; direct indentation
  2234. ;;(antlr-invalidate-context-cache)
  2235. (incf indent (antlr-syntactic-context))
  2236. (and (> indent 0) (looking-at antlr-indent-item-regexp) (decf indent))
  2237. (setq indent (* indent c-basic-offset)))
  2238. ;; the usual major-mode indent stuff ---------------------------------
  2239. (setq orig (- (point-max) orig))
  2240. (unless (= (current-column) indent)
  2241. (delete-region bol boi)
  2242. (beginning-of-line)
  2243. (indent-to indent))
  2244. ;; If initial point was within line's indentation,
  2245. ;; position after the indentation. Else stay at same point in text.
  2246. (if (> (- (point-max) orig) (point))
  2247. (goto-char (- (point-max) orig)))))))
  2248. (defun antlr-indent-command (&optional arg)
  2249. "Indent the current line or insert tabs/spaces.
  2250. With optional prefix argument ARG or if the previous command was this
  2251. command, insert ARG tabs or spaces according to `indent-tabs-mode'.
  2252. Otherwise, indent the current line with `antlr-indent-line'."
  2253. (interactive "*P")
  2254. (if (or arg (eq last-command 'antlr-indent-command))
  2255. (insert-tab arg)
  2256. (let ((antlr-indent-comment (and antlr-indent-comment t))) ; dynamic
  2257. (antlr-indent-line))))
  2258. (defun antlr-electric-character (&optional arg)
  2259. "Insert the character you type and indent the current line.
  2260. Insert the character like `self-insert-command' and indent the current
  2261. line as `antlr-indent-command' does. Do not indent the line if
  2262. * this command is called with a prefix argument ARG,
  2263. * there are characters except whitespaces between point and the
  2264. beginning of the line, or
  2265. * point is not inside a normal grammar code, { and } are also OK in
  2266. actions.
  2267. This command is useful for a character which has some special meaning in
  2268. ANTLR's syntax and influences the auto indentation, see
  2269. `antlr-indent-item-regexp'."
  2270. (interactive "*P")
  2271. (if (or arg
  2272. (save-excursion (skip-chars-backward " \t") (not (bolp)))
  2273. (antlr-with-syntax-table antlr-action-syntax-table
  2274. (antlr-invalidate-context-cache)
  2275. (let ((context (antlr-syntactic-context)))
  2276. (not (and (numberp context)
  2277. (or (zerop context)
  2278. (memq last-command-event '(?\{ ?\}))))))))
  2279. (self-insert-command (prefix-numeric-value arg))
  2280. (self-insert-command (prefix-numeric-value arg))
  2281. (antlr-indent-line)))
  2282. ;;;===========================================================================
  2283. ;;; Mode entry
  2284. ;;;===========================================================================
  2285. (defun antlr-c-init-language-vars ()
  2286. "Like `c-init-language-vars-for' when using cc-mode before v5.29."
  2287. (let ((settings ; (cdr '(setq...)) will be optimized
  2288. (if (eq antlr-language 'c++-mode)
  2289. (cdr '(setq ;' from `c++-mode' v5.20, v5.28
  2290. c-keywords (c-identifier-re c-C++-keywords)
  2291. c-conditional-key c-C++-conditional-key
  2292. c-comment-start-regexp c-C++-comment-start-regexp
  2293. c-class-key c-C++-class-key
  2294. c-extra-toplevel-key c-C++-extra-toplevel-key
  2295. c-access-key c-C++-access-key
  2296. c-recognize-knr-p nil
  2297. c-bitfield-key c-C-bitfield-key ; v5.28
  2298. ))
  2299. (cdr '(setq ; from `java-mode' v5.20, v5.28
  2300. c-keywords (c-identifier-re c-Java-keywords)
  2301. c-conditional-key c-Java-conditional-key
  2302. c-comment-start-regexp c-Java-comment-start-regexp
  2303. c-class-key c-Java-class-key
  2304. c-method-key nil
  2305. c-baseclass-key nil
  2306. c-recognize-knr-p nil
  2307. c-access-key c-Java-access-key ; v5.20
  2308. c-inexpr-class-key c-Java-inexpr-class-key ; v5.28
  2309. )))))
  2310. (while settings
  2311. (when (boundp (car settings))
  2312. (ignore-errors
  2313. (set (car settings) (eval (cadr settings)))))
  2314. (setq settings (cddr settings)))))
  2315. (defun antlr-language-option (search)
  2316. "Find language in `antlr-language-alist' for language option.
  2317. If SEARCH is non-nil, find element for language option. Otherwise, find
  2318. the default language."
  2319. (let ((value
  2320. (and search
  2321. (save-excursion
  2322. (goto-char (point-min))
  2323. (re-search-forward (cdr antlr-language-limit-n-regexp)
  2324. (+ (point)
  2325. (car antlr-language-limit-n-regexp))
  2326. t))
  2327. (match-string 1)))
  2328. (seq antlr-language-alist)
  2329. r)
  2330. ;; Like (find VALUE antlr-language-alist :key 'cddr :test 'member)
  2331. (while seq
  2332. (setq r (pop seq))
  2333. (if (member value (cddr r))
  2334. (setq seq nil) ; stop
  2335. (setq r nil))) ; no result yet
  2336. (car r)))
  2337. ;;;###autoload
  2338. (define-derived-mode antlr-mode prog-mode
  2339. ;; FIXME: Since it uses cc-mode, it bumps into c-update-modeline's
  2340. ;; limitation to mode-name being a string.
  2341. ;; '("Antlr." (:eval (cadr (assq antlr-language antlr-language-alist))))
  2342. "Antlr"
  2343. "Major mode for editing ANTLR grammar files."
  2344. :abbrev-table antlr-mode-abbrev-table
  2345. (c-initialize-cc-mode) ; cc-mode is required
  2346. (unless (fboundp 'c-forward-sws) ; see above
  2347. (fset 'antlr-c-forward-sws 'c-forward-syntactic-ws))
  2348. ;; ANTLR specific ----------------------------------------------------------
  2349. (unless antlr-language
  2350. (set (make-local-variable 'antlr-language)
  2351. (or (antlr-language-option t) (antlr-language-option nil))))
  2352. (if (stringp (cadr (assq antlr-language antlr-language-alist)))
  2353. (setq mode-name
  2354. (concat "Antlr."
  2355. (cadr (assq antlr-language antlr-language-alist)))))
  2356. ;; indentation, for the C engine -------------------------------------------
  2357. (setq c-buffer-is-cc-mode antlr-language)
  2358. (cond ((fboundp 'c-init-language-vars-for) ; cc-mode 5.30.5+
  2359. (c-init-language-vars-for antlr-language))
  2360. ((fboundp 'c-init-c-language-vars) ; cc-mode 5.30 to 5.30.4
  2361. (c-init-c-language-vars) ; not perfect, but OK
  2362. (setq c-recognize-knr-p nil))
  2363. ((fboundp 'c-init-language-vars) ; cc-mode 5.29
  2364. (let ((init-fn 'c-init-language-vars))
  2365. (funcall init-fn))) ; is a function in v5.29
  2366. (t ; cc-mode upto 5.28
  2367. (antlr-c-init-language-vars))) ; do it myself
  2368. (c-basic-common-init antlr-language (or antlr-indent-style "gnu"))
  2369. (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
  2370. (set (make-local-variable 'outline-level) 'c-outline-level) ;TODO: define own
  2371. (set (make-local-variable 'indent-line-function) 'antlr-indent-line)
  2372. (set (make-local-variable 'indent-region-function) nil) ; too lazy
  2373. (setq comment-start "// "
  2374. comment-end ""
  2375. comment-start-skip "/\\*+ *\\|// *")
  2376. ;; various -----------------------------------------------------------------
  2377. (set (make-local-variable 'font-lock-defaults) antlr-font-lock-defaults)
  2378. (easy-menu-add antlr-mode-menu)
  2379. (set (make-local-variable 'imenu-create-index-function)
  2380. 'antlr-imenu-create-index-function)
  2381. (set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test
  2382. (and antlr-imenu-name ; there should be a global variable...
  2383. (fboundp 'imenu-add-to-menubar)
  2384. (imenu-add-to-menubar
  2385. (if (stringp antlr-imenu-name) antlr-imenu-name "Index")))
  2386. (antlr-set-tabs))
  2387. ;; A smarter version of `group-buffers-menu-by-mode-then-alphabetically' (in
  2388. ;; XEmacs) could use the following property. The header of the submenu would
  2389. ;; be "Antlr" instead of "Antlr.C++" or (not and!) "Antlr.Java".
  2390. (put 'antlr-mode 'mode-name "Antlr")
  2391. ;;;###autoload
  2392. (defun antlr-set-tabs ()
  2393. "Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'.
  2394. Used in `antlr-mode'. Also a useful function in `java-mode-hook'."
  2395. (if buffer-file-name
  2396. (let ((alist antlr-tab-offset-alist) elem)
  2397. (while alist
  2398. (setq elem (pop alist))
  2399. (and (or (null (car elem)) (eq (car elem) major-mode))
  2400. (or (null (cadr elem))
  2401. (string-match (cadr elem) buffer-file-name))
  2402. (setq tab-width (caddr elem)
  2403. indent-tabs-mode (cadddr elem)
  2404. alist nil))))))
  2405. (provide 'antlr-mode)
  2406. ;;; Local IspellPersDict: .ispell_antlr
  2407. ;;; antlr-mode.el ends here